2016-12-01 83 views
1

我目前正在建造一款非常受歡迎的井字遊戲的複製品,它使用純紅寶石&經過測試的TDD風格構建而成。井字遊戲:檢查玩家是否贏得

我遇到的唯一問題是,我不能在我的生活中弄清楚如何檢查玩家何時贏得比賽。我知道這是一個相對簡單的問題,但我只是有一天 - 我真的只是在這裏作爲最後的手段。

任何幫助都被大量讚賞 - 隨時批評我目前的代碼!我應付得來。 :)

我的代碼:

class TicTacToe 

WINNING_COMBINATIONS = [[0, 1, 2], [3, 4, 5], [6, 7, 8], #Horizontal 
         [0, 3, 6], [1, 4, 7], [2, 5, 8], #Vertical 
         [0, 4, 8], [2, 4, 6]] #Diagonal  

def initialize 
    @board = ["", "", "", "", "", "", "", "", ""] 
    @players = ['player_one', 'player_two'] 
    @current_player = 'player_one' 
end 

def player_1 
    @players.first 
end 

def player_2 
    @players.last 
end 

def switch 
    @current_player = opponent_of(@current_player) 
end 

def display_board 
    puts " #{@board[0]} | #{@board[1]} | #{@board[2]} " 
    puts "-----------" 
    puts " #{@board[3]} | #{@board[4]} | #{@board[5]} " 
    puts "-----------" 
    puts " #{@board[6]} | #{@board[7]} | #{@board[8]} " 
end 

def move(position) 
    fail "Please select a space within range." if position < 1 || position > 9 
    fail "That space is already taken!" unless @board[position-1].empty? 
if @current_player == player_1 
    @board[position-1] = 'o' 
else 
    @board[position-1] = 'x' 
end 
    switch 
end 

def check_for_winner 
    #Help! 
end 

private 

def opponent_of(player) 
    @players.select { |p| p != player }.first 
    end 
end 

回答

1

這是一個確定小陣列(獲勝集)是否完全是較大陣列(板)的子集的問題。你可以用簡單的數組減法來做到這一點。

def has_winner(board) 
    WINNING_COMBINATIONS.each do |line| 
    return true if (line - board) == [] 
    end 
    return false 
end 

要合併的@Stefan指教在另一個答案...

def has_winner(board) 
    WINNING_COMBINATIONS.any? {|line| (line - board) == [] } 
end 
+0

嘿史蒂夫,謝謝你的回覆!你說這和減去一個數組一樣簡單,但是我沒有看到如何從WINNING_COMBINATIONS的每次迭代中減去板子來幫助我。對不起,在這裏慢一點,但所有的幫助是超級讚賞。 – IainK

+0

從數組中減去數組後,第二個數組中的每個元素都會從第一個數組中移除(如果找到)。如果你有'[0,4,8]'行,並且如果你減去了板[0,1,3,4,8],那麼結果是空的[]',所以你可以說「組合中的每個屬性線目前在我的董事會,所以我贏了!「。想象一個失敗的場景......如果你有'[0,4,8]'而你減去'[0,1,3,8]',你會留下'[4]'。由於它落後了,這意味着它沒有被減去,這意味着它在電路板上沒有找到......所以你知道你沒有'0,4,8'列表中的'4'。 – SteveTurczyn

+0

所以(清楚)我們測試的是'(線路板)== []'(空陣列) – SteveTurczyn

1

你非常接近。我不想寫你的代碼你,但我會給你一些僞從中你應該認識到正確的算法應用:

def has_winner(board) 
    WINNING_COMBINATIONS.each do |i, j, k| 
    return true if board[i] == board[j] && board[i] == board[k] 
    end 
    false 
end 

整合需要,然後也許在試圖涉足讓所有人都喜歡一些更高級的功能。

順便說一下,有一些真正的花式和更快的方式來計算勝利基於位掩碼和兩個總和權力等,但我猜最可讀性是好的。

+1

你可以用'WINNING_COMBINATIONS.any? {| i,j,k | ...}並刪除顯式的回報。 – Stefan

+0

謝謝,斯蒂芬! – IainK

+0

優秀點,@Stefan,改變了我的答案,使用它。 – SteveTurczyn

2

我會像這樣開始:

def check_for_winner 
    WINNING_COMBINATIONS.each do |combination| 
    case board.values_at(*combination) 
    when %w(o o o) 
     return 'Player 1 wins' 
    when %w(x x x) 
     return 'Player 2 wins' 
    end 
    end 
end 
+0

你也可以在%w(o o o)和'%w(x x x)時使用'case board.values_at(* combination)'以及'' – Stefan

+0

@Stefan:你說得對。這看起來好多了。 – spickermann