1

I am working on a tic-tac-toe program in python. Now, the Human's turn work's fine. However, the AI, after playing the first turn, does not play any further turns. I have scanned through the code and cannot seem to find any errors that can cause this.

Please ignore the comments and the part that deals with ties. I am still working on that.

import random
import copy
import sys


the_board = [" "]*10


def printboard(board):
    print(board[7] + " " + "|" + board[8] + " " + "|" + board[9])
    print("--------")
    print(board[4] + " " + "|" + board[5] + " " + "|" + board[6])
    print("--------")
    print(board[1] + " " + "|" + board[2] + " " + "|" + board[3])


def choose_player():
    while True:
        player = input("What do you want to be; X or O?")
        if player == "X":
            print("You chose X")
            comp = "O"
            break
        elif player == "O":
            print("You chose O")
            comp = "X"
            break
        else:
            print("Invalid Selection")
            continue
    return [player, comp]


def virtual_toss():
    print("Tossing to see who goes first.....")
    x = random.randint(0,1)
    if x== 0:
        print("AI goes first")
        move = "comp"
    if x == 1:
        print("Human goes first")
        move = "hum"
    return move


def win(board,le):
    if (board[7] == le and board[8] == le and board[9]==le) or (board[4] == le and board[5]==le and board[6] == le)or (board[1] == le and board[2]==le and board[3] == le)or (board[7] == le and board[5]==le and board[3] == le)or (board[9] == le and board[5]==le and board[1] == le)or (board[7] == le and board[4]==le and board[1] == le)or (board[8] == le and board[5]==le and board[2] == le)or (board[9] == le and board[6]==le and board[3] == le):
        return True
    else:
        return False


def make_move(board,number,symbol):
     board[number] = symbol


def board_full(board):
    count = 0
    for item in board:
        if item in ["X","O"]:
            count+= 1
    if count ==9 :
        return True
    else:
        return False


def valid_move(board,num):
    if board[num] == " ":
        return True
    else:
        return False


def player_move(board):
    number = int(input("Enter the number"))
    return number


def copy_board(board):
    copied_board = copy.copy(board)
    return copied_board


def check_corner(board):
    if (board[7] == " ") or (board[9] == " ") or (board[1] == " ") or (board[3] == " "):
        return True
    else:
        return False


def check_center(board):
    if (board[5] == " "):
        return True
    else:
        return False


while True:
    count = 0
    loop_break = 0
    print("welcome to TIC TAC TOE")
    pla,comp = choose_player()
    turn = virtual_toss()
    while True:
        #printboard(the_board)
        if board_full(the_board) == True:
            again = input ("Game is a tie. Want to try again? Y for yes and N for No")
            if again == "Y":
                loop_break = 6
                break
            else:
                system.exit()
#if loop_break == 6:
    #continue 

        if turn == "hum":


            while True:
                    number = player_move(the_board)
                    if (valid_move(the_board,number) == True) and not(board_full == False):
                        make_move(the_board,number,pla)
                        #printboard(the_board)
                        break
                    else:
                        print("Invalid Move, try again!")
                        continue
            if (win(the_board,pla) == True):
                print ("Yay, you won!!!")
                printboard(the_board)
                count = 1
                loop_break = 7 
                break
            else:
                turn = "comp"
                printboard(the_board)
                continue

        else:
            copied_board = copy_board(the_board)
            for i in range(1,10):
                make_move(copied_board,i,pla)
                if(win(copied_board,pla) == True):
                    make_move(the_board,i,comp)
                    printboard(the_board)
                    turn = "hum"
                    loop_break = 1
                    break
                else:
                    continue
            if loop_break == 1:
                continue
            if (check_corner(the_board) == True) or (check_center(the_board)==True):
                for i in [7,9,1,3,5]:
                    if(valid_move(copied_board,i)==True):
                        make_move(copied_board,i,comp)
                        if(win(copied_board,comp)==True):
                            make_move(the_board,i,comp)
                            printboard(the_board)
                            print("The AI beat you")
                            loop_break = 2
                            count = 1
                            break
                        else:
                            make_move(the_board,i,comp)
                            printboard(the_board)
                            turn = "hum"
                            loop_break = 3
                            break
                if loop_break == 2:
                    break
                elif loop_break == 3:
                    continue
                else:
                    for i in [8,4,6,2]:
                        if(valid_move(copied_board,i)==True):
                            make_move(copied_board,i,comp)
                            if(win(copied_board,comp)):
                                make_move(the_board,i,comp)
                                printboard(the_board)
                                print("The AI beat you")
                                count = 1
                                loop_break = 4
                                break
                            else:
                                make_move(the_board,i,comp)
                                printboard(the_board)
                                turn = "hum"
                                loop_break = 5
                                break
                if loop_break == 4:
                    break
                elif loop_break == 5:
                    continue

    if count == 1:
        again = input("Would you like to play again? y/n")
        if again == "y":
            continue
        else:
            system.exit()
