Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Won't let me end a loop
#1
I've been given a task to make a text based two player game of noughts & crosses. I made a variable called gameRun which would keep the game going if it was true. I then tried to make this variable become false when one of the players (only player one at the moment) gets a line, and therefore end the game, but it just prints that player one wins and then continues the game. Any idea how to fix this?

grid = [1, 2, 3,
        4, 5, 6,
        7, 8, 9]

gridSave = [1, 2, 3,
            4, 5, 6,
            7, 8, 9]

gameRun = True

def show():
    print(grid[0], '|', grid[1], '|', grid[2])
    print('----------')
    print(grid[3], '|', grid[4], '|', grid[5])
    print('----------')
    print(grid[6], '|', grid[7], '|', grid[8])

def checkX():
    
    if grid[0] == 'X' and grid[1] == 'X' and grid[2] == 'X':
        print("Player one wins!")
        gameTrue = False
    
    if grid[3] == 'X' and grid[4] == 'X' and grid[5] == 'X':
        print("Player one wins!")
        gameTrue = False

    if grid[6] == 'X' and grid[7] == 'X' and grid[8] == 'X':
        print("Player one wins!")
        gameTrue = False
        

    if grid[0] == 'X' and grid[3] == 'X' and grid[6] == 'X':
        print("Player one wins!")
        gameTrue = False

    if grid[1] == 'X' and grid[4] == 'X' and grid[7] == 'X':
        print("Player one wins!")
        gameTrue = False

    if grid[2] == 'X' and grid[5] == 'X' and grid[8] == 'X':
        print("Player one wins!")
        gameTrue = False
        

    if grid[0] == 'X' and grid[4] == 'X' and grid[8] == 'X':
        print("Player one wins!")
        gameTrue = False

    if grid[2] == 'X' and grid[4] == 'X' and grid[6] == 'X':
        print("Player one wins!")
        gameTrue = False
        

show()

while gameRun == True:

    inputX = input("Player one, please select a spot: ")
    inputX = (int(inputX) - 1)
    
    if grid[inputX] != 'X' and grid[inputX] != 'O':
        grid[inputX] = 'X'

    else:
        print("This space is taken!")

    show()

    checkX()

    inputY = input("Player two, please select a spot: ")
    inputY = (int(inputY) - 1)
    
    if grid[inputY] != 'X' and grid[inputY] != 'O':
        grid[inputY] = 'O'

    else:
        print("This space is taken!")

    show()

    

if gameRun == False: 

    print("The game is now finished! Play again!")
    grid = gridSave
    print(grid)
    gameRun = True
Reply
#2
It's not leaving the loop because you never change gameRun. You only change gameTrue, not gameRun. Furthermore, you are only changing gameTrue within the checkX function. Even if you changed that to gameRun, it would be a different gameRun. This is called the scope of the variable. What you need to do is put the following line at the end of the definition of checkX: return gameTrue. That will make the value of any call to checkX the value of gameTrue when it ran. Then, in your loop, change the call to checkX to gameRun = checkX(). That will change gameRun to False whenever someone wins the game, ending the game
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#3
I can't believe I didn't realise they were two different things lmao, thank you! But now it's coming up with an error message, saying 'UnboundLocalError: local variable 'gameRun' referenced before assignment'.
Reply
#4
How exactly did you change your code, and what is the full traceback (error message).
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#5
Here's my code now, and the error message:

Error:
Traceback (most recent call last): File "C:\Users\...\noughts and crosses.py", line 72, in <module> gameRun = checkX() File "C:\Users\...\noughts and crosses.py", line 54, in checkX return gameRun UnboundLocalError: local variable 'gameRun' referenced before assignment
grid = [1, 2, 3,
        4, 5, 6,
        7, 8, 9]

gridSave = [1, 2, 3,
            4, 5, 6,
            7, 8, 9]

gameRun = True

def show():
    print(grid[0], '|', grid[1], '|', grid[2])
    print('----------')
    print(grid[3], '|', grid[4], '|', grid[5])
    print('----------')
    print(grid[6], '|', grid[7], '|', grid[8])

def checkX():
    
    if grid[0] == 'X' and grid[1] == 'X' and grid[2] == 'X':
        print("Player one wins!")
        gameRun = False
    
    if grid[3] == 'X' and grid[4] == 'X' and grid[5] == 'X':
        print("Player one wins!")
        gameRun = False

    if grid[6] == 'X' and grid[7] == 'X' and grid[8] == 'X':
        print("Player one wins!")
        gameRun = False
        

    if grid[0] == 'X' and grid[3] == 'X' and grid[6] == 'X':
        print("Player one wins!")
        gameRun = False

    if grid[1] == 'X' and grid[4] == 'X' and grid[7] == 'X':
        print("Player one wins!")
        gameRun = False

    if grid[2] == 'X' and grid[5] == 'X' and grid[8] == 'X':
        print("Player one wins!")
        gameRun = False
        

    if grid[0] == 'X' and grid[4] == 'X' and grid[8] == 'X':
        print("Player one wins!")
        gameRun = False

    if grid[2] == 'X' and grid[4] == 'X' and grid[6] == 'X':
        print("Player one wins!")
        gameRun = False

    return gameRun
        

show()

while gameRun == True:

    inputX = input("Player one, please select a spot: ")
    inputX = (int(inputX) - 1)
    
    if grid[inputX] != 'X' and grid[inputX] != 'O':
        grid[inputX] = 'X'

    else:
        print("This space is taken!")

    show()

    gameRun = checkX()

    inputY = input("Player two, please select a spot: ")
    inputY = (int(inputY) - 1)
    
    if grid[inputY] != 'X' and grid[inputY] != 'O':
        grid[inputY] = 'O'

    else:
        print("This space is taken!")

    show()

    

if gameRun == False: 

    print("The game is now finished! Play again!")
    grid = gridSave
    print(grid)
    
Reply
#6
I see. If there is no win, gameRun never gets defined in checkX. I should have seen that coming. To fix that, put gameRun = True at the beginning of checkX.

You're going to have another problem. gameRun is being changed in the middle of the loop. So after player one wins, it asks player two to make a move. Also, it never checks if player two wins. I think you should generalize your code, so that each time through the loop, one player moves. Have a playerNumber variable that is 'one' or 'two', and a playerSymbol variable that is 'X' or 'O'. Then after one player moves, switch those variables and loop back for the next player.

Then generalize your check code, so it can check for X or O, depending on what you ask it to do. So have checkX accept a symbol parameter, and then check the grid locations against symbol instead of 'X'.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#7
Wait, so how can I fix it so that it stops player 2 from having to make a move if player 1 wins?
Reply
#8
I explained that in the second part of my post, which part did you not understand? It would be something like this:

playerName = 'one'
playerSymbol = 'two'
while True:
    move = input('Player {} make a move:'.format(playerName))
    print('Player one moved with an {}.'.format(playerSymbol))
    if playerName == 'one':
        playerName = 'two'
        playerSymbol = 'O'
    else:
        playerName = 'one'
        playerSymbol = 'X'
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020