Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
138 views
in Technique[技术] by (71.8m points)

python - Tic-Tac-Toe Game - Errors and AI

import random

def game():

def display_instructions():
    """ Will print out instructions for how to play tic-tac-toe"""
    print("Hello, and welcome to TIC-TAC-TOE! Here's how you play: you will choose whether you want to be X or O. I will tell you who is going first. When it is your turn, you will choose any number from zero to eight. The number you choose corresponds to the space you will be putting your letter in. Be careful not to choose a space already occupied by a letter! You will have to enter a new number. Your goal is to beat ME. The first one to get to three-in-a-row, sideways, up-and-down, or diagonally, wins. May the best man win.")    
    print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
    print("LET'S BEGIN")
display_instructions()




def assign_x_o():
    """ Allows the user to choose whether to be X or O """
    player_letter = input("Would you like to be X or O?")
    return player_letter

player_letter = assign_x_o()




def tell_letter():
    """ Tells the user who will be X and who will be O """
    print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
    print("You will be", player_letter.upper() + "!")
    if player_letter.upper() == "X":
        print("I will be O!")
    else:
        print("I will be X!")

tell_letter()


not_used = [0, 1, 2, 3, 4, 5, 6, 7, 8]
    
def computer_letter():
    """ Assigns the computer letter to whatever the player letter is not """
    if player_letter.upper() == "X":
        comp_letter = "O"
    else:
        comp_letter = "X"
    return comp_letter

comp_letter = computer_letter()




board_list = ["0","1","2","3","4","5","6","7","8"]

def display_board():
    """ Prints the Tic-Tac-Toe board """
    print(board_list[0] + "|" + board_list[1] + "|" + board_list[2])
    print("-+-+-")
    print(board_list[3] + "|" + board_list[4] + "|" + board_list[5])
    print("-+-+-")
    print(board_list[6] + "|" + board_list[7] + "|" + board_list[8])

display_board()




def ask_num():
    """ Asks the user to input a number from 0-8, corresponding to the spot to which they would like to move """
    user_turn = input("Which place would you like to move to? (Input a number, 0-8)")
    return user_turn




def second_board(board_list):
    """ Creates a second board with which to test possible moves for the computer """
    new_board = []
    for i in board_list:
        new_board.append(i)
    return new_board

        


def check_win(board_list, player_letter, comp_letter):
    """ Checks to see if there are three of X or O in a row (up, down, and diagonal) """
    if board_list[0] == board_list[1] == board_list[2]:
        return True
    if board_list[3] == board_list[4] == board_list[5]:          
        return True
    if board_list[6] == board_list[7] == board_list[8]:
        return True
    if board_list[0] == board_list[3] == board_list[6]:
        return True
    if board_list[1] == board_list[4] == board_list[7]:
        return True
    if board_list[2] == board_list[5] == board_list[8]:
        return True
    if board_list[0] == board_list[4] == board_list[8]:
        return True
    if board_list[2] == board_list[4] == board_list[6]:
        return True
    return False




def test_moves(board_list, player_letter, comp_letter, i):
     """ Tests possible moves for the computer on a duplicate tic tac toe board """
     new_board = second_board(board_list)
     new_board[i] = player_letter.upper()
     return check_win(board_list, player_letter, comp_letter)



    


def win_in_one(board_list):
    temp_board = board_list
    print(not_used)
    for i in not_used:
        for i in range(0, 1):
            temp_board[i] = comp_letter
            if check_win(temp_board, player_letter, comp_letter) == True:
                win = True
                if win == True:
                    return i
            else:
                win = check_win(temp_board, player_letter, comp_letter) == False
                return win
            
            
def lose_in_one(board_list):
    temp_board = board_list
    for i in not_used:
        for i in range(0, 1):
            temp_board[i] = player_letter
            if check_win(temp_board, player_letter, comp_letter) == True:
                lose = True
                if lose == True:
                    temp_board[i] = comp_letter
                    return i
                else:
                    lose = False
                    return lose
        

def computer_turn(board_list):
    """ Chooses which index value to use based on available spaces; first checks open corners, then the center, then the remaining side spaces """
    win_in_one(board_list)
    lose_in_one(board_list) 
    for i in range(0, 8):
        if board_list[i] != "X" and board_list[i] != "O" and test_moves(board_list, player_letter, comp_letter, i):
            return i
    for i in range(0, 8):
        if board_list[i] != "X" and board_list[i] != "O" and test_moves(board_list, player_letter, comp_letter, i):
            return i
    for i in [0, 2, 6, 8]:
        if board_list[i] != "X" and board_list[i] != "O":
            return i
    if board_list[4] != "X" and board_list[4] != "O":
        return 4 
    for i in [1, 3, 5, 7]:
        if board_list[i] != "X" and board_list[i] != "O":
            return i
    



def draw_message():
    """ Prints a message notifying the user that the game has ended in a tie """
    print("This game has ended in a tie!")
    play_again = input("Would you like to play again? (y/n) ")
    if play_again.lower() == "y":
        keep_playing()
    else:
        print("No worries. Let's play again soon!")



def keep_playing():
    """ Calls the game function again if the user chooses to continue playing """

    game()




