アルファ・ベータ・プルーニングは、ハード・コーディング(tic-tac-toe用)以外にも最も効率的なアルゴリズムのようです。しかし、リンクで与えられたC++の例からアルゴリズムを変換する際に問題があります:http://www.webkinesia.com/games/gametree.php。アルファ・ベータ・プルーニング・アルゴリズムをC++からRubyに変換する際の問題
プレーヤーは1または0のいずれかであるため、1-player
を実行するとプレーヤーが切り替わります。
WIN = 1
LOSS = -1
DRAW = 0
INFINITY = 100
def calculate_ai_next_move
best_move = -1
best_score = -INFINITY
cur_player = COMPUTER
self.remaining_moves.each do |move|
self.make_move_with_index(move, cur_player)
score = -self.alphabeta(-INFINITY,INFINITY, 1 - cur_player)
self.undo_move(move)
if score > best_score
best_score = score
best_move = move
end
end
return best_move
end
def alphabeta(alpha, beta, player)
best_score = -INFINITY
if not self.has_available_moves?
return WIN if self.has_this_player_won?(player) == player
return LOSS if self.has_this_player_won?(1 - player) == 1 - player
return DRAW
else
self.remaining_moves.each do |move|
break if alpha > beta
self.make_move_with_index(move, player)
move_score = -alphabeta(-beta, -alpha, 1 - player)
self.undo_move(move)
if move_score > alpha
alpha = move_score
next_move = move
end
best_score = alpha
end
end
return best_score
end
現在のところ、アルゴリズムはひどく遊んでいます。最初は最後のスペースを選択し、その後に最初から(左から右に)使用可能なスペースを選択します。
何が問題なの?
また、私はTDDをやっているので、self.has_this_player_won ?, self.undo_moveとself.remaining_movesが正しいことを知っています。
明白なこと: 'has_this_player_won?'はブール値を返しますが、それを整数と比較します。 'DRAW'を返すことはありません。 'move_score = -alphabeta(-beta、-alpha、1-player)'そしてTDDを使用しているので、AIに単純な位置を与えるテストを行います(2つまたは3つのフリーセル)、それが正しいスコアを返すことを確認してください。 – adamax
has_this_player_won?勝った場合にのみプレーヤーを返します。そうでなければfalse。私はDRAWを追加しました。それは私の再帰呼び出しのようなものですか? – NullVoxPopuli
TDDに関しては、いくつかのテストを手作業で行うことができるように、このアルゴリズムについてもっと知る必要があります。 – NullVoxPopuli