breaking out of while loops - python

So this is a simplified version of my bigger code (there is some unnecessary bits that makes more sense in my main code), and I cannot seem to understand why it neither breaks out of the playing nor the fight loops:
fight = True
a = "enemy"
t = ""
ccd = False,False
playing = True
def lvl():
playing = True
fight = True
while fight:
if a == "enemy":
t = "enemy"
else:
if a == "enemy":
t = "enemy"
else:
t = "player"
while t == "enemy":
print ("enemy attacks player")
t = "player"
while t == "player":
if ccd == (False , False):
fight = False
playing = False
turn = "no one"
t = "enemy"
fight = True
while playing:
fight = True
lvl()
while not playing:
print ("no")

Your program actually is breaking out of the "fight" loop, but it is sent right back in because the playing loop is still running.
The reason why you are not breaking out of the playing loop is that your "playing" variable is local, not global. As such, when you change the variable in the function it doesn't change the one in main (even though they have the same name), which you are using to control the while loop. A possible solution for this would be to return "playing" at the end of your function. Here is some modified code that should suit your purposes:
'''
fight = True
a = "enemy"
t = ""
ccd = False,False
playing = True
def lvl():
playing = True
fight = True
while fight:
if a == "enemy":
t = "enemy"
else:
t = "player"
while t == "enemy":
print ("enemy attacks player")
t = "player"
while t == "player":
if ccd == (False , False):
fight = False
playing = False
t = "enemy"
return playing
fight = True
while playing:
fight = True
playing = lvl()
while not playing:
print ("no")
'''

To have lvl() affect the global variable, you must do the following:
def lvl():
global playing
playing = True

Related

unexpected indent error inside a definition for a function

I have this code for the movement of a monster to move randomly between rooms but I get an unexpected intention error for the global value.
def monster(): """moves the monster randomly"""
global monster_current_room
if monster_current_room["name"] != current_room:
print('The monster is currently in', monster_current_room["name"])
exits = list(monster_current_room["exits"].values())
if random.randint(1, 4) == 4:
monster_current_room = rooms[random.choice(exits)]
elif monster_current_room["name"] == current_room:
game_over = True
if I unindent the global value it acts as the end of the definition and wants two lines between the definition and global value. when I try to run with the indent the program fails with the error.
You have misplaced the function comment:
def monster():
"""
moves the monster randomly
"""
global monster_current_room
if monster_current_room["name"] != current_room:
print('The monster is currently in', monster_current_room["name"])
exits = list(monster_current_room["exits"].values())
if random.randint(1, 4) == 4:
monster_current_room = rooms[random.choice(exits)]
elif monster_current_room["name"] == current_room:
game_over = True
or if you prefer an inline comment you can do like that
def monster(): # moves the monster randomly
global monster_current_room
if monster_current_room["name"] != current_room:
print('The monster is currently in', monster_current_room["name"])
exits = list(monster_current_room["exits"].values())
if random.randint(1, 4) == 4:
monster_current_room = rooms[random.choice(exits)]
elif monster_current_room["name"] == current_room:
game_over = True
when you write a multiline string like
"""
moves the monster randomly
"""
it has to respect the rules of the classic sentences of the python code. So you can't place them whenever you want like comments.

Why does this loop continuously run (asking player for their turn)?

Having an issue with the while loop for the win_checker method which I can't seem to figure out. I tried doing 2 while loops but that didn't work, so then I stuck with just one:
# Checking for win
def win_checker():
global is_game_on
if board[0] == board[1] == board[2] != "-":
print(board[0] + " won!")
is_game_on = False
# Start the game using a method
def start_game():
global is_game_on
is_game_on = True
display_board()
while is_game_on:
handle_turn_x()
win_checker()
tie_checker()
handle_turn_o()
start_game()
If I set the while loop to run only when is_game_on is True, and if my win_checker sets is_game_on to False (when appropriate), then why does the game keep going and ask the next player for its turn?
I suspect this is something to do with how I'm trying to jump out of the while loop.
Where am I wrong here?
Thanks for your help!!
The condition of the while loop is only checked when the program is "reading" the line that says
while <condition>:
I would recommend, instead of global variables, you make win_checker and tie_checker return a boolean value (True or False), and then make your while loop look like this:
while True: # run forever
handle_turn_x()
if win_checker() or tie_checker():
break # jump out of the while loop
handle_turn_o()
if win_checker() or tie_checker():
break
Globals are generally a bad idea...
instead of using a global, return True or False from that function.
Then in start_game:
def start_game():
display_board()
while True:
handle_turn_x()
if(not win_checker()):
break
tie_checker()
handle_turn_o()
start_game()
Then you can do the same for the tie checker
You could simply return is_game_on instead of modifying the global value, for example like so:
# Checking for win.
def win_checker():
if board[0] == board[1] == board[2] != "-":
print(board[0] + " won!")
return False
else
return True
# Start the game using a function.
def start_game():
while True:
handle_turn_x()
if win_checker() or tie_checker():
break
handle_turn_o()
if win_checker() or tie_checker():
break
Now this would be a little repetitive, so I think the win and tie checkers should be included to the turn handler. Something like this:
while True:
for player in ("x", "o"):
handle_turn(player)
if win_checker(player) or tie_checker():
break

