2016-01-11 53 views
1

這是針對一個tic tac腳趾遊戲。我有九個字符串元素,並嵌套數組WIN_COMBINATIONS與位置的組合陣列boardboard檢查一個陣列中的所有字符串是否在另一個陣列中

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] 
+2

請提供這些數組的示例。 – mudasobwa

+2

舉例說明輸入輸出。顯示你到目前爲止嘗試過的。 – ndn

+0

好吧,添加數組將添加我輸入的代碼,這是非常錯誤/不好/初學者 - 你可能會看到:p –

回答

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] 
+0

爲什麼「X」和「Y」? – sawa

+0

@sawa,我的壞。修正了,謝謝。 – ndn

+0

更直接(更短)的檢查將是'values = board.values_at(* combination);值==%w(X X X)||值==%w(O O O)' – Stefan

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返回的所有元素的量,塊11返回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

您可以替換selectfind如果你只是要檢索的第一個贏取的組合。

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. 

它未經測試,但應該工作。

+0

'won?'似乎沒有任何回報。 – Stefan

+0

需要通過董事會。 –

+0

@Stefan我錯過了回報聲明。 –

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

您可能想要解釋'&。&',這是相當新穎的。 – Stefan

+1

實際上'&.'不是必需的,因爲'(nil&a)== a'評估爲'false == a' – Stefan

+0

@Stefan感謝您指出這一點。 – sawa

1

只是出於好奇(略微更新@斯特凡的答案):

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 

在這裏,我們的組合匹配三個相同的符號,這可能是井字棋遊戲在語義上最正確的解釋。

+1

我喜歡你的正則表達式的方法,但我會使用'/(\ w)\ 1 \ 1 /'。 – Stefan

+0

@Stefan的確,更新,謝謝。但是,我留下了'index',使它更加靈活(與WIN_COMBINATIONS數組有一個反向連接,因爲它可能更容易在那裏調試錯誤的值。) – mudasobwa

相關問題