简体   繁体   中英

Error executing while-loop "Loop being escaped randomly" Python

I have this code that is made for a game similar like (Rock, Paper, Scissors). When the code starts running, sometimes it gives error in not running the actual loop and conditions correctly. For example when the code starts running, at the first time the loop runs normally:

Foot, Nuke or Cockroach? (Quit ends): Foot
You chose: Foot
Computer chose: Foot
It is a tie!
Foot, Nuke or Cockroach? (Quit ends): 

But if I re-run the code again, the while-loop does not get executed as in the following example:

Foot, Nuke or Cockroach? (Quit ends): Cockroach
Foot, Nuke or Cockroach? (Quit ends): 

Or it gives me elif condition that the input is incorrect even though the input is from the correct selection.

Here is the full code:


    import random
    
    def main():
        rounds = 0
        win = 0
        tie = 0
        choices = ["Foot", "Nuke", "Cockroach"]
        cpu = random.choice(choices)
    
        while True:
    
            inpt = input("Foot, Nuke or Cockroach? (Quit ends): ")
    
            if inpt == "Foot" and cpu == "Nuke" or inpt == "Cockroach" and \
                    cpu == "Foot":
                print(f"You chose: {inpt}")
                print(f"Computer chose: {cpu}")
                print("You LOSE!")
                rounds += 1
    
            elif inpt == "Nuke" and cpu == "Foot" or inpt == "Foot" and \
                    cpu == "Cockroach":
                print(f"You chose: {inpt}")
                print(f"Computer chose: {cpu}")
                print("You WIN!")
                rounds += 1
                win += 1
    
            elif inpt == "Foot" and cpu == "Foot" or inpt == "Cockroach" and \
                    cpu == "Cockroach" or inpt == "Nuke" and cpu == "Nuke":
                print(f"You chose: {inpt}")
                print(f"Computer chose: {cpu}")
                print("It is a tie!")
                rounds += 1
                tie += 1
    
            elif inpt == "Quit":
                print(f"You played {rounds} rounds, and won {win} rounds, "
                      f"playing tie in {tie} rounds.")
                break
    
            elif inpt != "Foot" and inpt != "Cockroach" and inpt != "Nuke":
                print("Incorrect selection.")
    
    
    if __name__ == "__main__":
        main()

Two things make this break, and there's a few thing to improve.

The reason for breaks is that you've done the tie condition wrong. When running multiple conditions like that in a row you need parentheses. Otherwise it reads it "incorrect". So the if condition should be:

elif (inpt == "Foot" and cpu == "Foot") or (inpt == "Cockroach" and cpu == "Cockroach") or (inpt == "Nuke" and cpu == "Nuke"):

The same thing might be happening for the other conditions too, I didn't run the loop that many times.

Secondary thing that doesn't break the loop itself but renders the game useless is that you have the cpu pick their value outside of the loop. That means that the CPU's pick stays the same during all loops. It's an easy fix to move this inside the while loop (ofc before the if statements)

In addition you should probably make a stop condition flag instead of using break. So set the while loop to run when flag (or whatever name you want) is True . Then if you need the game to end set the variable to False.

Also doing all the checks for win state in the if statements make mistake easy and reduce readability. You should instead check for each state (win, loss, tie) first, and set a variable to match that, and then run the point adding if statements against that variable.

Also making the game a class, and adding functions inside help it run smoother and increase readability. So you can run ie the game state checker in it's own function.

EDIT: Also any time you take input you should sanitize it. Here the input is simple so casting input.lower() is all you need. That way no matter what the user capitalizes the input will always be all lowercase. So an input of nUkE becomes just nuke

Not sure, but you have not treated the case that you input "Nuke" and cpu is "Cockroach" if i am not mistaken. You will have to implement that. However, a few suggestions:

  • Put your correct input check before your other if statements, just for logic. Also i optimized that if statement by adding the continue statement.
  • Same goes for the Quit phrase - you do not want any other code executed after the user enters Quit - just put it at top.
  • your if statement before the "Quit" one can be simplified drastically by just having input == cpu, if i am not mistaken.

The following code works for me except when i enter Nuke and cpu is on Cockroach, because there is no condition for that:

import random


def main():
    rounds = 0
    win = 0
    tie = 0
    choices = ["Foot", "Nuke", "Cockroach"]
    cpu = random.choice(choices)

    while True:
        inpt = input("Foot, Nuke or Cockroach? (Quit ends): ")

        if inpt == "Quit":
            print(f"You played {rounds} rounds, and won {win} rounds, "
                  f"playing tie in {tie} rounds.")
            break

        if inpt not in choices:
            print("Incorrect selection.")
            continue

        if inpt == "Foot" and cpu == "Nuke" or inpt == "Cockroach" and cpu == "Foot":
            print(f"You chose: {inpt}")
            print(f"Computer chose: {cpu}")
            print("You LOSE!")
            rounds += 1

        if inpt == "Nuke" and cpu == "Foot" or inpt == "Foot" and cpu == "Cockroach":
            print(f"You chose: {inpt}")
            print(f"Computer chose: {cpu}")
            print("You WIN!")
            rounds += 1
            win += 1

        if inpt == cpu:
            print(f"You chose: {inpt}")
            print(f"Computer chose: {cpu}")
            print("It is a tie!")
            rounds += 1
            tie += 1


if __name__ == "__main__":
    main()

If I input Nuke and the cpu picks Foot , nothing happens. This is because you have not programmed that specific condition.

I also recommend moving cpu = random.choice(choices) inside the while loop, so the cpu can change its choice during the game.

I don't about your game but if it's like rock paper scissors, shouldn't you have more conditions? You never test cockroach vs nuke.

Also, it may be best to change cpu within the while loop (otherwise in at most 3 tries the player can guess its value and always win).

I don't see any obvious error that would prevent your input to be valid, so make sure you have entered the capitalized letters as in your program (or maybe better, use inpt.lower() to always consider lower case strings)

To avoid multiple if-else statements you can use list to store all possible combinations:

import random

ACTIONS = ['foot', 'nuke', 'cockroach']
MAP = [['=', '<', '>'],
       ['>', '=', '<'],
       ['<', '>', '=']]
SCORE = {'=': ['Tied Game!', 0, 0],
         '>': ['You WIN!', 1, 0],
         '<': ['You LOOSE!', 0, 1]}

rounds = 0
score_user = 0
score_comp = 0
while True:
    action = input(f'Foot, Nuke or Cockroach? (Quit ends): ').lower()
    if action == 'quit':
        break
    user = ACTIONS.index(action)
    comp = random.randint(0, 2)
    print(f'You chose {ACTIONS[user]}, computer chose {ACTIONS[comp]}.')
    res = MAP[user][comp]
    score_user += SCORE[res][1]
    score_comp += SCORE[res][2]
    print(f'{ACTIONS[user].title()} {res} {ACTIONS[comp].title()}. {SCORE[res][0]} Your score: {score_user}. Comp score: {score_comp}')
    rounds += 1

print(f'You played {rounds} rounds, and won {score_user} rounds, playing tie in {rounds-score_user-score_comp} rounds.')

Output:

Foot, Nuke or Cockroach? (Quit ends): foot
You chose foot, computer chose nuke.
Foot < Nuke. You LOOSE! Your score: 0. Comp score: 1
Foot, Nuke or Cockroach? (Quit ends): nuke
You chose nuke, computer chose foot.
Nuke > Foot. You WIN! Your score: 1. Comp score: 1
Foot, Nuke or Cockroach? (Quit ends): quit
You played 2 rounds, and won 1 rounds, playing tie in 0 rounds.

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