Boolean condition is reading True, but the while loop still isn't breaking

For some reason the while loop is not breaking when the condition is met. The while loop should be checking for a players input to fill up a tic tac toe board until the variable "win" reads True.
Once the board reflects one of the winning conditions of tic tac toe, it assigns the variable "win" to True, and in turn should break out of the loop.
For some reason the loop isn't breaking, but the variable "win" is still reading True.
Can someone explain why the loop isn't breaking? I have tried rewriting the condition for the while loop to read "while win == False", but that doesn't seem to resolve the issue either.
I have included some of the functions I am using, and explained some of the simpler ones with a comment next to it.
I am using repl.it to do all of this online and not on a program on my local machine, so I think this may be part of the issue as well.
import os
board = ["#"," "," "," "," "," "," "," "," "," "]
def determine_win(marker):
# Winning Patterns:
# (1,2,3), (4,5,6), (7,8,9), (1,4,7), (2,5,8), (3,6,9), (3,5,7), (1,5,9)
if board[1]== board[2]==board[3]==marker:
return True
elif board[4]== board[5]==board[6]==marker:
return True
elif board[7]== board[8]==board[9]==marker:
return True
elif board[1]== board[4]==board[7]==marker:
return True
elif board[2]== board[5]==board[8]==marker:
return True
elif board[3]== board[6]==board[9]==marker:
return True
elif board[3]== board[5]==board[7]==marker:
return True
elif board[1]== board[5]==board[9]==marker:
return True
else:
return False
player1 = xo() # A Function that takes user input either "X" or O"
if player1 == "X":
player2 = "O"
else:
player2 = "X"
win = False
while not win:
display_board(board) # display_baord(board) takes the list "board" and uses it as input to display the tic tac toe board to the screen.
print("\nPlayer 1")
board[player_turn()] = player1
win = determine_win(player1)
print(win) # used to verify if win is changing
input() # used to pause the screen for troubleshooting
display_board(board)
print("\nPlayer 2")
board[player_turn()] = player2
win = determine_win(player2)
print(win) # used to verify if win is changing
input() # used to pause the screen for troubleshooting
print("Win Declared")
As the comment said, the reason is because while only check the condition of win when you finish the whole iteration of the loop. I would prefer the following way to make the code neater:
# win = False <-- you don't need this now
while True:
display_board(board) # display_baord(board) takes the list "board" and uses it as input to display the tic tac toe board to the screen.
print("\nPlayer 1")
board[player_turn()] = player1
if determine_win(player1):
print("Player 1 won")
break # break out of the loop
display_board(board)
print("\nPlayer 2")
board[player_turn()] = player2
if determine_win(player2):
print("Player 2 won")
break # break out of the loop
if not determine_win(player1):
display_board(board)
print("\nPlayer 2")
board[player_turn()] = player2
win = determine_win(player2)
# player 2 wins
else:
# player 1 wins
win = True
use something like this. It is same as #jasonharper and #Idlehands answered

Code regarding game won for lillypad not seem to be working

