Ruby 解析康威';s游戏网格
以下是我试图用Ruby编写Conway的生命游戏()的尝试 我有一个非常具体的问题,关于“计算邻居”的方法。基本上,当我到达网格边缘时,我会有一些奇怪的行为。当我解析第0行并到达最后一列(Cloumn 4)时,它会执行如下操作: 计算单元:R:0 C:4Ruby 解析康威';s游戏网格,ruby,arrays,parsing,conways-game-of-life,Ruby,Arrays,Parsing,Conways Game Of Life,以下是我试图用Ruby编写Conway的生命游戏()的尝试 我有一个非常具体的问题,关于“计算邻居”的方法。基本上,当我到达网格边缘时,我会有一些奇怪的行为。当我解析第0行并到达最后一列(Cloumn 4)时,它会执行如下操作: 计算单元:R:0 C:4 评价邻域R:-1c:3。州:0 评价邻域R:-1c:4。国家:1 评估邻居R:-1 C:5。声明: 评估邻居R:0c:3。州:0 评估邻居R:0c:5。声明: 评价邻域R:1c:3。国家:1 评价邻域R:1c:4。州:0 评价邻域R:1c:5
- 评价邻域R:-1c:3。州:0
- 评价邻域R:-1c:4。国家:1
- 评估邻居R:-1 C:5。声明:
- 评估邻居R:0c:3。州:0
- 评估邻居R:0c:5。声明:
- 评价邻域R:1c:3。国家:1
- 评价邻域R:1c:4。州:0
- 评价邻域R:1c:5。声明:
#Dimensions for the game grid
WIDTH = 5
HEIGHT = 5
def rand_cell
rand(2)
end
def starting_grid
#Initialise the playing grid
@start_grid = Array.new(WIDTH){Array.new(HEIGHT)}
#Randomly generate starting state for each cell on the grid
@start_grid.each_with_index do |row, rindex|
row.each_with_index do |col, cindex|
@start_grid[rindex][cindex] = rand_cell
end
end
end
def next_grid
#build the next generation's grid to load values into
@next_gen_grid = Array.new(WIDTH){Array.new(HEIGHT)}
#parse each cell in the start grid to see if it lives in the next round
@start_grid.each_with_index do |row, rindex|
row.each_with_index do |col, cindex|
puts "\n\nEvaluating cell: R: #{rindex} C: #{cindex}"
@next_gen_grid[rindex][cindex] = will_cell_survive(rindex, cindex)
end
end
#move the newly generated grid to the start grid as a sterting point for the next round
@start_grid = @next_gen_grid
end
def show_grid(grid)
#Display the evolving cell structures in the console
grid.each_with_index do |row, rindex|
row.each_with_index do |col, cindex|
if grid[rindex][cindex] == 1
print "️⬛️ "
else
print "⬜️ ️"
end
end
puts "\n"
end
end
def count_neighbours(row, col)
cell_count = 0
rows = [-1, 0, 1]
cols = [-1, 0, 1]
rows.each do |r|
cols.each do |c|
#ingnore the cell being evaluated
unless c == 0 && r == 0
#This line is a hack to stop an error when evaluating beyond the last row
if row != HEIGHT-1
puts "Evaluating neighbor R: #{row+r} C: #{col+c}. State: #{@start_grid[(row+r)][(col+c)]}"
if @start_grid[(row+r)][(col+c)] == 1
cell_count += 1
end
end
end
end
end
puts "Neighbour count is #{cell_count}"
return cell_count
end
def will_cell_survive(rindex, cindex)
count = count_neighbours(rindex, cindex)
#If the cell being evaluated is currently alive
if @start_grid[rindex][cindex] == 1
#test rule 1
if alive_rule1(count)
puts "Rule 1"
return 0
#test rule 2
elsif alive_rule2(count)
puts "Rule 2"
return 1
elsif
#test rule 3
puts "Rule 3"
return 0
end
#If the cell being evaluated is currently dead
else
#test rule 4
alive_rule4(count)
puts "Rule 4"
return 1
end
end
def alive_rule1(neighbour_count)
neighbour_count < 2
end
def alive_rule2(neighbour_count)
neighbour_count == 2 || neighbour_count == 3
end
def alive_rule3(neighbour_count)
neighbour_count > 3
end
def alive_rule4(neighbour_count)
neighbour_count == 3
end
#Run just one round of the game
system "clear"
starting_grid
show_grid(@start_grid)
puts "\n\n"
next_grid
show_grid(@next_gen_grid)
#Initiate the game grid
# system "clear"
# starting_grid
#Run the game
# 200.times do |t|
# system "clear"
# puts "\n\n"
# next_grid
# puts "Grid #{t}"
# show_grid(@next_gen_grid)
# sleep(0.25)
# end
#游戏网格的尺寸
宽度=5
高度=5
def rand_电池
兰特(2)
结束
def起动格栅
#初始化播放网格
@start_grid=Array.new(宽度){Array.new(高度)}
#为网格上的每个单元随机生成起始状态
@开始网格。每个网格都有索引do行,rindex|
行。每个带有索引do的列,cindex|
@启动网格[rindex][cindex]=随机单元
结束
结束
结束
def下一个网格
#构建下一代网格以将值加载到
@next_gen_grid=Array.new(宽度){Array.new(高度)}
#分析起始网格中的每个单元格,查看它是否存在于下一轮中
@开始网格。每个网格都有索引do行,rindex|
行。每个带有索引do的列,cindex|
放置“\n\n计算单元:R:{rindex}C:{cindex}”
@下一代网格[rindex][cindex]=细胞会存活吗(rindex,cindex)
结束
结束
#将新生成的网格移动到起始网格,作为下一轮的存储点
@开始网格=@next\u gen\u网格
结束
def显示网格(网格)
#在控制台中显示不断演变的单元结构
grid.each_与_索引do|行,rindex|
行。每个带有索引do的列,cindex|
如果网格[rindex][cindex]==1
“打印”️⬛️ "
其他的
“打印”⬜️ ️"
结束
结束
放入“\n”
结束
结束
def计数(行、列)
单元格计数=0
行=[-1,0,1]
cols=[-1,0,1]
行。每行做| r|
每种颜色都有| c|
#ingnore正在评估的单元格
除非c==0&&r==0
#这一行是一种在计算超过最后一行时停止错误的方法
如果行!=高度-1
将“计算邻居R:#{row+R}C:#{col+C}。状态:#{@start_网格[(行+r)][(列+c)]}”
如果@start_网格[(行+r)][(列+c)]==1
单元计数+=1
结束
结束
结束
结束
结束
放置“邻居计数为#{cell_count}”
返回单元计数
结束
def细胞将存活(rindex,cindex)
计数=计数(rindex、cindex)
#如果正在计算的单元格当前处于活动状态
如果@start_grid[rindex][cindex]==1
#测试规则1
如果活动(规则1)(计数)
“规则1”
返回0
#测试规则2
elsif活动规则2(计数)
把“规则2”
返回1
埃尔西夫
#测试规则3
“规则3”
返回0
结束
#如果正在评估的单元格当前已死亡
其他的
#测试规则4
现行规则4(计数)
把“规则4”
返回1
结束
结束
def活动规则1(邻居计数)
相邻单元计数<2
结束
def活动规则2(邻居计数)
邻居计数=2 | |邻居计数=3
结束
def活动规则3(邻居计数)
邻接计数>3
结束
def活动规则4(邻居计数)
邻接计数==3
结束
#只跑一轮比赛
系统“清除”
启动网格
显示网格(@start\u网格)
放置“\n\n”
下一个网格
显示网格(@next\u gen\u grid)
#启动游戏网格
#系统“清除”
#启动网格
#运行游戏
#200.5倍|
#系统“清除”
#放置“\n\n”
#下一个网格
#放置“网格#{t}”
#显示网格(@next\u gen\u grid)
#睡眠(0.25)
#结束
[编辑]:实现答案的代码位于如果您想将边相互连接(顺便说一下,这会创建一个“圆环”形状,或者如果您更喜欢永远无法离开屏幕的“小行星”世界模型),那么最简单的调整就是使用模块化算法: 更改:
if @start_grid[(row+r)][(col+c)] == 1
致:
运算符符号%
是模块化算术,并根据需要精确执行环绕逻辑
超出最后一行与超出最后一列的行为不同的原因是:
@start_grid[ 3 ][ 5 ] == nil
在您的邻居支票中返回false,其他一切正常
但是,
@start_grid[ 5 ][ 3 ]
是一个问题,因为@start\u grid[5]
是nil
,所以它是有效的
nil[ 3 ]
抛出此错误是因为Ruby没有逻辑来解析
[]
在nil
上的含义,谢谢你的回答。非常聪明。:-)
nil[ 3 ]