nim 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +5 -0
- data/Gemfile +4 -0
- data/README.rdoc +18 -0
- data/Rakefile +2 -0
- data/bin/nim +17 -0
- data/lib/nim.rb +1 -0
- data/lib/nim/nim_core.rb +253 -0
- data/lib/nim/version.rb +3 -0
- data/nim.gemspec +21 -0
- metadata +55 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
= Nim
|
2
|
+
|
3
|
+
分成几摊的豆子,两个玩家轮流拣,一次可拿任意一摊里的至少一颗,拣掉最后一粒豆子的玩家判负。
|
4
|
+
|
5
|
+
You and Q take turns nim beans from distinct heaps,
|
6
|
+
On each turn, you must nim at least one bean, and may nim any number of beans provided they all come from the same heap.
|
7
|
+
|
8
|
+
Whom nim the last one bean were *lost*
|
9
|
+
|
10
|
+
== Playing
|
11
|
+
|
12
|
+
gem install nim
|
13
|
+
|
14
|
+
nim
|
15
|
+
|
16
|
+
== Authors
|
17
|
+
|
18
|
+
* {Takafan}[http://hululuu.com]
|
data/Rakefile
ADDED
data/bin/nim
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
lib_path = File.expand_path('../../lib', __FILE__)
|
4
|
+
$:.unshift(lib_path)
|
5
|
+
require 'nim'
|
6
|
+
require 'nim/version'
|
7
|
+
|
8
|
+
begin
|
9
|
+
raise Nim::VERSION if ['--version', '-v'].include? ARGV[0]
|
10
|
+
|
11
|
+
Nim::Nim.new
|
12
|
+
|
13
|
+
rescue Exception => e
|
14
|
+
print "#{e.class}: " unless e.class == RuntimeError
|
15
|
+
puts "#{e.message}"
|
16
|
+
exit 1
|
17
|
+
end
|
data/lib/nim.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'nim/nim_core'
|
data/lib/nim/nim_core.rb
ADDED
@@ -0,0 +1,253 @@
|
|
1
|
+
module Nim
|
2
|
+
class Nim
|
3
|
+
|
4
|
+
#游戏规则:分成几摊的豆子,两个玩家轮流拣,一次可拿任意一摊里的至少一颗,拣掉最后一粒豆子的玩家判负。
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
puts %q{
|
8
|
+
You and Q take turns nim beans from distinct heaps,
|
9
|
+
On each turn, you must nim at least one bean, and may nim any number of beans provided they all come from the same heap.
|
10
|
+
|
11
|
+
Whom nim the last one bean were *lost*
|
12
|
+
|
13
|
+
}
|
14
|
+
|
15
|
+
a = [1,3,5,7]
|
16
|
+
b = [3,4,5,6]
|
17
|
+
puts "heap 1 (#{a.inject{|x, sum| x + sum}} beans)"
|
18
|
+
draw0(a)
|
19
|
+
puts "heap 2 (#{b.inject{|x, sum| x + sum}} beans)"
|
20
|
+
draw0(b)
|
21
|
+
|
22
|
+
loop do
|
23
|
+
print 'choose the heap 1/2: '
|
24
|
+
heap = gets.to_i
|
25
|
+
if [1,2].include?(heap)
|
26
|
+
@mat = heap == 1 ? a : b
|
27
|
+
break
|
28
|
+
end
|
29
|
+
puts %q{ inputs: 1 or 2
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
init_unsafe_positions
|
34
|
+
|
35
|
+
hand = 1
|
36
|
+
|
37
|
+
loop do
|
38
|
+
print 'nim first or second 1/2: '
|
39
|
+
g = gets
|
40
|
+
if g.strip == "unsafe"
|
41
|
+
@unsafe_positions.each{|x| puts x.join ' '}
|
42
|
+
draw_mat
|
43
|
+
else
|
44
|
+
hand = g.to_i
|
45
|
+
break if [1,2].include?(hand)
|
46
|
+
puts %q{ inputs: 1 or 2
|
47
|
+
}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
puts
|
51
|
+
|
52
|
+
ai_pick if hand == 2
|
53
|
+
|
54
|
+
loop do
|
55
|
+
|
56
|
+
loop do
|
57
|
+
print 'you nim: '
|
58
|
+
args = gets.split ' '
|
59
|
+
|
60
|
+
if args.size == 1
|
61
|
+
iarg0 = args[0].to_i
|
62
|
+
|
63
|
+
if iarg0 > 0 and iarg0 < 10 #4
|
64
|
+
pos = iarg0 - 1
|
65
|
+
if (0...@mat.size).include?(pos) and @mat[pos] > 0
|
66
|
+
pick(pos)
|
67
|
+
break
|
68
|
+
end
|
69
|
+
elsif iarg0 > 10 and iarg0 < 100 #45
|
70
|
+
pos = iarg0 / 10 - 1
|
71
|
+
num = iarg0 % 10
|
72
|
+
if (0...@mat.size).include?(pos) and num > 0 and @mat[pos] >= num
|
73
|
+
pick(pos, num)
|
74
|
+
break
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
elsif args.size == 2
|
79
|
+
iarg0 = args[0].to_i
|
80
|
+
iarg1 = args[1].to_i
|
81
|
+
|
82
|
+
if iarg0 > 0 and iarg0 < 10 and iarg1 > 0 and iarg1 < 10 #4 5
|
83
|
+
pos = iarg0 -1
|
84
|
+
num = iarg1
|
85
|
+
if (0...@mat.size).include?(pos) and @mat[pos] >= num
|
86
|
+
pick(pos, num)
|
87
|
+
break
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
puts %q{ invalid inputs.
|
92
|
+
nim least 1 beans from a line.
|
93
|
+
nim 5 beans from line 4, inputs: 45 or 4 5
|
94
|
+
nim all beans from line 4, inputs: 4
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
if @mat == [0,0,0,0]
|
99
|
+
puts 'you *LOSE* :('
|
100
|
+
break
|
101
|
+
end
|
102
|
+
|
103
|
+
ai_pick
|
104
|
+
if @mat == [0,0,0,0]
|
105
|
+
puts 'you *WIN* :)'
|
106
|
+
break
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
def ai_pick
|
114
|
+
#行动集
|
115
|
+
actions = Hash.new
|
116
|
+
|
117
|
+
@unsafe_positions.each do |unsafe|
|
118
|
+
dup = unsafe.dup
|
119
|
+
|
120
|
+
scoped_index = 0
|
121
|
+
scoped_value = 0
|
122
|
+
|
123
|
+
@mat.each_with_index do |x, i|
|
124
|
+
idx = dup.index(x)
|
125
|
+
if idx
|
126
|
+
dup.delete_at(idx)
|
127
|
+
else
|
128
|
+
#暂记不相等的value和它的下标
|
129
|
+
scoped_index = i
|
130
|
+
scoped_value = x
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
if dup.size == 1 and scoped_value > dup.first
|
135
|
+
actions[scoped_index] = scoped_value - dup.shift
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
#拣取的下标和数量
|
140
|
+
pos = num = 0
|
141
|
+
|
142
|
+
if actions.size > 0
|
143
|
+
#随机挑一个候选执行
|
144
|
+
keys = actions.keys
|
145
|
+
pos = keys[Random.new.rand(0...keys.size)]
|
146
|
+
num = actions[pos]
|
147
|
+
else
|
148
|
+
#值不为0的下标集
|
149
|
+
pos_ex = []
|
150
|
+
@mat.each_with_index do |x, i|
|
151
|
+
pos_ex << i if x > 0
|
152
|
+
end
|
153
|
+
|
154
|
+
#从不为0的堆中随机找一堆,随机拣取n颗
|
155
|
+
pos = pos_ex[Random.new.rand(0...pos_ex.size)]
|
156
|
+
num = Random.new.rand(1..@mat[pos])
|
157
|
+
end
|
158
|
+
|
159
|
+
puts "Q nim: #{(pos + 1) * 10 + num}"
|
160
|
+
pick(pos, num)
|
161
|
+
end
|
162
|
+
|
163
|
+
|
164
|
+
def pick(pos, num=@mat[pos])
|
165
|
+
@mat[pos] -= num
|
166
|
+
puts
|
167
|
+
draw_mat
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
def draw_mat
|
172
|
+
draw(@mat)
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
def draw(mat)
|
177
|
+
graph = ''
|
178
|
+
space = ' '
|
179
|
+
dot = '.'
|
180
|
+
|
181
|
+
mat.each_with_index do |c, i|
|
182
|
+
graph << "#{space * 4} #{i + 1} #{space * (3 - i)} #{(dot + space) * c} \n"
|
183
|
+
end
|
184
|
+
|
185
|
+
puts "#{graph}\n"
|
186
|
+
end
|
187
|
+
|
188
|
+
|
189
|
+
def draw0(mat)
|
190
|
+
graph = ''
|
191
|
+
space = ' '
|
192
|
+
dot = '.'
|
193
|
+
|
194
|
+
mat.each_with_index do |c, i|
|
195
|
+
graph << "#{space * 4} #{space * (3 - i)} #{(dot + space) * c} \n"
|
196
|
+
end
|
197
|
+
|
198
|
+
puts "#{graph}\n"
|
199
|
+
end
|
200
|
+
|
201
|
+
|
202
|
+
def init_unsafe_positions
|
203
|
+
@unsafe_positions = []
|
204
|
+
#初始化阵集
|
205
|
+
arr = []
|
206
|
+
for a in 0..@mat[0]
|
207
|
+
for b in a..@mat[1]
|
208
|
+
for c in b..@mat[2]
|
209
|
+
for d in c..@mat[3]
|
210
|
+
arr << [a, b, c, d]
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
#remove [0,0,0,0]
|
217
|
+
arr.shift
|
218
|
+
|
219
|
+
#first unsafe-position is [0,0,0,1]
|
220
|
+
@unsafe_positions << arr.shift
|
221
|
+
|
222
|
+
#从小到大遍历阵集,增加unsafe
|
223
|
+
arr.each do |sample|
|
224
|
+
is_safe = false
|
225
|
+
|
226
|
+
@unsafe_positions.each do |unsafe|
|
227
|
+
|
228
|
+
dup = unsafe.dup
|
229
|
+
sample.each_with_index do |x, i|
|
230
|
+
j = dup.index(x)
|
231
|
+
dup.delete_at(j) if j
|
232
|
+
end
|
233
|
+
|
234
|
+
#有一堆豆子数不相等(多出) => 可以拿成一种unsafe => 是安全的
|
235
|
+
if dup.size == 1
|
236
|
+
is_safe = true
|
237
|
+
break
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
@unsafe_positions << sample unless is_safe
|
242
|
+
end
|
243
|
+
|
244
|
+
puts
|
245
|
+
draw_mat
|
246
|
+
end
|
247
|
+
|
248
|
+
def gets
|
249
|
+
STDIN.gets
|
250
|
+
end
|
251
|
+
|
252
|
+
end
|
253
|
+
end
|
data/lib/nim/version.rb
ADDED
data/nim.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "nim/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "nim"
|
7
|
+
s.version = Nim::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["takafan"]
|
10
|
+
s.email = ["takafan@163.com"]
|
11
|
+
s.homepage = "http://github.com/takafan/nim"
|
12
|
+
s.summary = %q{Nim}
|
13
|
+
s.description = %q{play nim game with Q, Whom nim the last one bean were *lost*}
|
14
|
+
|
15
|
+
s.rubyforge_project = "nim"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nim
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- takafan
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-08-17 00:00:00.000000000Z
|
13
|
+
dependencies: []
|
14
|
+
description: play nim game with Q, Whom nim the last one bean were *lost*
|
15
|
+
email:
|
16
|
+
- takafan@163.com
|
17
|
+
executables:
|
18
|
+
- nim
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- .gitignore
|
23
|
+
- Gemfile
|
24
|
+
- README.rdoc
|
25
|
+
- Rakefile
|
26
|
+
- bin/nim
|
27
|
+
- lib/nim.rb
|
28
|
+
- lib/nim/nim_core.rb
|
29
|
+
- lib/nim/version.rb
|
30
|
+
- nim.gemspec
|
31
|
+
homepage: http://github.com/takafan/nim
|
32
|
+
licenses: []
|
33
|
+
post_install_message:
|
34
|
+
rdoc_options: []
|
35
|
+
require_paths:
|
36
|
+
- lib
|
37
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ! '>='
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
44
|
+
none: false
|
45
|
+
requirements:
|
46
|
+
- - ! '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
requirements: []
|
50
|
+
rubyforge_project: nim
|
51
|
+
rubygems_version: 1.7.2
|
52
|
+
signing_key:
|
53
|
+
specification_version: 3
|
54
|
+
summary: Nim
|
55
|
+
test_files: []
|