Unable to break a python while loop inside a function - python

This program is a snakes and ladders program for my GCSE computer science (don't worry, this is just practice), and I'm having trouble breaking a while loop with a function that exists inside the loop. Here's the code:
win = False
while win == False:
print("Player 1 goes first.")
def dice():
roll = random.randint(1,6)
return roll
roll = dice()
print("They roll a...",roll)
player1+=roll
def check():
if player1 in ladders or player2 in ladders:
print("A ladder has moved the player to a new position.")
elif player1 in snakes or player2 in snakes:
print("A snake has moved the player to a new position.")
elif player1 >= 36:
print("Congratulations. Player 1 has won the game.")
win = True
elif player2 >= 36:
print("Congratulations. Player 2 has won the game.")
win = True
check()
print("Player 1 is on square",player1)
It's obviously not finished yet, and that's not all the code. After that bit, it does the same but with player2. There's a tuple above it that the check function checks to see if the player landed on a snake or a ladder, but I haven't added the code which actually moves the player up/down the ladder/snake.
The error is that the while loop is an infinite loop.
I've tried changing the whole win = False or True thing to just while True and then using break where I say win = True, but then it returns an error of 'break outside loop' even though the break is obviously inside the loop. I wonder if it's because I need to return something from the function, but I'm not quite sure how to do that. Simply putting 'return win' below both win = True doesn't change anything, and the while loop still continues indefinitely.
I've looked here and here for answers but neither worked for me; I think my situation is slightly different.

Perhaps this is what you are looking for? Note how I took the functions out of the loop. Then I ditched using a boolean variable altogether, as there is cleaner ways around it. You can use while True and then simply break if a certain condition is met. If you want the loop go back to starting point when a certain condition is met, you can use continue.
def dice():
return random.randint(1,6)
def check():
if player1 in ladders or player2 in ladders:
print("A ladder has moved the player to a new position.")
elif player1 in snakes or player2 in snakes:
print("A snake has moved the player to a new position.")
elif player1 >= 36:
print("Congratulations. Player 1 has won the game.")
return True
elif player2 >= 36:
print("Congratulations. Player 2 has won the game.")
return True
while True:
print("Player 1 goes first.")
roll = dice()
print("They roll a...",roll)
player1 += roll
if check():
break
print("Player 1 is on square",player1)
I didn't really touch the logic but it would make sense to pass the player score into check.

It happened because when you are assign variable in function it used local variable. So, for a fast fix you can add global win in check function:
def check():
global win
if player1 in ladders or player2 in ladders:
print("A ladder has moved the player to a new position.")
elif player1 in snakes or player2 in snakes:
print("A snake has moved the player to a new position.")
elif player1 >= 36:
print("Congratulations. Player 1 has won the game.")
win = True
elif player2 >= 36:
print("Congratulations. Player 2 has won the game.")
win = True
You can read more about type of variables here - http://www.python-course.eu/python3_global_vs_local_variables.php
Also it's not a good idea to store function inside while because it will create function on each iteration which is not good. So better is define them outside of loop.

Related

Is this correct for rock-paper-scissor game | Python?

The question is :
Make a two-player Rock-Paper-Scissors game. (Hint: Ask for player plays (using input), compare them, print out a message of congratulations to the winner, and ask if the players want to start a new game)
player1 = input("Player 1: ")
player2 = input("Player 2: ")
if player1 == "rock" and player2 == "paper":
print("Player 2 is the winner!!")
elif player1 == "rock" and player2 == "scissor":
print("Player 1 is the winner!!")
elif player1 == "paper" and player2 == "scissor":
print("Player 2 is the winner!!")
elif player1 == player2:
print("It's a tie!!")
After asking if the players want to start a new game, how to restart the code?
You could use a while loop, i.e. something like
play = 'Y'
while play=='Y':
# your original code
play = input("Do you want to play again (Y/N): ")
Also I'd suggest you check that the responses from the user are valid (i.e. what if they type potatoe, in your code nothing will print if one or both players don't respond with rock, scissors or paper. You should also look at the lower() command and convert the answer to lower case for this reason.
options = {"rock" : 0, "paper": 1, "scissors": 2} #correct inputs
ratio = options[player1] - options[player2]
if player1 not in options.keys() and player2 not in options.keys():
return 0 #tie, both inputs wrong
if player1 not in options.keys():
return 2 #Player1 input wrong, Player 2 wins
if player2 not in options.keys():
return 1 #Player2 input wrong, Player 1 wins
if ratio == 0:
return 0 #tie
if ratio == 1 or ratio == -2:
return 1 #Player 1 wins
return 2 #Player 2 wins

Problem with python: how can I make something happen only some times that a definition is called upon?

So I have a text-adventure game for an intr Computer Science class & I need to put items in it. Inside of a definition, I have a global variable knife. But I need to make it so that it doesn't ask you to pick up the knife every time you walk into the room (or the definition is called upon) if you already have picked up the knife.
global knife
global knife_val
if knife_val = 1
knife = input("You step on the handle of a knife when walking into the room. Do you wish to pick it up?").lower()
if knife == "yes":
print("You picked up the Knife!")
knife_val = 0
then later it asks you
attack = input("Do you wish to attack?")
if attack == "yes":
move_miss = random.randint(1,5)
if move_miss == 1:
miss = True
else:
miss = False
if miss:
print("You missed!")
print("You are bitten by the monster and you die. Goodbye")
quit()
elif attack == "no":
print("You are bitten by the monster and you die. Goodbye")
quit()
print("You beat the monster!")
elif knife_val = 1:
print("You are bitten by the monster and you die. Goodbye")
quit()
how can I make it so that this only happens when the condition is met? when I tried before there was an error

Updating local variables inside a function in Python

I'm learning python and about to complete a program to run a rock, paper, scissors game between two players for three rounds and update player scores at the end of each round and display it on screen:
import random
"""This program plays a game of Rock, Paper, Scissors between two Players,
and reports both Player's scores each round."""
moves = ['rock', 'paper', 'scissors']
"""#!/usr/bin/env python3
import random
"""This program plays a game of Rock, Paper, Scissors between two Players,
and reports both Player's scores each round."""
moves = ['rock', 'paper', 'scissors']
"""The Player class is the parent class for all of the Players
in this game"""
class Player:
def move(self):
return 'rock'
def learn(self, my_move, their_move):
pass
def beats(one, two):
return ((one == 'rock' and two == 'scissors') or
(one == 'scissors' and two == 'paper') or
(one == 'paper' and two == 'rock'))
class RandomPlayer(Player):
def move(self):
return random.choice(moves)
class Game:
def __init__(self, p1, p2):
self.p1 = p1
self.p2 = p2
def keep_p1_score(self, p1_Score):
return p1_Score
def play_round(self):
move1 = self.p1.move()
move2 = self.p2.move()
p1_Score = 0
p2_Score = 0
print(f"Player One played: {move1} Player Two played: {move2}")
if beats(move1, move2) == True:
print('**Player One wins**')
p1_Score += 1
elif beats(move2, move1) == True:
print('**Player Two wins**')
p2_Score += 1
else:
print('**TIE**')
print(f'Score: Player One: {p1_Score} Player Two: {p2_Score}')
self.p1.learn(move1, move2)
self.p2.learn(move2, move1)
def play_game(self):
print("Game start!")
for round in range(3):
print(f"Round {round + 1}:")
self.play_round()
print("Game over!")
if __name__ == '__main__':
game = Game(RandomPlayer(), RandomPlayer())
game.play_game()
The problem is when I run the code it doesn't update players scores. As you can see in this picture of the output even though player two won rounds two and three, his score at the end of run three is still 1 instead of 2. I know that's because for each iteration of play_round function in the for loop inside the play_game function the values of p1_score and p2_score resets to zero but I do not know how to stop that from happening. Any suggestion will be greatly appreciated.
program output
The problem is that p1_Score and p2_Score are local variables in play_round. So every time you call this function, you get a new instance of these variables. Moreover, you always set
p1_Score = 0
p2_Score = 0
in play_round. So at the end of the function no score will ever be larger than 1.
To rememdy this, use self.p1_Score and self.p2_Score to make these variables instance variables and also move the 0-initialization into the __init__ function of the game class. Alternatively, make the score a class variable of the Player class.

Why can't I break out of my loop? (Python)

import rando
move = rando.Moves()
All of this junk is just writing to a file to give some context about the game
oof = open('README.txt', 'w') #opens the text file
oof.write("The Final Adventure\n")
oof.write("\n") #writes text to the file
oof.write("This game is about an adventurer(you) trying to fight through a
dungeon in order to get the legendary sword of mythos.\n")
oof.write("\n")
oof.write("With this legendary sword you can finally rid your homeland of
the evil king of Mufasa and take the mantle of kingship.\n")
oof.write("\n")
oof.write("Best of luck to you, Warrior!\n")
oof.write("\n")
oof.write("You have 3 move options with any enemy you encounter.\n")
oof.write("\n")
oof.write("1 - Attack\n")
oof.write("2 - Run Away\n")
oof.write("3 - Talk\n")
oof.write("Have fun!!")
oof.close() #closes the file
print("Please read the README.txt in this file")
player = True
A buddy of mine told me I had to have two while loops so not too sure why I need those but it works slightly like it's meant to.
while True:
while player:
#First Door
print("You walk through the forest until you finally find the talked
about entrance door.")
print("There is a Gatekeeper standing by the entrance and in order
to enter you must defeat him")
print("")
move = int(input("What will you do?(Please use numbers 1-2-3 for
moves) "))
The problem is here. I have a module that I made that if the attack fails, you die and player gets set to False but it still continues the while loop.
if move == 1:
rando.Moves.move1(player)
elif move == 2:
rando.Moves.move2(player)
elif move == 3:
rando.Moves.move3(player)
else:
print("You ran out of time and died")
player = False
if player == False:
break
#First Room
print("The door suddenly opens and you walk through.")
print("")
print("After walking for a bit you discover a chest, probably full
of loot!")
print("You walk up and begin to open the chest and it clamps down on
your hand with razor sharp teeth.")
print("ITS A MONSTER!")
print("After struggling, you are able to free your hand.")
move = int(input("What will you do? "))
if move == 1:
rando.Moves.move1(player)
elif move == 2:
rando.Moves.move2(player)
elif move == 3:
rando.Moves.move3(player)
else:
print("You ran out of time and died")
player = False
#Play again
play = input("Want to play again? (y/n) ")
if play == "y":
player = True
elif play == "n":
print("Goodbye!")
break
You don't need two loops, just one.
while True:
if move == 1:
rando.Moves.move1(player)
elif move == 2:
rando.Moves.move2(player)
elif move == 3:
rando.Moves.move3(player)
else:
print("You ran out of time and died")
break
...
Your code was just breaking out of the inner loop, not the outer loop.

NIM game - re-running the game

I have to do a small game called NIM. The game is a human vs. computer game where each player removes a number of straws (1,2 or 3) and the player who removes the last straw looses. I got the game to work properly but the problem is that it doesn't want to re-run if the player wants to play again. Any help would be apprecieted. :)
import random
print("""************ NIM GAME ***********
************ Game Start ***********
************ The rules ***********
-----------------------------------------------------
You need to remove from 1 to 3 straws from the pile.
The player that removes the final straw is the loser.
-----------------------------------------------------""")
player1=str(input("Enter your name. "))
player2="Computer"
howMany=0
gameover=False
strawsNumber=random.randint(10,20)
if (strawsNumber%4)==1:
strawsNumber+=1
def removingStrawsComputer():
removedNumber=random.randint(1,3)
global strawsNumber
while removedNumber>strawsNumber:
removedNumber=random.randint(1,3)
strawsNumber-=removedNumber
return strawsNumber
def removingStrawsHuman():
global strawsNumber
strawsNumber-=howMany
return strawsNumber
def humanLegalMove():
global howMany
legalMove=False
while not legalMove:
print("It's your turn, ",player1)
howMany=int(input("How many straws do you want to remove?(from 1 to 3) "))
if howMany>3 or howMany<1:
print("Enter a number between 1 and 3.")
else:
legalMove=True
while howMany>strawsNumber:
print("The entered number is greater than a number of straws remained.")
howMany=int(input("How many straws do you want to remove?"))
return howMany
def checkWinner(player):
if strawsNumber==0:
print(player," wins.")
global gameover
gameover=True
return gameover
def resetGameover():
global gameover
gameover=False
return gameover
def game():
while gameover==False:
print("It's ",player2,"turn. The number of straws left: ",removingStrawsComputer())
checkWinner(player1)
if gameover==True:
break
humanLegalMove()
print("The number of straws left: ",removingStrawsHuman())
checkWinner(player2)
def playAgain():
answer=input("Do you want to play again?(y/n)")
resetGameover()
while answer=="y":
game()
else:
print("Thanks for playing the game")
game()
playAgain()
You forgot to reset the number of straws at the start of each game. After def game():, you should insert:
global strawsNumber
strawsNumber=random.randint(10,20)
Note: you also need to put answer=input("Do you want to play again?(y/n)") at the end of your while answer=="y": loop. This will ask the user for a replay every time, instead of just after the first game.

Categories

Resources