2016-12-01 6 views
1

私は現在、純粋なルビー&でテストされたTDDスタイルのTic-Tac-Toeゲームのレプリカを作っています。Tic-Tac-Toe:プレーヤーが勝ったかどうかを確認する

私が抱いている唯一の問題は、私の人生のために、プレーヤーが勝ったときをチェックする方法を理解できないことです。私はこれが比較的簡単な問題だと知っていますが、私はその日のうちの1つを持っています - そして、私は本当に最後の手段としてここに投稿します。

何か助けが大変ありがとうございます。私の現在のコードを批評してください。対処できます。 :)

マイコード:

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

配列から配列を減算すると、2番目の配列のすべての要素が見つかると1番目の配列から削除されます。あなたが '[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 

は統合し、:私はあなたのためにあなたのコードを記述する必要はありませんが、私はあなたが適用するには、正しいアルゴリズムを認識する必要があり、そこからいくつかの擬似コードをあげますいくつかの高次関数ですべてのファンシーを得る。

ちなみに、ビットマスクと2つのパワーを合計することで、勝利を計算する方法がいくつかありますが、わかりやすいもので行くと思います。

+1

? {| i、j、k | ...} 'を呼び出し、明示的な戻り値を削除します。 – Stefan

+0

ありがとう、ステファン! – IainK

+0

優れた点、@Stefanはこれを使うために私の答えを変えました。 – SteveTurczyn

2

私はこのような何かを開始します:あなたは `WINNING_COMBINATIONS.anyを使用することができます

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

関連する問題