2016-07-13 3 views
0

を持つすべての空のスペースを埋めることにより、ボードを更新チックタックつま先のためのミニマックスアルゴリズム私は、このようなチックタックつま先として、小さなゲームをプログラミングすることによってパイソンの私の理解を改善しようとしています。私は最初からゲームのコピーを作成したが、その後のゲームのための合理的なAIを作成する方法を見つけるためにオフに行ってきました。私はこの目標を達成するためにミニマックスを使うことに決めました。私は、アルゴリズムのためのチュートリアルを発見し、ゲームのためにそれを成形しようとしました。のpython - 同じシンボル

しかしコードは、AIの最初のターンで、実行されたとき。ボード上に残ってすべての空きスペースは、ゲームがアンプレアブル作り、勝利を強制的に、同じシンボルで満たされています。

私はアルゴリズムに慣れていないと未経験だったので、私はユーチューブのチュートリアルからコードを取り、それがゲームのための機能であるように、それを編集しました。ここで

はコード

import random 
import time 
import sys 
from sys import maxsize 




#converts numbers from the board to X O and "" for printing out the board 
def numToSymbol(board): 
    visual = board 
    for i in range(0, 9): 
     if visual[i] == -1: 
      visual[i]= "X" 
     elif visual[i] == 1: 
      visual[i] = "O" 
     elif visual[i] == 0: 
      visual[i] = " " 
    return visual 


def symbolToNum(visual): 
    board = visual 
    for i in range(0, 9): 
     if board[i] == "X": 
      board[i] = -1 
     elif board[i] == "O": 
      board[i] = 1 
     elif board[i] == " ": 
      board[i] = 0 
    return board 


# prints the board, first coverting numbers throught numtoSymbol 
def drawBoard(): 
    visual = numToSymbol(board) 
    print(
     "|"+ str(visual[0]) + "|" + str(visual[1]) + "|" + str(visual[2]) + "| \n" 
     "-------\n" 
     "|"+ str(visual[3]) + "|" + str(visual[4]) + "|" + str(visual[5]) + "| \n" 
     "-------\n" 
     "|"+ str(visual[6]) + "|" + str(visual[7]) + "|" + str(visual[8]) + "| \n" 
     "-------") 
    symbolToNum(visual) 


# checks the possible options for 3 in a row and if any are all held by one side returns true 
def checkWin(board, winConditions, ai): 
    if ai == True: 
     win = 3 
    if ai == False: 
     win = -3 
    for row in winConditions: 
     checkA = board[row[0]] 
     checkB = board[row[1]] 
     checkC = board[row[2]] 
     if checkA + checkB + checkC == int(win): 
      return True 

    return False 

def checkDraw(board): 
    emptyTile = 9 
    for tile in board: 
     if tile != 0: 
      emptyTile -= 1 
    if emptyTile == 0: 
     completion(2) 

def availableMoves(board, bonus): 
    availableSlots = [] 
    for position in range(0,9): 
     if board[position] == 0: 
      availableSlots.append(position + bonus) 
    return availableSlots 



def playerTurn(board, remainingTurns): 
    board = board 
    checkDraw(board) 
    visual =drawBoard() 
    print("pick one of the available slots \n") 
    availableSlots = availableMoves(board, 1) 
    print(availableSlots) 
    choice = int(input('Select a tile from those shown above:\n')) -1 
    while True:  
     if 0 <= choice <= 8: 
      if board[choice] == 0: 
       board[choice] = -1 
       break 
      else: 
       choice = int(input('Select a tile from those shown above which has not already been selected:\n')) -1 
     else: 
      choice = int(input('Select a tile from those shown above:\n')) -1 
    visual = drawBoard() 
    if checkWin(board, winConditions, False) == True: 
     completion(0) 
    else: 
     aiTurn(board, remainingTurns - 1) 


