基本上我正在制作一个可以为我解决数独谜题的程序,我想保持原始输入矩阵的起点,必须选择重置电路板并重新启动,如果程序陷入困境一个兔子洞。我想将我的原始文件存储在一个名为@start的字段变量中,并且在算法过程中永远不会触及它。
我必须使用某种关键字吗?我试过.map,我试过从输入矩阵手动复制它。
class Game
def initialize(gamematrix)
@start=gamematrix
@rows=gamematrix
puts "rows - #{@rows}"
@cols=@rows.transpose
end
def findnils
puts "finding the nils"
sleep 0.1
nilspaces=[]
g=0
while g<@cols.length
puts "3 we parse through col #{g}"
sleep 0.1
p=0
while p<@rows.length
if @rows[g][p]!=nil
puts "4 [#{g}][#{p}]"
end
sleep 0.1
if @rows[g][p]==nil
puts " [#{g}][#{p}] :found a nil!!!"
nilspaces<<[g,p]
end
p+=1
end
g+=1
end
return nilspaces
end
def sudku
puts '1 we\'re in the sudku method'
#sleep 0.8
#update the coordinatebank of nill spaces in the matric
#sleep 0.8
nilspaces=findnils
while !win?
puts '5 now our nilspaces array now looks like this: '
puts "nils: [#{nilspaces}]"
sleep 0.4
#randomly find an empty nil space, find its coordinates in the matrix
current=nilspaces.sample
puts "out current nilspace is [#{current}]"
sleep 0.2
nilspaces.delete_if{|e| e==current}
puts "nils: [#{nilspaces}]"
sleep 0.2
#then use the guessNum method to guess based on the coordinates
guessedN=guessNum(@cols[current[0]], @rows[current[1]])
puts "guessed: #{guessedN}"
sleep 0.2
#assign out guessed number to replace the nil
if guessedN != 999
@rows[current[0]][current[1]]=guessedN
sleep 0.1
puts "guessed rturns a number so @rows is #{@rows[current[0]][current[1]]}"
puts " start matrix: #{@start}"
else
puts "=========================="
#reset
puts "resets everything"
sleep 0.3
@rows=@start
@cols=@rows.transpose
puts "rows: #{@rows}"
puts "cols: #{@cols}"
nilspaces=findnils
puts "=========================="
sleep 0.1
end
display
sleep 0.4
end
end
def guessNum(vset, hset)
#create an array of numbers to choose from
choice=(1..@rows.length).to_a
#subtract everything in the choice array thats in the hset
choice.delete_if {|e| hset.include?(e)}
#subtract everything in the choice array thats in the vset
choice.delete_if {|e| vset.include?(e)}
#if nothing is left in the choice array return a string called empty
#otherwise return a random number from the array (the choice array)
if choice.empty?
return 999
else
return choice.sample
end
end
def display
puts "--------------------"
for g in @rows
out=" "
for l in g
out+= "#{'%03s' % l.to_s}"
end
out+=" \n"
puts out
end
puts "--------------------"
end
def win?
[@rows.all? { |e| e.uniq.length==@rows.length }, @cols.all? { |e| e.uniq.length==@cols.length }].all? { |e| e==true }
end
end
驱动程序测试是这样的:
easygame4x4 = [[4,零,零,零],[零,3,4,零],[零,1,2,零],[零,零,零,1]]
智傲= Game.new(easygame4x4)
gameone.sudku
你可以运行它并查看它是如何工作的,我在这里放了一堆puts语句和sleep语句来引导任何人完成整个过程,问题是,我的@start矩阵总是用@rows矩阵更新
答案 0 :(得分:2)
示例:
def initialize(gamematrix)
@start=gamematrix.clone.freeze
执行anything = @start
时,请执行以下操作:
@rows=@start.dup
您在代码中看到的是Ruby修改对象:
array1 = ["a"]
array2 = array1 # now these variables point to the same place
array2[0] #=> "a" as you expect
array1[0] = "b"
array2[0] #=> "b" because array1 and array2 point to the same place
什么克隆做的是浅拷贝,a.k.a。浅克隆:
array1 = ["a"]
array2 = array1.clone # now array2 points to a new place
array2[0] #=> "a" as you expect
array1[0] = "b"
array2 #=> ["a"] because array2 points to its own place, not array1's place
浅拷贝和深拷贝之间的区别:
array1 = [["a"]]
array2 = array1.clone # array2 points to a new place, which in turn points to the array that contains "a"
array1[0][0] = "b" # you're changing the array that contains "a"
array2 #=> [["b"]] # because array2 points to its own place, which in turn still points to the same array that contained "a"
您需要的代码是深层拷贝,即深度克隆。 Ruby没有这种方法(这是一个错误恕我直言),所以典型的解决方案是使用gem或Ruby Marshall
方法。看到
Why isn't there a deep copy method in Ruby?
除了复制没有复制冻结状态之外,复制的内容就像克隆一样:
s = "foo"
s.clone.frozen? # true
s.dup.frozen? # false
您的特定应用程序正在修改行,因此您的重置功能应使用dup
代替clone
。
如果您正在为矩阵编写自己的对象类,那么您可能需要编写自己的clone
方法,例如:
class GameMatrix
def clone
# create a clone as you want,
# such as initializing a new object,
# and/or cloning sub-objects, etc.,
# including singleton/class methods,
# including frozen state, etc.
end
def dup
# create a duplicate as you want,
# such as initializing a new object,
# and/or duplicating sub-objects, but
# excluding singleton/class methods,
# excluding frozen state, etc.
end
end
额外的笔记......
clone
和dup
方法由每个类来定义,因此请阅读每个方法的文档。通常,clone
是dup的超集,因为clone
还复制单例方法,冻结状态等。
freeze
方法并不是必需的,并且表现出意外(恕我直言)但它仍然值得使用该方法,因为它有点帮助,并向您显示您想要的其他代码阅读器对象是不变的。
答案 1 :(得分:0)
我想通了:它是一个矩阵输入,所以我必须将它映射两次以真正克隆它。