How to Add Win/Loss Counter to Rock Paper Scissors Program - python

I have pretty much finished this Rock Paper Scissors program, but one of the final steps is to add a counter to print the Win, Loss, and Tie ratio after the user is done playing.
I tried in the count_win_loss() function to enumerate the messages index that I pass to it in the play_game() function, but all it is returning zeros
import random
def count_win_loss(messages_from_result):
player_wins = 0
cpu_wins = 0
ties = 0
#This is supposed to get the index value position of this list, which
should be defined at the end of `play_game()` function.
for index in enumerate(messages_from_result):
new_index = index
#NOT WORKING NEEDS TO BE FIXED
if new_index == 0:
ties += 1
elif new_index == 1:
player_wins += 1
elif new_index == 2:
cpu_wins += 1
else:
ties += 0
player_wins += 0
cpu_wins += 0
#NOT WORKING NEEDS TO BE FIXED
print(player_wins)
print(cpu_wins)
print(ties)
#print('\nHuman Wins: %d, Computer Wins: %d, Ties: %d' % (player_wins, cpu_wins, ties))
This elif statement appears at the end of my game function. It executes when a user inputs '2' which ends the loop.
#Creates a format that can be passed to the results matrix.
#Additionally creates an index 3 that I will reference as the error value.
guesses_index = guess_dict.get(user_guess, 3)
computer_index = guess_dict.get(computer_guess)
result_index = results[guesses_index][computer_index]
final_result = result_messages[result_index]
elif play_again == '2':
count_win_loss(result_messages) #NOT WORKING NEED HELP
print('Thanks for playing!')
continue_loop = False
I pass it this messages list:
result_messages = [
"You tied!",
"You win!",
"The Computer won. :(",
"Invalid weapon, please try again."
]
As mentioned in the title, I need a win/loss counter, which I thought my calc_win_loss() would do

New_Index variable is not defined inside this function, therefore global to where ever you defining the value and get in the starting of this function
For ex:-
def a():
b = 2
def c(): . print(b) . Whenever you will call c() it will cause an error because b is a local variable
in side function a() however if you do
def a():
global b
b = 2
def c():
print(b)
Now when you call a() and then c(). Th error will go away

Related

Simple Function Problem. Trying to make a simple dice roll race game that tracks the position when they roll the dice

