1

I am a complete beginner with Python and coding in general. I am making a Tic Tac Toe game in Python as part of the online course I am studying.

I've struggled with getting my head around the nitty gritty of how functions work and can be utilised. I have had to follow the course notes quite closely to try and understand what is happening once the code starts fitting together. Can't find similar problems on here so it can't be an issue with the course notes!

When I run the programme, it skips my position_choice() function, displays the empty board and then asks to replay. I feel I'm missing some basic issue like indentation, but would really appreciate if anyone is able to spot a problem with the function itself or the code set up? It follows the course notes structure almost identically and I'm at a loss!

Here are the functions:

from IPython.display import clear_output
import random

def display_board(board):
    clear_output()

    print(' ' + board[7] + ' ' + '|' + ' ' + board[8] + ' ' + '|' + ' ' + board[9] + ' ')
    print('- - - - - -')
    print(' ' + board[4] + ' ' + '|' + ' ' + board[5] + ' ' + '|' + ' ' + board[6] + ' ')
    print('- - - - - -')
    print(' ' + board[1] + ' ' + '|' + ' ' + board[2] + ' ' + '|' + ' ' + board[3] + ' ')


def player_choice():

    player1 = input('Choose your marker: '.upper())

    while True:
        if player1.upper() == 'X':
            player2 = 'O'
            print('\nPlayer 1 is ' + player1.upper() + '\nPlayer 2 is ' + player2 + '.')
            return player1.upper(), player2
        elif player1.upper() == 'O':
            player2 = 'X'
            print('\nPlayer 1 is ' + player1.upper() + '\nPlayer 2 is ' + player2 + '.')
            return player1.upper(), player2
        else:
            print('Sorry, that is not a valid marker. Please choose either O or X.')
            player1 = input('Choose your marker: '.upper())


def place_marker(board, marker, position):

    board[position] = marker


def win_check(position, mark):

    return ((position[7] == position[8] == position[9] == mark)
    or (position[4] == position[5] == position[6] == mark)
    or (position[1] == position[2] == position[3] == mark)
    or (position[1] == position[5] == position[9] == mark)
    or (position[7] == position[5] == position[3] == mark)
    or (position[7] == position[4] == position[1] == mark)
    or (position[8] == position[5] == position[2] == mark)
    or (position[9] == position[6] == position[3] == mark))


def choose_first():
    rand_int = random.randint(1,2)

    if rand_int == 1:
        print('Player 1 goes first')
        return '1'
    if rand_int == 2:
        print('Player 2 goes first')
        return '2'


def space_check(board, position):

    return board[position] == ' '


def full_board_check(board):

    for position in range(1,10):
        if space_check(board, position):
            return False

    return True


def position_choice(board):

    position = 0

    while position not in [1,2,3,4,5,6,7,8,9] and not space_check(board, position):
        position = int(input('Please choose your position: '))
    
    return position


def replay():

    return input('Do you want to play again?').lower().startswith('y')


def play_game():

    play_game = input('Do you want to play?')

    if play_game.lower()[0] == 'y':
        return True
    else:
        return False

And here's the programme code. Why does it just display the empty board, skip asking for the position, and ask for the replay? Any help would keep up my stalling motivation!!

print('Welcome to Tic Tac Toe!')

while play_game():

    theboard = [' '] * 10
    player1_marker, player2_marker = player_choice()
    turn = choose_first()

    if turn == 1:
        display_board(theboard)
        position = position_choice(theboard)
        place_marker(theboard, player1_marker, position)
        
        if win_check(theboard, player1_marker):
            display_board(theboard)
            print('Player 1 is the winner!')
            replay()
        else:
            if full_board_check(theboard):
                display_board(theboard)
                print('The game is a tie!')
                replay()
            else:
                turn == 2
    
    else:
        display_board(theboard)
        position = position_choice(theboard)
        place_marker(theboard, player2_marker, position)
        
        if win_check(theboard, player2_marker):
            display_board(theboard)
            print('Player 2 is the winner!')
            replay()
        else:
            if full_board_check(theboard):
                display_board(theboard)                    
                print('The game is a tie!')
                replay()
            else:
                turn == 1
            
    if not replay():
        break
Skegger
  • 21
  • 1
  • 1
    Do you get the prompt 'p'lease choose your position: ? – balderman Sep 01 '20 at 13:46
  • There are a number of other issues, but the issue you mention about asking for position is because of this line: while position not in [1, 2, 3, 4, 5, 6, 7, 8, 9] and not space_check(board, position): - This expression is evaluating to false because of your call to space_check function. – John Greenfield Sep 01 '20 at 14:43
  • Part of your learning adventure should be developing ways to debug your programs. Printing *stuff* can be very effective. Look at your code find places where you can print *stuff* that will tell you what is happening. *Stuff* can be values, conditions, calculation results, function return values - anything that will tell you which part is working and which is not. One excellent feature of functions is that they can be tested independent of the rest of the program with known inputs - test/fix each function first before you run the program. – wwii Sep 01 '20 at 14:54
  • If you are using an IDE **now** is the time to learn its debugging features, most should have a way to step through the code line by line and let you inspect variables, most will have other features. You should learn them **now**. It is probably worthwhile to set aside an afternoon to learn/play-with [Python's built-in debugger](https://docs.python.org/3/library/pdb.html) - it will be like an overview for things to look for in your IDE's debugger, Try using `pdb` with some of your functions. – wwii Sep 01 '20 at 15:01
  • Pretend you are the interpreter. Use pencil and paper and execute each statement in sequence recording the result on the paper - keep track of variables, function arguments, conditional results - till you find something that behaved different than you thought, fix that and repeat. – wwii Sep 01 '20 at 15:03
  • Thanks so much for the debugger tip, had no idea this was a feature. I definitely need to sit down and deconstruct and analyse the code to understand how everything functions and interacts. – Skegger Sep 03 '20 at 21:24

2 Answers2

0

There are several problems :

  • The choose_first returns a String instead of an integer.
  • The method called in the while, always ask if you want to play.
  • You recreate a new board on each loop, you have to declare it before the loop if you don't want to lose it.
  • At the end of each loop you ask each times if you want to replay
  • to change the turn variable you should do turn = 2 instead of using double equals witch is comparing equality.
  • And when you want to "replay", don't forget to reset the board.

To debug this, you should comment a part of your code. And run it step by step. By doing this, you will find were are the errors.

Here is the code, the game will works but you may still want to ad some improvements.

theboard = [' '] * 10
if play_game():
    player1_marker, player2_marker = player_choice()
    turn = choose_first()
    while not full_board_check(theboard):
        display_board(theboard)
        position = position_choice(theboard)
        if turn == 1:
            place_marker(theboard, player1_marker, position)

            if win_check(theboard, player1_marker):
                display_board(theboard)
                print('Player 1 is the winner!')
                if replay():
                    theboard = [' '] * 10
                else:
                    break
            turn = 2

        else:
            place_marker(theboard, player2_marker, position)
            if win_check(theboard, player2_marker):
                display_board(theboard)
                print('Player 2 is the winner!')
                if replay():
                    theboard = [' '] * 10
                else:
                    break
            turn = 1

        if full_board_check(theboard):
            display_board(theboard)
            print('The game is a tie!')
            if replay():
                theboard = [' '] * 10
            else:
                break
AlexisG
  • 2,476
  • 3
  • 11
  • 25
  • Many thanks for the reply! I'll have a play around with this code and see how everything has changed and hopefully something will click! Cheers – Skegger Sep 03 '20 at 21:24
0

Why does it just display the empty board, skip asking for the position, and ask for the replay?

position not in [1,2,3,4,5,6,7,8,9] and not space_check(board, position) - this condition isn't working, the logic is wrong.

>>> theboard = [' '] * 10
>>> theboard
[' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
>>> position = 0
>>> position not in [1,2,3,4,5,6,7,8,9] and not space_check(theboard, position)
False
>>>

Here is one way to refactor position_choice

def position_choice(board):
    #print(board)
    #position = 0
    valid = False
    # keep asking till thay give a valid answer
    while not valid:
        position = int(input('Please choose your position (1-9): '))
        valid = position in [1,2,3,4,5,6,7,8,9]
        valid = valid and space_check(board, position)
    return position

##    OLD STUFF    
##    while position not in [1,2,3,4,5,6,7,8,9] and not space_check(board, position):
##        position = int(input('Please choose your position: '))
##    
##    return position

Asking the user for input until they give a valid response
How to debug small programs

wwii
  • 23,232
  • 7
  • 37
  • 77
  • Thanks for the reply. I need to really go through each function and play with it to see how its working. Seems like checking what something is NOT rather than IS appears a better way to validate input. Cheers – Skegger Sep 03 '20 at 21:26