halfer
  • 19,824
  • 17
  • 99
  • 186
  • 1
    Have you tried stepping through the code in a debugger? – FujiApple Aug 21 '16 at 08:58
  • @FujiApple : I am quite new to programming. How do I do that? – Swastik Mohapatra Aug 21 '16 at 09:06
  • What IDE (i.e. editor) are you using to write your code? Most decent IDEs provide a visual debugger, i.e. PyCharm has [this](https://www.jetbrains.com/help/pycharm/2016.1/stepping-through-the-program.html) – FujiApple Aug 21 '16 at 09:10
  • 1
    @SwastikMohapatra: see the [`pdb` module](https://docs.python.org/3/library/pdb.html) for a text-mode debugger. Your IDE may have a visual debugger. Or insert a lot more `print()` statements so you can follow what values variables have at different points. – Martijn Pieters Aug 21 '16 at 09:11
  • @SwastikMohapatra: IDLE has a visual debugger built-in. See https://inventwithpython.com/chapter7.html for a tutorial. – Martijn Pieters Aug 21 '16 at 09:13
  • Your bot doesn't do anything if this `if` doesn't trigger: `if (check_corner(the_board) == True) or (check_center(the_board)==True):`. – Aran-Fey Aug 21 '16 at 09:22
  • Also, in the `for i in range(1,10):` loop, you need to copy the board _every iteration_, not just before the loop. – Aran-Fey Aug 21 '16 at 09:26
  • @Rawing : I found out the problem. As you suggested, the board has to be copied every iteration. It works very well now. – Swastik Mohapatra Aug 21 '16 at 09:37
  • Can anyone suggest me any logic to prevent a "win-Fork" kind of situation, i.e, the user has 2 paths to win. How to code the AI To prevent that? – Swastik Mohapatra Aug 21 '16 at 09:38

1 Answers1

2

In a word, the problem of your AI is that it chose the same position all the times, which seems like "not playing any further turns".

To prove that, simply add a print in the for-loop of your AI:

for i in range(1,10):
    make_move(copied_board,i,pla)
    if(win(copied_board,pla) == True):
        make_move(the_board,i,comp)
        print("The AI chose #%d"%i)  # <-- here it is
        printboard(the_board)
        # ......

And here's the result.

welcome to TIC TAC TOE
What do you want to be; X or O?X
You chose X
Tossing to see who goes first.....
Human goes first
Enter the number1
  |  |
--------
  |  |
--------
X |  |
The AI chose #3
  |  |
--------
  |  |
--------
X |  |O
Enter the number2
  |  |
--------
  |  |
--------
X |X |O
The AI chose #3
  |  |
--------
  |  |
--------
X |X |O
Enter the number

I can't give a specific advice to solve this bug, as I totally didn't get the point of this AI #=_= (maybe you should use MiniMax). But anyway, your AI shouldn't place pieces at the same position.

ps. you might need to change system.exit() into sys.exit().

pps. the for-else grammar in Python is great for you.

ppps. "remove redundant parentheses", says PyCharm.

Community
  • 1
  • 1
xmcp
  • 3,347
  • 2
  • 23
  • 36
  • Well, I am kind of a newbie. Tried to design the AI myself and I guess I failed miserably :( Anyways, thanks a lot for your help. I will check out the links provided and try to fine tune my AI. – Swastik Mohapatra Aug 21 '16 at 09:41
  • @SwastikMohapatra this is [an MiniMax example](http://paste.ubuntu.com/23075036/) for tic tac toe in Python, written by me a year ago. it might help. – xmcp Aug 21 '16 at 09:53