def congrats():
    """ Decides whether or not to congratulate the user or to tell them the computer won; also gives the option to play the game again """
    if board_list[0] == board_list[1] == board_list[2] == player_letter.upper():
        print("Congrats! You are the winner!")
        play_again = input("Would you like to play again? (y/n) ")
        if play_again.lower() == "y":
            keep_playing()
        else:
            print("No worries. Let's play again soon!")
    elif board_list[3] == board_list[4] == board_list[5] == player_letter.upper():
        print("Congrats! You are the winner!")
        play_again = input("Would you like to play again? (y/n) ")
        if play_again.lower() == "y":
            keep_playing()
        else:
            print("No worries. Let's play again soon!")
    elif board_list[6] == board_list[7] == board_list[8] == player_letter.upper():
        print("Congrats! You are the winner!")
        play_again = input("Would you like to play again? (y/n) ")
        if play_again.lower() == "y":
            keep_playing()
        else:
            print("No worries. Let's play again soon!")
    elif board_list[0] == board_list[3] == board_list[6] == player_letter.upper():
        print("Congrats! You are the winner!")
        play_again = input("Would you like to play again? (y/n) ")
        if play_again.lower() == "y":
            keep_playing()
        else:
            print("No worries. Let's play again soon!")
    elif board_list[1] == board_list[4] == board_list[7] == player_letter.upper():
        print("Congrats! You are the winner!")
        play_again = input("Would you like to play again? (y/n) ")
        if play_again.lower() == "y":
            keep_playing()
        else:
            print("No worries. Let's play again soon!")
    elif board_list[2] == board_list[5] == board_list[8] == player_letter.upper():
        print("Congrats! You are the winner!")
        play_again = input("Would you like to play again? (y/n) ")
        if play_again.lower() == "y":
            keep_playing()
        else:
            print("No worries. Let's play again soon!")
    elif board_list[0] == board_list[4] == board_list[8] == player_letter.upper():
        print("Congrats! You are the winner!")
        play_again = input("Would you like to play again? (y/n) ")
        if play_again.lower() == "y":
            keep_playing()
        else:
            print("No worries. Let's play again soon!")
    elif board_list[2] == board_list[4] == board_list[6] == player_letter.upper():
        print("Congrats! You are the winner!")
        play_again = input("Would you like to play again? (y/n) ")
        if play_again.lower() == "y":
            keep_playing()
        else:
            print("No worries. Let's play again soon!")
    else:
        print("Uh oh. Looks like I won! Better luck next time!")
        play_again = input("Would you like to play again? (y/n) ")
        if play_again.lower() == "y":
            keep_playing()
        else:
            print("No worries. Let's play again soon!")




tf_list = ["True", "False"]

user_first = random.choice(tf_list)

def first_turn():
    """ Uses user_first random choice to decide if the computer or user goes first, then prints who will start; if user starts, user will input a number and the board will be displayed; if computer starts, computer will take turn and display board"""
    if user_first == "True":
        print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
        print("You will start!")
        user_turn = int(ask_num())
        if board_list[user_turn] != "X" and board_list[user_turn] != "O":
            board_list[user_turn] = player_letter.upper()
            not_used.remove(user_turn)
            print(not_used)
            display_board()
    else:
        print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
        print("The computer will start!")
        if board_list[computer_turn(board_list)] != "X" and board_list[computer_turn(board_list)] != "O":
            board_list[computer_turn(board_list)] = comp_letter
            not_used.remove(computer_turn(board_list))
            display_board()
    
first_turn()




def next_turn(user_first):
    """ While playing, the computer and user will alternate turns. Upon either of them achieving three-in-a-row or a draw occurring, the user will be asked if they want to play again."&quot

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You could use this compact Computer player function as your AI:

from random import sample
axes = [(0,1,2),(3,4,5),(6,7,8),(0,3,6),(1,4,7),(2,5,8),(0,4,8),(2,4,6)] 

def isWin(board):
    return any(board[a]+board[b]+board[c] in ["XXX","OOO"] for a,b,c in axes)

#level 3**3=Naive, 3**4=beginner, 3**5=intermediate, 3**6=good, 3**7=expert

def rating(position,play,board,level=3**6):    
    if board[position] != " " or level < 3: return 0
    newBoard = board[:position]+[play]+board[position+1:]
    if isWin(newBoard): return level*2
    nextRatings = [rating(p,"XO"[play=="X"],newBoard,level/3) for p in range(9)]
    return level-max(nextRatings,key=abs)

To make the computer play (with some randomness), use this line where computer is the letter that the computer plays ("X" or "O") and board is a list of board positions (indexed from 0 to 8) containing "X", "O" or a space character:

position = max(sample(range(9),9),key=lambda p:rating(p,computer,board))

Here is some sample code using the computer playing function:

while True:
    board = [" "]*9
    player,computer = sample("XOXO",2)
    player = computer
    print(player,computer)
    while True:
        for r in range(0,9,3):
            print("("+") (".join(board[r:r+3])+")",list(range(r+1,r+4)))
        available = [str(p+1) for p in range(9) if board[p] == " "]
        if isWin(board) or not available : break
        player = "XO"[player=="X"]
        if player == computer:
            position = max(sample(range(9),9),key=lambda p:rating(p,computer,board))
            print(f"Computer plays {player} at {position+1}")
        else:
            while True:
                position = input(f"Position to play for {player}: ")
                if position not in available: print("Invalid position")
                else : position = int(position)-1; break
        board[position] = player
    print( f"{player}'s WIN !!!
" if isWin(board) else "DRAW.
")

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...