Ruby Array赋值更新时应该更新

时间:2015-01-23 23:09:55

标签: ruby arrays sudoku

基本上我正在制作一个可以为我解决数独谜题的程序,我想保持原始输入矩阵的起点,必须选择重置电路板并重新启动,如果程序陷入困境一个兔子洞。我想将我的原始文件存储在一个名为@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矩阵更新

2 个答案:

答案 0 :(得分:2)

使用Ruby方法clonefreezedup

示例:

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

额外的笔记......

clonedup方法由每个类来定义,因此请阅读每个方法的文档。通常,clone是dup的超集,因为clone还复制单例方法,冻结状态等。

freeze方法并不是必需的,并且表现出意外(恕我直言)但它仍然值得使用该方法,因为它有点帮助,并向您显示您想要的其他代码阅读器对象是不变的。

答案 1 :(得分:0)

我想通了:它是一个矩阵输入,所以我必须将它映射两次以真正克隆它。