Search code examples
pythonwhile-loop

Python skips half of a while loop and the while loop inside of it but runs the code after the nested while loop


In this terminal game I am working on, a while loop asks you to guess a word with a certain number of letters (represented in the variable diff but you + 2 to get the actual number of letters). However, in the code below, it skips to the line where it uses the type() function to ask if you want to play again. All of the variables such as stop diff and guess are all defined at the start. I am using Python 3.12.1.

-Code snippet (where problem occurs)

while stop not in ['y']:
    roll()
    if "\'" in word:
        roll()
    print(word)
    while word != guess:
        type("\nYour guess...")
        guess = input(" ")
        guess = guess.lower()
        if len(guess) != diff + 2:
            type(f'\nYour guess has to be at least {diff+2} characters long.')
        for i in range(len(guess)):
            if guess[i] == word[i]:
                print(f"{bcolors.OKGREEN}{guess[i]}{bcolors.ENDC}", end = '')
            elif guess[i] in word:
                print(f"{bcolors.WARNING}{guess[i]}{bcolors.ENDC}", end = '')
            else:
                print(f"{bcolors.FAIL}{guess[i]}{bcolors.ENDC}", end = '')
    type('\nWould you like to play again or stop? (a/s)')
    ans = input(" ")
    if ans == 's':
        stop = 'y'

-Full code (in case the problem occurs elsewhere)

import nltk
from nltk.corpus import brown
from time import sleep
from os import *
from random import *
import sys
import os.path

def type(phrase, speed = 1):
    a = 0
    for i in range (len(phrase)):
        print(phrase[a], end='', flush=True)
        c = phrase[a]
        if c == '.' or c=='!' or c=='?':
            sleep(0.5/speed)
        elif c == ',':
            sleep(0.25/speed)
        else:
            sleep(0.05/speed)
        a+=1

word = ''
diff = ''
stop = ''
guess = ''

def roll():
    word = (word_list[randint(0, len(word_list)-1)])
    word = word.lower()

nltk.download('brown')
common_words = set(brown.words())

common_known_words = sorted(set(common_words))

threelw = [word for word in common_known_words if len(word) == 3]
fourlw = [word for word in common_known_words if len(word) == 4]
fivelw = [word for word in common_known_words if len(word) == 5]
sixlw = [word for word in common_known_words if len(word) == 6]

class bcolors:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKCYAN = '\033[96m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'

system('cls')

type(f"Welcome to...")
type('''
░▒▓█▓▒░      ░▒▓█▓▒░▒▓███████▓▒░ ░▒▓██████▓▒░ ░▒▓██████▓▒░  
░▒▓█▓▒░      ░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ 
░▒▓█▓▒░      ░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░      ░▒▓█▓▒░░▒▓█▓▒░ 
░▒▓█▓▒░      ░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒▒▓███▓▒░▒▓█▓▒░░▒▓█▓▒░ 
░▒▓█▓▒░      ░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ 
░▒▓█▓▒░      ░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ 
░▒▓████████▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓██████▓▒░ ░▒▓██████▓▒░  ''', 45)
print("\n")
sleep(1)
type("The game where you get a word and you have to guess it in as little guesses possible.")
type('''\nWhat difficulty would you like to play at?:\n[1] 3 letter words\n[2] 4 letter words\n[3] 5 letter words\n[4] 6 letter words\n''')

while diff not in ['1', '2', '3', '4', '5']:
    diff = input("\n(1/2/3/4): ")
    if diff == '1':
        word_list = threelw
    elif diff == '2':
        word_list = fourlw
    elif diff == '3':
        word_list = fivelw
    elif diff == '4':
        word_list = sixlw
    else:
        type("Invalid input. Try again.")

diff = int(diff)

while stop not in ['y']:
    roll()
    if "\'" in word:
        roll()
    print(word)
    while word != guess:
        type("\nYour guess...")
        guess = input(" ")
        guess = guess.lower()
        if len(guess) != diff + 2:
            type(f'\nYour guess has to be at least {diff+2} characters long.')
        for i in range(len(guess)):
            if guess[i] == word[i]:
                print(f"{bcolors.OKGREEN}{guess[i]}{bcolors.ENDC}", end = '')
            elif guess[i] in word:
                print(f"{bcolors.WARNING}{guess[i]}{bcolors.ENDC}", end = '')
            else:
                print(f"{bcolors.FAIL}{guess[i]}{bcolors.ENDC}", end = '')
    type('\nWould you like to play again or stop? (a/s)')
    ans = input(" ")
    if ans == 's':
        stop = 'y'

I tried changing the format of the while loop (from while stop != 'y' to while stop not in ['y']) and messing with indentation. I was expecting Python to run the whole (non nested) while loop untill you guessed the word right.


Solution

  • This function is the problem:

    def roll():
        word = (word_list[randint(0, len(word_list)-1)])
        word = word.lower()
    

    Inside of this function, word is a local variable. It has no effect on the global variable of the same name.

    So at the global level, word is still a blank string, and the while word != guess loop exits immediately, because guess is also a blank string.

    If you want a function to assign to a global variable, you have to tell the function that it is global, by using the global keyword:

    def roll():
        global word
        word = (word_list[randint(0, len(word_list)-1)])
        word = word.lower()