To be more specific been trying to code a frog and toad game. Most of the code works however can not seem to get python to display when the user has won the game. Feel free to ask for any added information.
frogandtoad= ['f','f','f',' ', 't','t','t']
def game_won():
for i in range(0,3):
if frogandtoad[i] =='f':
frog = True
if frogandtoad[i]=='t':
toad = True
if frog == True and toad == True:
return True
def playgame(frogandtoad):
print("From: ")
from_pos = int(input()) - 1
print("To: ")
to_pos = int(input())-1 #Bring in valid_move
valid = valid_move(frogandtoad, from_pos, to_pos)
if valid:
value = frogandtoad[from_pos]
frogandtoad[to_pos] = value
frogandtoad[from_pos] = ' '
print("frogandtoad panel", frogandtoad)
else:
print("Invalid Move, Look at rules under demonstration!")
if game_won():
print("you won")
exit_game()
if game_won==True: should probably be if game_won()==True:
You need to actually call the function game_won.
What does it mean to "call" a function in Python?
Also, as #quamrana points out, for if/while statements, the Pythonic way is to write if condition instead of if condition == True.
In game_won(), when frog == True and toad == True is False, then one of those variables are going to be undefined (as I get an exception). Unless they are already defined in the global scope.
My consideration for game_one() is:
def game_won():
result = [False, False]
for i in range(0,3):
if frogandtoad[i] =='f':
result[0] = True
elif frogandtoad[i]=='t':
result[1] = True
return all(result)
Variable result is defined with False and False for frog and toad status. For all(result) to be True, then both items must be True and thus True will be returned else False otherwise.
Edit: I should have mentioned that I ran your code with valid = True as I do not have valid_move() and I commented exit_game() as I do not have that.

Python OOP Monty Hall not giving the expected results

Trying out some OOP in python, I tried to create a Monty Hall Problem simulation that is giving odd results. I implement three different strategies that a player can choose from, either to stay with the first door selected, switch to the second closed door, or randomly choose between them.
import random
class Door():
behind = None
is_open = False
is_chosen = False
def __init__(self,name=None):
self.name = name
def open(self):
self.is_open = True
def choose(self):
self.is_chosen = True
class Goat():
is_a = 'goat'
class Car():
is_a = 'car'
class Player():
door = None
def choose(self,door):
self.door = door
self.door.choose()
def open(self):
self.door.open()
if self.door.behind.is_a == 'car':
return True
return False
def play(strategy):
player = Player()
items = [Goat(),Goat(),Car()]
doors = [Door(name='a'),Door(name='b'),Door(name='c')]
for door in doors:
item = items.pop()
door.behind = item
random.shuffle(doors)
player.choose(random.choice(doors))
if strategy == 'random':
if random.choice([True,False]):
for door in doors:
if not door.is_open and not door.is_chosen:
final = door
break
else:
final = player.door
elif strategy == 'switch':
for door in doors:
if not door.is_open and not door.is_chosen:
final = door
break
elif strategy == 'stay':
final = player.door
player.choose(final)
if player.open():
return True
else:
return False
## Play some games
for strategy in ['random','switch','stay']:
results = []
for game in range(0,10000):
if play(strategy):
results.append(True)
else:
results.append(False)
## Gather the results
wins = 0
loses = 0
for game in results:
if game:
wins += 1
else:
loses += 1
print 'results:\tstrategy={}\twins={}\tloses={}'.format(strategy,str(wins),str(loses))
But every time I run it, I get something like:
results: strategy=random wins=3369 loses=6631
results: strategy=switch wins=3369 loses=6631
results: strategy=stay wins=3320 loses=6680
Why is this giving nearly the same results for each strategy? Shouldn't the 'switch' strategy give a ratio of ~66% wins and 'stay' give ~33%?
You're not playing the game correctly. After the contestant chooses a door, the host reveals a goat behind one of the other two doors, and then offers the contestant the opportunity to switch -- you're allowing a choice between three doors instead of two. Here's a revised play() function:
def play(strategy):
player = Player()
items = [Goat(), Goat(), Car()]
doors = [Door(name='a'), Door(name='b'), Door(name='c')]
random.shuffle(items)
for door in doors:
item = items.pop()
door.behind = item
player.choose(random.choice(doors))
# player has chosen a door, now show a goat behind one of the other two
show = None
for door in doors:
if not (door.is_open or door.is_chosen) and door.behind.is_a == 'goat':
show = door
show.open()
break
# The player has now been shown a goat behind one of the two doors not chosen
if strategy == 'random':
if random.choice([True, False]):
for door in doors:
if not (door.is_open or door.is_chosen):
final = door
break
else:
final = player.door
elif strategy == 'switch':
for door in doors:
if not (door.is_open or door.is_chosen):
final = door
break
elif strategy == 'stay':
final = player.door
player.choose(final)
return player.open()
That produces results like:
results: strategy=random wins=4977 loses=5023
results: strategy=switch wins=6592 loses=3408
results: strategy=stay wins=3368 loses=6632

Categories

Resources