2017-02-11 15 views
2

現在、Python TicTacToeゲーム用のAIを実装しようとしています。 1つの状況を除いて、すべてが大幅に実行されます。 私の現在のコード:Python TicTacToe minimaxが間違ったオプションを選択しました

def testLine(line): 
    ''' 
    ' :param line: Liste containing 3 ints 
    ' :return: 1, if all elements of the list == 1 
    '   -1, if all elements of the list == -1 
    '   0, otherwise 
    ''' 

    if line[0] == 1 and line[1] == 1 and line[2] == 1: 
     return 1 
    elif line[0] == -1 and line[1] == -1 and line[2] == -1: 
     return -1 
    return 0 


def getWinner(board): 
    # test columns 
    for idx in range(3): 
     line = [board[0][idx], board[1][idx], board[2][idx]] 
     if not testLine(line) == 0: 
      return line[0] 

    # test rows 
    for idx in range(3): 
     line = board[idx] 
     if not testLine(line) == 0: 
      return line[0] 

    # test diagonals 
    line = [board[0][0], board[1][1], board[2][2]] 
    if not testLine(line) == 0: 
     return line[0] 
    line = [board[0][2], board[1][1], board[2][0]] 
    if not testLine(line) == 0: 
     return line[0] 

    # no winner 
    return 0 

def count(board, obj): 
    c = 0 
    for r in range(len(board)): 
     for col in range(len(board[r])): # FIXED IT 
      if board[r][col] == obj: 
       c += 1 
    return c 

def nextMove(board, player): 

    if len(board[0]) + len(board[1]) + len(board[2]) == 1: return 0, 4 
    nextPlayer = player * (-1) 

    if not getWinner(board) == 0: 
     if player is 1: return -1, (-1, -1) 
     else: return 1, (-1, -1) 
    listOfResults = [] # empty array 

    if count(board, 0) == 0: # there is no empty field 
     return 0, (-1, -1) 

    _list = [] 
    for i in range(len(board)): 
     for j in range(len(board[i])): 
      if board[i][j] == 0: 
       _list.append((i, j)) 

    for (i, j) in _list: 
     board[i][j] = player 
     ret, move = nextMove(board, nextPlayer) 
     listOfResults.append(ret) 
     board[i][j] = 0 
    if player is 1: 
     maxPossibleValue = max(listOfResults) 
     return maxPossibleValue, _list[listOfResults.index(maxPossibleValue)] 
    else: 
     minPossibleValue = min(listOfResults) 
     return minPossibleValue, _list[listOfResults.index(minPossibleValue)] 



if __name__ == '__main__': 
    print(str(nextMove([[ 1, -1, 0], 
         [ -1, -1, 1], 
         [ 1, 1, 0]], 
         -1))) 

出力:(0, (0, 2))

私は確信しているcountgetWinnertestLine仕事のために完全に言うことができます。 しかし、コードの一番下にあるシナリオの出力は、であるため、間違っていることがあります。(0, 2, 2)は、最終的に勝つチャンスを「ブロック」する必要があるためです。 私のminimaxアルゴリズムを修正する方法の提案がありますか?

編集:私はそれを修正しました。countメソッドでエラーが発生しました。それ以外の場合は、正しい順序で要素を保持していないだろうし、全体メソッドがfalseを返したため、あなたは

for col in board[r] 

しかし

for col in range(len(board[r])) 

を言うべきではありません。

+1

1)各メソッドのunittestを書いてください 2)私はその問題がリストに関連している可能性があります(変更可能で、さらにリストのリンクされたコピー(割り当てによって作成されます)、元のリストも変更された場合) – Sergius

+1

@ Ser私はそれをうまく修正したので、この質問を編集しました。 unittestsのアイデアをありがとう、彼らは私をたくさん助けました。私はもともと 'count'メソッドにエラーがないと思っていたので、実際にテストしませんでした。あなたは私にそれについて考えるようにさせ、私はその機能を正しく得ることができました。どうもありがとうございます! – dv02

答えて

1

私はそれを修正しました。カウント方法にエラーがありました。それ以外の場合は、正しい順序で要素を保持していないだろうし、全体メソッドがfalseを返したため、あなたは

for col in board[r] 

しかし

for col in range(len(board[r])) 

を言うべきではありません。

0

最初に知る必要があるのは、タプルの定義には括弧(空のタプルの場合は不要)を必要としないため、return a, breturn (a,b)に似ています。

だから、簡単に(0, (0, 2))の代わりに(0, 0, 2)を返すことができます。

return (maxPossibleValue,) + _list[listOfResults.index(maxPossibleValue)] 
# use (a,) for a tuple of len 1 

しかし、私は、これはあなたの問題の半分しか解決承知しています。

+0

私は知っていますが、この "返信形式"を使用すると、さまざまな値に簡単にアクセスできます。 "しかし、私はこれがあなたの問題の半分だけ解決することを知っています。"それはまったく問題を解決するものではありませんが、とにかくありがとうございます! :) – dv02

+0

あなたは "_itは'(0、2、2) '_ 'でなければならないと私は混乱していました:)私はアルゴリズムそのものを見ています... – User9123

+0

それは馬鹿でした。エラーは 'count'メソッドにありました。それは、そうでなければ正しい順序でそれを保持しないので、それは「列内の列[r]」ではなく「範囲内の列(len(ボードr)」)であるべきです。ご協力いただきありがとうございます! – dv02

関連する問題