Trying to figure out why the program won't run.
This is the error code I am getting:
update_position (random_roll_1, random_roll_2)
builtins.NameError: name 'random_roll_1' is not defined
I thought I had all the correct parameters but I guess not. Any help would be really appreciated
import random
from random import randint
#both of the players are able to roll out their turs
this is the function where the players can roll their dice and receive a random number
def roll_die(p1_move,p2_move):
if p1_move is True:
input('Press enter to roll the die for player 1')
random_roll_1 = randint(1,6)
random_roll_1 = str(random_roll_1)
print('Player 1 rolled ' + random_roll_1)
random_roll_1 = int(random_roll_1)
return random_roll_1
elif p2_move is true:
input('Press enter to roll the die for player 2')
random_roll_2 = randint(1,6)
random_roll_2 = str(random_roll_2)
print('Player 2 rolled ' + random_roll_2)
random_roll_2 = int(random_roll_2)
return random_roll_2
This part updates the position on where each player is after it rolls the dice. The players have to roll exactly 8 in order to win. Anything higher than that will cause the player to stay in its position
def update_position(random_roll_1, random_roll_2):
player_1_position = 0
player_2_position = 0
max_score = 8
if player_1_position < max_score:
if player_1_position + random_roll_1 > 8:
print('The roll was too high, player 1 stays in the same spot')
else:
player_1_position += random_roll_1
print('Player 1 moved up ' + random_roll_1 + ' spots!')
return player_1_position
elif player_2_position < max_score:
if player_2_position + random_roll_2 > 8:
print(' The roll was too high, player 2 stays in the same spot')
else:
player_2_position += random_roll_2
print('Player 2 moved up ' + random_roll_2 + ' spots!')
return player_2_position
this function checks to see if one of the players hit 8 as their score
#checks to see if any of the players have managed to reach the end of the game
def check_game_over(player_1_position, player_2_position):
if player_1_position == 8:
print('Player 1 has won!')
print('Thank you for playing!')
continue_game = False
return continue_game
elif player_2_position == 8:
print('Player 2 has won!')
print('Thank you for playing!')
continue_game = False
return continue_game
This function is what controls who's turn it is. I added in the roll dice function along with the update spot function as it would be easier to include them in one whole function together. This is where I am getting my problem.
#random_roll_1,random_roll_2, player_1_position, player_2_position
#change the turn over to the next player
def opponent():
p1_move = True
p2_move = False
if p1_move is True:
roll_die (p1_move, p2_move)
update_position (random_roll_1, random_roll_2)
p1_move = False
p2_move = True
return p1_move, p2_move
elif p2_move is True:
roll_die(p1_move, p2_move)
update_position (random_roll_1, random_roll_2)
p1_move = True
p2_move = False
return p1_move, p2_move
This function basically shows the user which location they are currently sitting at.
def display_state (player_1_position, player_2_position, p1_move, p2_move):
if p1_move is True:
player_1_position = str(player_1_position)
print('Player 1 is in ' + player_1_position + ' spot')
player_1_position = int(player_1_position)
elif p2_move is True:
player_2_position = str(player_2_positon)
print('Player 2 is in ' + player_2_position + ' spot')
player_2_position = int(player_2_position)
Not entirely sure if this function is right at all because I still don't understand main functions completely so not sure if this main function works
def main():
#display instructions
continue_game = True
while continue_game:
opponent()
display_state (player_1_position, player_2_position, p1_move, p2_move)
check_game_over(player_1_position, player_2_position)
main()
So there are a few errors in your program above. The runtime error you stated above is caused when you try to pass 2 variables into the update_position function before they have been defined.
roll_die (p1_move, p2_move)
## random_roll_1 and random_roll_2 have not been defined
update_position (random_roll_1, random_roll_2)
However, before you deal with this error, there is a key programming concept to understand. Global and Local variables.
A Global variable is one which the entire program can use. They are normally defined at the top of your program:
p1_move = True
p2_move = False
def roll_die(): ...
def main(): ...
etc
A Local variable is one which can only be used inside of the function it was created in.
def foo():
x = 10
y = 5
return x + y
In this example, the variables x and y are local variables and cannot be used in other functions of your program (as they only exist inside the function foo).
One thing to note, in the case where you pass a variable as a functional argument, then modify that variable in the function without returning the modified variable. That variable will only be modified inside that function, no where else. This is true for primitive data types (variables not passed by reference).
def foo(z):
z += 1
z = 5
foo(z)
print(z)
In this example, the output would be 5, not 6 as the modified z variable in the function foo has not been returned.
For this reason alone, global variables may seem like the better option, however in general global variables are a bad idea and it is recommended that you stick to using local variables.
More information about Global and Local variables.
With this knowledge, some of your errors may seem more obvious.
For example, in your function roll_die, you define 2 variables random_roll_1 and random_roll_2. However you try to use these variables in other functions, update_position for example.
I realise that you have tried to return each random_roll variable independently from the roll_die function, however you do not store these returned values.
# Original
roll_die (p1_move, p2_move)
# Correctly returned
random_roll = roll_die(p1_move, p2_move)
In the next line, you then try to use both random_roll_1 and random_roll_2 variables, even though you only know 1 of those variables at that stage.
# Original
update_position (random_roll_1, random_roll_2)
# Possible Correction
update_position(random_roll)
You would then have to redefine the update_position function, thinking about each player's go as if it happened one after another, and not both at the same time.
I would also like to emphasize the importance of reducing the amount of duplicate code in your program.
Your opponent function could instead be written as:
def opponent(p1_move, p2_move):
random_roll = roll_die(p1_move, p2_move)
update_position(random_roll)
p1_move = not p1_move
p2_move = not p2_move
return p1_move, p2_move
This refactoring has changed a few details, most importantly, the use of the not. This operator will turn True->False and False->True. For example, if p1_move is false, not p1_move is True.
In addition, the function has parameters p1_move, p2_move, as these variables will be required in other parts of your program, you should define them outside of this functions scope, and pass them as arguments into your other functions. And don't forget to store the return values!
Just to note, this function refactoring is an example of how to reduce duplicate code, and is designed to be used with your modified program.
There are a few more modifications required to make your program run, but I will let you work them out for yourself.

Why changing a function argument reflects to the main value that is I passed to that function?

I have tried to create a BLACKJACK game using python (actually I'm learning python). Currently I have not setup bet command (that is written in my Account class). I only takes name from my Account class.
I have a main file : blackjack.py
and two classes in files : deckofcards.py, account.py
I am only accessing name from account class, so I wont be putting that long mess here.
blackjack.py :
from account import Account
player = Account('kalaLokia')
cards = DeckOfCards()
play = False
playershand = []
dealershand = []
action = ''
blackjack = False
def showCards(items, name):
'''
Shows {name}'s cards and hand value
'''
print(f"{name}'s hand: ")
print(f"\t{' - '.join(items)}")
print(f"Hand value: {cards.handValue(items)}")
def bust(hand):
'''
Whether a someone has busted or not
'''
if(cards.handValue(hand) > 21):
return True
return False
def dealersMove():
'''
Dealers move: executes when player calls "stand"
Dealer perform hit until he gets bust, wins or his hand value becomes >= 17
When hand value is >17 and players has greater value, dealer loses ;-)
'''
global blackjack
if(cards.handValue(dealershand) == 21):
print('Dealer got a BLACKJACK')
print('Dealer WINS')
return
elif(blackjack):
print(f'{player.name} got a BLACKJACK')
print(f'{player.name} WINS')
blackjack=False
return
while(not bust(dealershand)):
if(cards.handValue(dealershand) > cards.handValue(playershand)):
print('Dealer WINS')
showCards(dealershand, 'Dealer')
break
elif(cards.handValue(dealershand) == cards.handValue(playershand)):
print("It's a TIE!!\n Dealer WINS")
break
elif(cards.handValue(dealershand) > 17):
print(f'Dealer loses\n{player.name} has WON.')
print(f'{cards.handValue(playershand)} > {cards.handValue(dealershand)}')
break
dealershand.append(cards.hit())
else:
print(f'Dealer busts! \n{player.name} has WON the game.')
def start():
'''
The actiona that can be performed
'''
global blackjack
if(cards.handValue(playershand) == 21):
blackjack = True
dealersMove()
return
while(not bust(playershand)):
action = input(
f"{player.name}'s turn: Do you want to hit or stand ? ").lower()
if(action == 'hit'):
playershand.append(cards.hit())
showCards(playershand, player.name)
elif(action == 'stand'):
dealersMove()
break
else:
print('Please enter a valid action !')
else:
print(f'{player.name} has been BUSTED')
if __name__ == "__main__":
print(f'Hello {player.name}, Welcome to BlackJack Game')
# Tell game rules here, may be
response = input('Do you want to start the game (Y/n)? ').lower()
if(response != 'y'):
play = False
print('You have been exited the game')
else:
play = True
# Ask for bet amount later
while(play):
cards = DeckOfCards()
cards.shuffle()
print('Cards on the table is now shuffled')
playershand = list(cards.initiate())
dealershand = list(cards.initiate())
print(
f"{player.name}'s hand:\n {playershand[0]} - {playershand[1]}\nHand value: {cards.handValue(playershand)}\n")
print(f"Dealer's hand:\n {dealershand[0]} - ?\n")
start()
if(input('Do you want to play again (Y/n)?').lower() != 'y'):
print('The End')
play = False
deckofcards.py :
import random
class DeckOfCards():
'''
All talks here is about cards
'''
cards = {'A':11,'K':10,'Q':10,'J':10,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9,'10':10}
def __init__(self):
'''
Initialize deck of cards
'''
self.deck = list(self.cards.keys())*4
def shuffle(self):
'''
Simply shuffles the deck of cards
'''
return random.shuffle(self.deck)
def handValue(self, hand):
'''
Calculates and returns the hand value, expecting a string value to be feeded.
'''
result = 0
for element in hand:
result = result + self.cards[element]
while('A' in hand and result > 21):
if(hand[0]=='A'):
result = result - 10
# Somehow this hand.pop is poping out from main value itself. Why ???
hand.pop(0)
if(hand == []):
break
return result
def hit(self):
'''
Pop out and returns the last card in the deck
'''
return self.deck.pop()
def initiate(self):
'''
Pop out 2 cards from the deck and return as a tuple
'''
return (self.deck.pop(), self.deck.pop() )
Issue:
When I have an ACE in my hand and my hand value is greater than 21, the while condition executes in the handValue function (which is in DeckofCards class) as it is. Problem is, after that while condition executes, playershand (declared in main file) I just passed to this handValue function gets empty. That is the hand.pop(0) actually seems popping out value from main object playershand itself (It seems me so).
When I press a hit after that, I get a single new card, all other cards are got popped out. I don't understand why it is so.
On hit(user enter hit) : actually I am passing playershand (cards on the player hand, it's a list) to function showCards (which is also in the main file) where it takes it as argument items and pass it to handValue function in the class DeckOfCards.
So why is it happening? even though I am passing playershand as an argument to other functions, how pop() function affecting playershand which has only access to hand object in the handValue class ?
I have my complete code in github repo to test out, the files in folder blackjack

Is it possible to use a variable then later redefine it?

I´m making a project for school and it is a dice game. This snippet of my code is like a catch 22.
I need to define a variable otherwise it flags, so I do this but then every time the button is run it changes the value to zero instead of increasing it.
if Rollnop1 == 0 :
Userscore1 = Randomnumber
print ("User 1 ",Userscore1 )
Rollnop1 = Rollnop1+1 #But this changes it so it will go to the next players roll, every
#time the button is pressed it changes the variable back to 0
def gamerun():
global Player
global usernamestr
global passwordstr
global usernamestr2
global passwordstr2
Rollnop1 = 0
def roll2():
Rollnop2 = 0
Randomnumber = random.randint(2,12)
print ("Console: Random Number 2 = ",Randomnumber)
if Rollnop2 == 0 :
Userscore2 = Randomnumber
print ("User 2 ",Userscore2 )
def roll1():
Rollnop1 = 0 #Need to define this here otherwise It wont work
Randomnumber = random.randint(2,12)
print ("Console: Random Number = ",Randomnumber)
if Rollnop1 == 0 :
Userscore1 = Randomnumber
print ("User 1 ",Userscore1 )
Rollnop1 = Rollnop1+1 #But this changes it so it will go to the next players roll, every
#time the button is pressed it changes the variable back to 0
else:
roll2()
actdicegame = Tk()
gamerunl0 = Label(actdicegame, text = usernamestr, fg = "black")
gamerunl0.pack()
gamerunl1 = Label(actdicegame, text = "Roll The Dice", fg = "black")
gamerunl1.pack()
gamerunb1 = Button(actdicegame, text="ROLL",fg="Black", command=roll1)#Register Butto
gamerunb1.pack()
actdicegame.geometry("350x500")
print ("Console: GUI RUNNING 1")
actdicegame.mainloop()
snippet https://pastebin.com/FSWwBGpA
Use an option where you provide the player as part of the roll, that way you say which player is playing at any given time. The function below plays for the provided player and returns who is playing next
def roll(Rollnop=0):
UserScore = random.randint(2,12)
print ("Console: Random Number 2 = ", UserScore)
if Rollnop == 0 :
print ("User 1 ", UserScore)
return 1
else:
print ("User 2 ", UserScore)
return 0
This could answer your question: nested function change variable in an outside function not working. Basically you need to assign Rollnop1 = 0 and Rollnop2 = 0 in gamerun and declare them as nonlocal inside roll1 & roll2 before attempting to change their value.
– DarrylG Thank You so much and to everyone else who helped.
More here
nested function change variable in an outside function not working

If statement does not detect string or doesn't take action

I wanted to make a bot that plays Rock, Paper, Scissors with the player.
But every time I try to run the script, and type in Stein (German for rock),
the if statement doesn't detect it or doesn't take any action.
Here's my code so far:
import random
import time
print("Anfangs Buchstaben immer groß schreiben!")
time.sleep(2)
outcomes2 = ("Stein")
Runde = 0
while True:
Player = input("Deine Wahl: ")
for i in range(1):
outcomes = print(random.choice(outcomes2))
if outcomes == Player:
print("draw")
Runde + 1
continue
Issue 1
>>> outcomes2 = ("Stein")
>>> print(random.choice(outcomes2))
n
You're iterating over a string and selecting a character at random.
I'm assuming you want:
>>> outcomes2 = ("Stein", )
>>> print(random.choice(outcomes2))
Stein
Now, by specifying the ,, you're iterating over a tuple of strings (tuple of size 1). You'll end up getting "Stein" only unless you add more strings, like
outcomes2 = ("Stein", "Name2", "Name3", ...)
Issue 2
You want outcomes = random.choice(outcomes2). Do not assign the value to the print statement, because print returns None.
Putting it together...
outcomes2 = ("Stein", )
Runde = 0
while True:
Player = input("Deine Wahl: ")
outcomes = random.choice(outcomes2)
if outcomes == Player:
print("draw")
Runde + 1
continue
`import time
import random
comp_score=0
play_score=0
outcome=('rock','paper','scissor')
while True:
player = raw_input("Enter any?");
out=random.choice(outcome)
print "COMP->"+out
if out==player:
print "draw"
elif out=="rock"and player=="scissor":
comp_score+=1;
elif out=="scissor" and player=="rock":
play_score+=1;
elif out=="rock" and player=="paper":
play_score+=1;
elif out=='paper' and player=='rock':
comp_score+=1;
elif out=="scissor" and player=="paper":
play_score+=1;
elif out=='paper' and player=="scissor":
comp_score+=1;
elif player=="quit":
break;
print "GAME over"
print "PLayer score: ",play_score
print "Comp score ",comp_score`

Need help writing algorithm in Python/Sage

I'm a complete novice to python and sage so I need some help and clarification on the steps all the way through. This is a question concerning game theory.
First I will describe the algorithm and then I will propose a solution the best I can.
The algorithm:
I want to start the program with a random variable from 1-100. This
variable will be defined 'S'. I also want to define a set of variables
'C' which can be deducted from S every turn, this set is {1,2,3,4,5,6}
(in other words the user and computer can deduct 1, 2, 3, 4, 5 or 6
from S. If variable S is divisible by 7 (e.g. 21), then print: "I
lose". If not, the game can begin.
Let's say that the random variable turns out to be 20. The player is
now prompted to enter a number within the range of C. When the player
has entered the number, I want the program to deduct that number from
S, so if the player enters 4 (a legal move), S is then 20-4=16. The
computer then calculates mod(S,7) and finds out that modulo 16,7 is 2
so it deducts 2 from S, in other words, 16-2=14.
If the player enters a number which results in S being divisible by 7, such as 6 (20-6=14) then the computer simply deducts 1 and attempts to get to such a number again next round.
The game continues until the computer eventually wins as the player is
eventually placed at 7 and has to deduct a number which the computer
can finish with (user deducts 6, computer deducts the last one and
wins). Print: "I win".
So like I said, I have literally no experience in python and sage so I can only go by my (limited) java experience:
I would attempt to establish a variable S with some 'ran' element (no idea what it's called in python). I would then attempt something like:
if S%7=0 then print "I lose"
else
prompt "Pick a number between 1 and 6, those included".
Declare user input as variable U.
Do S-U=S
Now do S-S%7=S
Now I want the program to realize when S=7 and then print: "You lose". If you can help me go all the way, though, that would be great.
import random
def playgame():
s = random.randint(1,100) #grabs a random integer between 1 and 100
POSS = range(1,7) #range ignores the last number, so this is [1,2,3,4,5,6]
if not s % 7: #if s%7 != 0
print("I lose")
return #exit the function
while s > 0: #while s is still positive
choice = 0 #set choice to 0 (this may as well have been "foo",
# I just needed it to not be in POSS)
while choice not in POSS: #until the user picks a valid number
choice = int(input("Select a number between 1 and 6: ")) #prompt for input
s -= choice #subtract choice from s, then set the difference to s
print("You subtracted {}, leaving {}".format(choice,s)) #print for the user
comp_choice = s%7 #the computer's choice is always s%7
s -= comp_choice #subtract the comp's choice from s, then set the diff to s
print("I subtracted {}, leaving {}".format(comp_choice,s)) #print for user
print("I win!") #since we know computer will always win, I don't have to do a check
playgame() #run the function
Here's a vastly more complicated function that does essentially the exact same thing ;-)
class Entity(object):
"""Base class that should not be instantiated on its own -- only
exists to be inherited from. Use Player() and Computer() instead"""
def __init__(self,name=None):
if name is None:
name = input("What's your name? ")
self.name = name
self.myturn = False
def __str__(self):
# this magic function means calling str(self) returns str(self.name)
# included so I can do print(player)
return self.name
def makemove(self,choice):
"""finds the global s and subtracts a given choice from it,
printing the choice and the result to the user."""
global s
s -= choice
print("{} chooses {}, leaving {}".format(self,choice,s))
return choice
def activate(self):
self.myturn = True
return self
def deactivate(self):
"""does exactly self.myturn = False"""
self.myturn = False
class Player(Entity):
"""A player-controlled Entity"""
def getchoice(self):
"""Prompts the user for a choice, ensuring it's between 1 and 6, then
calls Entity's makemove() with that as an argument"""
choice = None
while choice not in range(1,7):
choice = int(input("Pick a number between 1 and 6: "))
return super().makemove(choice)
class Computer(Entity):
def __init__(self):
super().__init__(name="Computer Player")
#overrides to ensure every Computer object has the name Computer Player
def getchoice(self):
"""grabs a number for the computer, and makes its move"""
global s
choice = s%7
if choice == 0: #edge case where computer goes first on an s where s%7==0
choice = random.randint(1,6)
return super().makemove(choice)
class Game(object):
"""Class defining an instance of the Game
FUNCTIONS:
Game.start() <-- use this to start the game"""
def __init__(self,playerArray=[]):
"""defines s as a global, ensures the players array is built
correctly, and gives s a random int value between 1-100"""
global s
if type(playerArray) is Player:
playerArray = [playerArray]
while len(playerArray) < 2:
playerArray.append(Computer())
self.players = playerArray
s = random.randint(1,100)
def start(self):
"""Let's play!"""
global s
print ("""
====================================
THE GAME BEGINS NOW!!!
We will begin with a value of: {:3}
====================================""".format(s).lstrip())
turn = random.randint(1,len(self.players))-1
while True:
try:active_player = self.players[turn].activate()
except IndexError: print(turn)
choice = active_player.getchoice()
if s <= 0: break
active_player.deactivate() # is active_player.myturn = False
turn += 1
if turn == len(self.players): turn = 0 #wrap the list
for player in self.players:
#this will execute the turn s becomes zero
if player.myturn:
winner = player
break
print("Winner: {}".format(winner))
import random
game = Game()
game.start()
S=random.randint(1,100) #will pick a random number
user_input = int(raw_input("Enter a number:")) #will get an integer from the user
#subtraction and modulo work just like in any other language ...
if(condition):
do_something() #is the format for if statements
does that cover all your questions? or did I miss some?

Categories