简体   繁体   中英

Nested while loop, why this loop isnn't looping back to top?

I am trying to create a loop, that will rotate among users and get valid inputs. Inputs are dictionary words checked with external two files one containing allowed words and another restricted. It's a game where users have to say a word that starts with ending letter of their opponents' last word. You get up to 3 passes when you are out of words. When all three passes are takes, you lose the game. I have revised the code many times but it is not looping for some reason:

def game_logic(players_data):
"""takes in players data and initiates the game logic.

:param players_data: contains Player objects with name, word_list and pass_taken as attributes.
:type players_data: list containing dictionaries as items.
"""
# Initialise allowed and prohibited words from external file read.
with open("docs/wordDict.txt", "r") as wordDict:
    allowed_words = wordDict.read()
with open("docs/excludeWords.txt", "r") as excludeWords:
    prohibited_words = excludeWords.read()
game_switch = True
valid_word = False
player_turn = ""
start_letter = ""
while game_switch:
    player_turn = players_data[0].name
    if not players_data:             # iff empty list
        print("Something went wrong. I could not find players! Please restart the game.")
        break
    elif len(players_data) == 1:        # when one person is left
        print(f"{players_data[0].name} wins.\nCongratulations!\n°°*°°*°°*°°*°°*°°*° ")
        print(f"beat all opponents in: {playtime - datetime.datetime.now()}")
        break
    else:
        print(f"\nIt is {player_turn.upper()}'s turn")
        # add a copy of first element to the end
        players_data.append(players_data[0])
        # remove the first element. so that next turn is next ones'.
        players_data.remove(players_data[0])
        # start the game
        while not valid_word:
            if not start_letter:
                input_word = input(f"please enter a valid word to begin: ")
                if input_word.lower() in allowed_words and input_word.lower() not in prohibited_words:
                    players_data[-1].word_list.append(input_word)
                    start_letter = input_word[-1].upper()
                    print(f"\nStarting letter for next player is: {start_letter}")
                    valid_word = True
                    return start_letter
                else:
                    players_data[-1].pass_taken += 1
                    print(f"FOUL!\nThe word was not recognised as a valid word.\nPenalty: 1 pass({3 - players_data[-1].pass_taken})")
                    print("Turn goes to your opponent.")
                    valid_word = False
                    if players_data[-1].pass_taken >= 3:
                        print(f"LOST!\n{players_data[-1].name} is out of the game")
                        players_data.pop()
            else:
                input_word = input(f"please enter a valid word begining with letter {start_letter}: ")
                if input_word.lower() in allowed_words and input_word.lower() not in prohibited_words and input_word[0].upper() == start_letter:
                    players_data[-1].word_list.append(input_word)
                    start_letter = input_word[-1].upper()
                    print(f"\nStarting letter for next player is: {start_letter}")
                    valid_word = True
                    return start_letter
                else:
                    players_data[-1].pass_taken += 1
                    print(f"FOUL!\nThe word was not recognised as a valid word.\nPenalty: 1 pass({3 - players_data[-1].pass_taken})")
                    print("Turn goes to your opponent.")
                    valid_word = False
                    if players_data[-1].pass_taken >= 3:
                        print(f"LOST!\n{players_data[-1].name} is out of the game")
                        players_data.pop()
                continue   

´´´´

As Nico238 said in the comments, you break your loop with return statements inside every if/else statement. As this game relies on a logical progression (Whether a player has entered the correct first letter, and if it's in the dictionary) you need to handle loops carefully, preferably making them as flat (not nested) as possible, and of course not breaking out of them if you need to stay in the game loop.

My suggestion would be to remove those return start_letter statements as you already set it to be something other than empty, and this should continue your loop.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM