2016-12-01 58 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