用于访问多维数组中的数据的数据类型

时间:2015-02-24 20:39:52

标签: ruby arrays multidimensional-array

我有一个数组如下:

@spaces = []
def make_board
  7.times do |x|
    x += 1
    6.times do |y|
      y += 1
      @spaces << [x," "]
    end
  end
end

......以及一系列理想的组合:

def winners 
    #V row 1 
    [ [[0][1], [1][1], [2][1], [3][1]], 
    [[1][1], [2][1], [3][1], [4][1]], 
    [[2][1], [3][1], [4][1], [5][1]],
    #V row 2
    [[6][1], [7][1], [8][1], [9][1]],
    [[7][1], [8][1], [9][1], [10][1]],
    [[8][1], [9][1], [10][1], [11][1]],
    #V row 3
    [[12][1], [13][1], [14][1], [15][1]],
    [[13][1], [14][1], [15][1], [16][1]],
    [[14][1], [15][1], [16][1], [17][1]] ]
end

在整个计划的其余部分,&#34; &#34;在@spaces数组中可以更改为&#34; X&#34;或者&#34; O&#34;。我试图编写一种方法来检测何时任何组合都不是&#34; &#34;并且都具有相同的价值。

def @win? = false
def success
  winners.each do |x|
    fours = [ @spaces[x[0]], @spaces[x[1]], @spaces[x[2]], @spaces[x[3]] ]
    if fours.each{|x| x[1] != " "}
      if @spaces[x[0]] == @spaces[x[1]] && @spaces[x[1]] == @spaces[x[2]] && @spaces[x[2]] == @spaces[x[3]]
        @win = true
      end
    end
  end
end

它不喜欢从#winners数组传递的数据类型#success方法来搜索@spaces数组。它将其读作nil并想要一个整数,但添加.to_i会导致所有内容都变为0.添加括号的变化和各种组合,&#34; &#34;,以及响应错误消息的其他任何内容刚刚导致更多的nil和0. 使该方法有效的数据类型是什么?或者,在可能的情况下我&#39我是以一种特别愚蠢的方式处理它而只是没有意识到它有人能提出另一种方法来实现同样的目标吗?

6X7网格是一个&#34;连接四个&#34;板。 @sample数组中的每个子数组[0]都是该列,并在程序的其他部分中使用。每个子阵列[1]是&#34; X&#34;,&#34; O&#34;或&#34; &#34; (没用过)。该计划是一个游戏,连接四个&#34;用于学习目的

2 个答案:

答案 0 :(得分:0)

我认为你对winners的定义有点偏僻。特别是

[0][1] # => nil

因为你实际上是在创建一个数组[0],然后立即要求位置1中的元素,即nil(该数组在位置0只有一个元素)。由于所有数组都是单个元素,因此获奖者看起来像这样

[ [nil, nil, nil, nil], 
[nil, nil, nil, nil], 
[nil, nil, nil, nil],
# etc

认为你想要的是这个

[ [0, 1, 2, 3], 
[1, 2, 3, 4], 
[2, 3, 4, 5],

这将使这一行

fours = [ @spaces[x[0]], @spaces[x[1]], @spaces[x[2]], @spaces[x[3]] ]

因此,对于winners

中的第一个数组
fours = [ @spaces[0], @spaces[1], @spaces[2], @spaces[3] ]

可能看起来像

# the first 6 elements of spaces have x = 1, so all 1's here
fours = [ [1, " "], [1, " "], [1, " "], [1, " "] ]

...取决于游戏的状态。在那之后,你的代码有点偏离。看起来您正在尝试检查这些fours中的所有四个在空间中具有相同的值并且该值不为空。使用您拥有的结构:

if fours.all? { |space| space[1] != " " }
  if fours[0][1] == fours[1][1] &&
       fours[1][1] == fours[2][1] &&
       fours[2][1] == fours[3][1]
    @win = true
  end
end

如果我正确理解你的结构,那应该有效,或者至少要接近。

所有这一切,如果可以的话,我会非常重视这里的结构。首先,我将电路板表示为一个数组数组,您可以使用x,y坐标访问任何位置,如此

board = 7.times.map { Array.new(6, " ") }
board[0][0] # => " "

您可以使用基于0或1的坐标,但如果您使用的是1,则每次访问阵列时都必须减去1。

填充广场很容易

board[x][y] = "O"

您可以将所有获胜者列为坐标对(请注意使用常量,因为这永远不会改变):

WINNERS = [
  [[0,0], [1,0], [2,0], [3,0]], # horizontal win
  [[0,0], [1,1], [2,2], [3,3]], # diagonal win
  # etc
]

然后检查那些

WINNERS.each do |win_row|
  if win_row.all? { |x, y| board[x][y] == "X" } || win_row.all? { |x, y| board[x][y] == "O" }
    @win = true
    break
  end
end

如果您不想构建和存储获胜者数组,您也可以通过算法确定获胜者。

答案 1 :(得分:0)

这是第一个问题...... [0]是一个只有一个元素的数组。 [0][1]说&#34;得到数组的第二个元素&#34; (索引1)但没有第二个元素,因此返回nil。

我认为不是[0][1]而是你真的想做0等等。

def winners 

    #V row 1 
    [ 
      [0, 1, 2, 3], 
      [1, 2, 3, 4], 
      [2, 3, 4, 5],
    #V row 2
      [6, 7, 8, 9],
      [7, 8, 9, 10],
      [8, 9, 10, 11],
    #V row 3
      [12, 13, 14, 15],
      [13, 14, 15, 16],
      [14, 15, 16, 17]
    ]
end

下一个问题是这一行......

if fours.each{|x| x[1] != " "}

......没有做你认为的事情。 each块返回迭代的数组,而不是truefalse。你想要的是......

if fours.select{|x| x[1] == " "}.empty?

如果没有带&#34的单元格,将返回true &#34;在第二个元素中。