检查一个数组中的所有字符串是否都在另一个数组中

时间:2016-01-11 09:23:47

标签: arrays ruby

这是一个tic tac toe游戏。我有一个包含九个字符串元素的数组board,以及一个位置组合来自WIN_COMBINATIONS的嵌套数组board

board = ["X", "X", "X", " ", " ", " ", " ", " ", " "]

WIN_COMBINATIONS = [
  [0, 1, 2],
  [0, 3, 6],
  [0, 4, 8],
  [3, 4, 5],
  [6, 7, 8],
  [6, 4, 2],
  [1, 4, 7],
  [2, 5, 8]
]

如何使用board中的组合从"X"全部"O"或全部WIN_COMBINATIONS中选择数组合?

例如      一个不同的板,上面的X在右对角线上获胜。

board = ["X", "O", "X", "O", "X", "O", "X", "X", "O"]

#  X | O | X
# ---+---+---
#  O | X | O
# ---+---+---
#  X | X | O

won?(board) #=> [2,4,6]

5 个答案:

答案 0 :(得分:5)

ndn's answer的轻微变化:

board = %w(X O X
           O X O
           X X O)
WIN_COMBINATIONS.select { |c| board.values_at(*c).join =~ /XXX|OOO/ }
#=> [[6, 4, 2]]

说明:

  • select返回块返回true的所有元素。

  • values_at返回指定索引处的值:

    board.values_at(*[0, 1, 2])
    #=> ["X", "O", "X"]
    

    *将数组转换为参数列表,因此上面的内容变为values_at(0, 1, 2)

  • join返回带有连接元素的字符串:

    ["X", "O", "X"].join
    #=> "XOX"
    
  • =~检查字符串是否与regular expression /XXX|OOO/匹配,即XXXOOO

如果您只想检索第一个获胜组合,可以将select替换为find

答案 1 :(得分:2)

编辑代码包含了Stefan的建议。

这样做一次:

WIN_COMBINATIONS.each(&:sort!)

然后,

h = board.each_index.group_by{|i| board[i]}
# => {"X"=>[0, 1, 2], " "=>[3, 4, 5, 6, 7, 8]}
WIN_COMBINATIONS.find{|a| (h["X"] & a) == a or (h["O"] & a) == a}
# => [0, 1, 2]

答案 2 :(得分:1)

WIN_COMBINATIONS.find do |combination|
  values_at_positions = board.values_at(*combination).uniq
  values_at_positions.size == 1 and ['X', 'O'].include?(*values_at_positions)
end # => [0, 1, 2]

答案 3 :(得分:1)

出于好奇(稍微更新了@Stefan的回答):

WIN_COMBINATIONS.index do |wc|
  board.values_at(*wc).join =~ /(?<l>\w)\k<l>\k<l>/
  # or, as suggested by @Stefan: board.values_at(*wc).join =~ /(\w)\1\1/
end
#⇒ 5

这里我们将这些组合与三个相同的符号相匹配,这可能是对井字游戏最正确的解释。

答案 4 :(得分:0)

你可以试试这个。

def won?(board)
    xpos = []
    opos = []
    who_won = nil;
    board.each_with_index{|x,i| xpos << i if x == "X" }
    board.each_with_index{|x,i| xpos << i if x == "O" }
    WIN_COMBINATIONS.each do |com|
         temp = com & xpos
         who_won = "X" if temp == com
         temp = com & opos
         who_won = "O" if temp == com
         break if !who_won.nil?
    end
    return who_won
end

won?(board) #=> X if x wins, O if O wins. nil if no body wins.

未经测试但应该有效。