class Node(object): 

    def __init__(self, remainingTurns, playerNum, board, value = 0): 
     self.depth = remainingTurns 
     self.playerNum = playerNum 
     self.board = board 
     self.value = value 
     self.moves = availableMoves(self.board, 0) 
     self.children = [] 
     self.createChildren() 

    def availableMoves(self, board): 
     self.availableSlots = [] 
     for position in range(0,9): 
      if board[position] == 0: 
       availableSlots.append(position) 
     return self.availableSlots 

    def winCheck(self, state, playerNum): 
     self.winConditions = [[0, 1, 2],[3, 4, 5],[6, 7, 8],[0, 3, 6],[1, 4, 7],[2, 5, 8],[0, 4, 8],[2, 4, 6]] 
     self.win = 3 
     for row in self.winConditions: 
      self.checkA = self.state[row[0]] 
      self.checkB = self.state[row[1]] 
      self.checkC = self.state[row[2]] 
      if self.checkA + self.checkB + self.checkC == int(self.win * self.playerNum): 
       return True 
     return False 

    def createChildren(self): 
     if self.depth > 0: 
      for i in self.moves: 
       self.state = self.board 
       self.state[i] = self.playerNum 
       print(board) 
       self.children.append(Node(self.depth - 1, self.playerNum * -1, self.state, self.realVal(self.state, self.playerNum))) 


    def realVal(self, value, playerNum): 
     value = self.winCheck(self.state, self.playerNum) 
     if value == True: 
      return maxsize * self.playerNum 
     else: 
      return 0 




def minimax(node, depth, playerNum): 
    if depth == 0 or abs(node.value) == maxsize: 
     return node.value 

    bestValue = maxsize * -playerNum 

    for i in range(len(node.children)): 
     child = node.children[i] 
     val = minimax(child, depth - 1, -playerNum) 
     if (abs(maxsize * playerNum - val) < abs(maxsize * playerNum - bestValue)): 
      bestValue = val 
    return bestValue 


def aiTurn(board, remainingTurns): 
    checkDraw(board) 
    print('Waiting for ai') 
    time.sleep(2) 
    board = board 
    state = board 
    currentPlayer = 1 
    tree = Node(remainingTurns, currentPlayer, state) 
    bestChoice = -100 
    bestValue = maxsize * -1 
    for i in range(len(tree.children)): 
     n_child = tree.children[i] 
     i_val = minimax(n_child, remainingTurns, -currentPlayer,) 
     if (abs(currentPlayer * maxsize - i_val) <= abs(currentPlayer * maxsize - bestValue)): 
      bestValue = i_val 
      bestChoice = i 
    print(bestChoice) 
    print(board) 
    #choice = minimax(tree, remainingTurns, 1) 
    board[bestChoice] = 1 
    print(board) 
    if checkWin(board, winConditions, True) == True: 
     completion(1) 
    else: 
     playerTurn(board, remainingTurns - 1) 



def completion(state): 
    if state == 1: 
     print('The computer has won this game.') 
     choice = str(input('press y if you would like to play another game; Press n if you would not \n')) 
     if choice == 'y' or choice == 'Y': 
      playGame() 
     else: 
      sys.exit() 
    if state == 0: 
     print('you win!') 
     choice = str(input('press y if you would like to play another game; Press n if you would not \n')) 
     if choice == 'y' or choice == 'Y': 
      playGame() 
     else: 
      sys.exit() 
    if state == 2: 
     print('you drew') 
     choice = str(input('press y if you would like to play another game; Press n if you would not \n')) 
     if choice == 'y' or choice == 'Y': 
      playGame() 
     else: 
      sys.exit()   




def playGame(): 
    global board 
    board = [0,0,0,0,0,0,0,0,0] 

    global winConditions 
    winConditions = [ 
       [0, 1, 2], 
       [3, 4, 5], 
       [6, 7, 8], 
       [0, 3, 6], 
       [1, 4, 7], 
       [2, 5, 8], 
       [0, 4, 8], 
       [2, 4, 6] 
       ] 


    global remainingTurns 
    remainingTurns = 9 
    playerFirst = random.choice([True, False]) 

    if playerFirst == True: 
     playerTurn(board, remainingTurns) 
    else: 
     aiTurn(board, remainingTurns) 


if __name__ == '__main__': 
    playGame() 

これは、上記のコードの出力

[1, 0, 0, 0, 0, 0, 0, 0, 0] 
[1, -1, 0, 0, 0, 0, 0, 0, 0] 
[1, -1, 1, 0, 0, 0, 0, 0, 0] 
[1, -1, 1, -1, 0, 0, 0, 0, 0] 
[1, -1, 1, -1, 1, 0, 0, 0, 0] 
[1, -1, 1, -1, 1, -1, 0, 0, 0] 
[1, -1, 1, -1, 1, -1, 1, 0, 0] 
[1, -1, 1, -1, 1, -1, 1, -1, 0] 
[1, -1, 1, -1, 1, -1, 1, -1, 1] 
[1, -1, 1, -1, 1, -1, 1, -1, -1] 
[1, -1, 1, -1, 1, -1, 1, 1, -1] 
[1, -1, 1, -1, 1, -1, 1, 1, 1] 
[1, -1, 1, -1, 1, -1, -1, 1, 1] 
[1, -1, 1, -1, 1, -1, -1, -1, 1] 
[1, -1, 1, -1, 1, -1, -1, -1, -1 
[1, -1, 1, -1, 1, 1, -1, -1, -1] 
[1, -1, 1, -1, 1, 1, 1, -1, -1] 
[1, -1, 1, -1, 1, 1, 1, 1, -1] 
[1, -1, 1, -1, 1, 1, 1, 1, 1] 
[1, -1, 1, -1, -1, 1, 1, 1, 1] 
[1, -1, 1, -1, -1, -1, 1, 1, 1] 
[1, -1, 1, -1, -1, -1, -1, 1, 1] 
[1, -1, 1, -1, -1, -1, -1, -1, 1 
[1, -1, 1, -1, -1, -1, -1, -1, - 
[1, -1, 1, 1, -1, -1, -1, -1, -1 
[1, -1, 1, 1, 1, -1, -1, -1, -1] 
[1, -1, 1, 1, 1, 1, -1, -1, -1] 
[1, -1, 1, 1, 1, 1, 1, -1, -1] 
[1, -1, 1, 1, 1, 1, 1, 1, -1] 
[1, -1, 1, 1, 1, 1, 1, 1, 1] 
[1, -1, -1, 1, 1, 1, 1, 1, 1] 
[1, -1, -1, -1, 1, 1, 1, 1, 1] 
[1, -1, -1, -1, -1, 1, 1, 1, 1] 
[1, -1, -1, -1, -1, -1, 1, 1, 1] 
[1, -1, -1, -1, -1, -1, -1, 1, 1 
[1, -1, -1, -1, -1, -1, -1, -1, 
[1, -1, -1, -1, -1, -1, -1, -1, 
[1, 1, -1, -1, -1, -1, -1, -1, - 
[1, 1, 1, -1, -1, -1, -1, -1, -1 
[1, 1, 1, 1, -1, -1, -1, -1, -1] 
[1, 1, 1, 1, 1, -1, -1, -1, -1] 
[1, 1, 1, 1, 1, 1, -1, -1, -1] 
[1, 1, 1, 1, 1, 1, 1, -1, -1] 
[1, 1, 1, 1, 1, 1, 1, 1, -1] 
[1, 1, 1, 1, 1, 1, 1, 1, 1] 
8 
[1, 1, 1, 1, 1, 1, 1, 1, 1] 
[1, 1, 1, 1, 1, 1, 1, 1, 1] 
The computer has won this game. 

任意の提案ですか?ですか

答えて

0

問題は、あなたがあなたのノードを初期化するときにだけboardの参照をコピーある:

self.board = board 

すべてのあなたのNodeオブジェクトは、同じボードを参照値エルス

self.board = board[::] 

をコピーする必要があり、一方:グローバルなもの。

関連する問題