I am a python newbie and this is my first question on stackoverflow so sorry if it's not correct. I am programming my own rock, paper scissors game in Python, which includes a computer class which remembers the previous turn of the player. However, I can only get it to return random.choice moves, and I am not sure where I am going wrong?
moves = ['rock', 'paper', 'scissors']
class Player:
def __init__(self):
self.my_move = None
self.their_move = None
def learn(self, my_move, their_move):
self.my_move = my_move
self.their_move = their_move
def beats(one, two):
return ((one == 'rock' and two == 'scissors') or
(one == 'scissors' and two == 'paper') or
(one == 'paper' and two == 'rock'))
class MemoryPlayer(Player):
def move(self):
if self.their_move in moves:
return self.their_move
else:
return random.choice(moves)
class Game:
def __init__(self, p1, p2):
self.p1 = p1
self.p2 = p2
self.scorep1 = 0
self.scorep2 = 0
# starting score of both players
def play_round(self):
firstmove = self.p1.move()
secondmove = self.p2.move()
print(f"Player 1: {firstmove} Player 2: {secondmove}")
# prints move of Player 1 and Player 2 after each round
if beats(firstmove, secondmove):
self.scorep1 += 1
print(f"Player 1 Wins. Score: {self.scorep1}"
f" to {self.scorep2}")
elif beats(secondmove, firstmove):
self.scorep2 += 1
print(f"Player 2 Wins. Score: {self.scorep2}"
f" to {self.scorep1}")
else:
print(f"Boring - TIE. Score: {self.scorep1}"
f" to {self.scorep2}")
# uses beats function in if and else statement to define score increase
# if player 1 move beats player 2 move and vice versa
def play_game(self):
print("Game start!")
self.rounds = 3
for round in range(self.rounds):
print(f"Round {round}:")
self.play_round()
print(f"Game over! Final score:\
Player 1: {self.scorep1}), Player 2: {self.scorep2}")
# prints final secores for Player 1 and Player 2
if self.scorep1 > self.scorep2:
print("Player 1 is Triumphant")
# if player 1 score is greater than player 2 - prints winning statement
elif self.scorep2 > self.scorep1:
print("Player 2 is Triumphant")
# if player 2 score is greater than player 1 - prints winning statement
else:
print("Boring - TIE")
if __name__ == '__main__':
game = Game(HumanPlayer(), MemoryPlayer())
# randomly chooses opposing NPC
game.play_game()
Related
I want to make a card game simulation called 'Game of War" in Python, which can input the number of times that we want to play, for example, 3 times, the output should be like this Enter in the number of simulations for War Game: 10 Sim 1 Player 1 is the winner Sim 2 Player 1 is the winner Sim 3 The game was a draw FINAL RESULT: Player 1 won 2 times Player 2 won 0 times There were 1 draw
For now, I'm having a problems with create a function sim_num_games(sim_num) that asks the user for how many simulations they would like to run. The function must return the results for player 1, player 2 and the number of times a game was a tie. Then its must display how many times Player 1 wins, how many times Player 2 wins, and how many times the game was a tie. This is what I got so far.
deck = []
suits = ["Clubs", "Diamonds", "Hearts", "Spades"]
def create_deck():
for suit in suits:
for rank in range(2,15):
deck.append((rank,suit))
return deck
def deal_cards(the_deck):
if the_deck[0] <= 10: rank = str(the_deck[0])
if the_deck[0] == 11: rank = "Jack"
if the_deck[0] == 12: rank = "Queen"
if the_deck[0] == 13: rank = "King"
if the_deck[0] == 14: rank = "Ace"
fullname = rank + " of " + the_deck[1]
return fullname
def draw_card(player):
the_deck = deck[0]
deck.remove(deck[0])
print(player + 'has: ' + deal_cards(the_deck))
return the_deck
def play_game(p1_cards,p2_cards):
if p1_cards[0] > p2_cards[0]:
return "Player one"
if p1_cards[0] < p2_cards[0]:
return "Player two"
else:
return "DRAW!!!!!!!!"
def main():
deck = create_deck()
random.shuffle(deck)
round_play = 1
p1_score = 0
p2_score = 0
draw = 0
print("ALRIGHT, Let's Play...")
while len(deck) >= 2:
print("Hand number: ", round_play)
player_one_card = draw_card("Player 1 ")
player_two_card = draw_card("Player 2 ")
winner = play_game(player_one_card, player_two_card)
round_play += 1
if winner == "Player one": p1_score += 1
if winner == "Player two": p2_score += 1
if winner == "DRAW!!!!!!!!": draw += 1
print(f"{winner} wins")
else:
print("-"*15)
print("FINAL GAME RESULTS:","\nPlayer 1 won ", p1_score," hands" ,"\nPlayer 2 won ", p2_score," hands","\n",draw," hands were draw")
main()```
This can generate the deck and play but I cannot put the sim_num_games(sim_num) function in since it always error..
I would do something like this as your main structure.
p1_score = 0
p2_score = 0
draw = 0
ngames = int(input("How many games you want to simulate?"))
for _ in range(ngames):
winner = play_game()
if winner == 1:
p1_score += 1
elif winner == 2:
p2_score += 1
else:
draw += 1
if p1_score > p2_score:
print(f"Player 1 wins {p1_score} of {ngames} games")
elif p1_score < p2_score:
print(f"Player 2 wins {p2_score} of {ngames} games")
else:
print("draw")
Now, you have to put all the logic that initializes a game, plays it and determines a winner inside a function play_game(), which will return either 0, 1 or 2
Ideally you should create a class to have things better organized, but having functions hanging around will also work since it's a small project.
You can also make helper functions, so your main structure keeps as clean as possible. For example you can create a function update_scores() and a function determine_winner() that will take code out of the main structure and make it cleaner.
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.
This was a Rock scissors paper game code ,its a humanplayer versus a reflectplayer. Reflectplayer who copy the last time humanplayer move and show the move. I tried to access the move2 from the play_round to ReflectPlayer . But How? Isn't game1.play_round.move2 work?
import random
moves = ['rock', 'paper', 'scissors']
class Player:
def move(self):
return 'rock'
def learn(self, my_move, their_move):
pass
class RandomPlayer:
def move(self):
all = ["rock","scissors","paper"]
ranint = random.randint(0,2)
return all[ranint]
def learn(self, my_move, their_move):
pass
class HumanPlayer:
def move(self):
ans = input("Rock Paper or Scissors?").lower()
return ans
def learn(self,my_move,their_move):
pass
class ReflectPlayer:
def move(self):
i = 1
RSP = ["rock","paper","scissors"]
print(self.move2)
if i == 1:
i += 1
return RSP[random.randint(0,2)]
elif game1.play_round.move2 == RSP[0]:
return RSP[0]
elif game1.play_round.move2 == RSP[1]:
return RSP[1]
elif game1.play_round.move2 == RSP[2]:
return RSP[2]
else:
print("Wrong input !")
pass
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 Game:
def __init__(self, p1, p2):
self.p1 = p1
self.p2 = p2
def play_round(self):
move1 = self.p1.move()
move2 = self.p2.move()
print(f"Player 1: {move1} Player 2: {move2}")
if beats(move1 , move2) == True:
print(f"This Round : Player 1 WIN")
elif beats(move2 , move1) == True:
print(f"This Round : Player 2 WIN")
elif move1 == move2:
print("This Round : TIE")
else:
print("Wrong Input !")
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}:")
self.play_round()
print("Game over!")
if __name__ == '__main__':
game1 = Game(ReflectPlayer(),HumanPlayer())
game1.play_game()
Consider changing your implementation to pass the last moves played to the move() method. If your player needs to use the previous moves then you can access them easily. If not just discard them. I am assuming that you will have other types of players that can benefit from this.
rsp = ['rock', 'paper', 'scissors']
class ReflectPlayer:
def move(self, lastOpponentMove):
if lastOpponentMove == None:
return rsp[random.randint(0,2)]
elif lastOpponentMove == rsp[0]:
return rsp[0]
elif lastOpponentMove == rsp[1]:
return rsp[1]
elif lastOpponentMove == rsp[2]:
return rsp[2]
else:
print("Wrong input !")
pass
def learn(self,my_move,their_move):
pass
Possible adaption on the Game class:
class Game:
def __init__(self, p1, p2):
self.p1 = p1
self.p2 = p2
self.lastP1Move = None
self.lastP2Move = None
def play_round(self):
move1 = self.p1.move(lastP2Move)
move2 = self.p2.move(lastP1Move)
lastP1Move = move1
lastP2Move = move2
print(f"Player 1: {move1} Player 2: {move2}")
if beats(move1 , move2) == True:
print(f"This Round : Player 1 WIN")
elif beats(move2 , move1) == True:
print(f"This Round : Player 2 WIN")
elif move1 == move2:
print("This Round : TIE")
else:
print("Wrong Input !")
self.p1.learn(move1, move2)
self.p2.learn(move2, move1)
Some notes:
You defined rsp as global in the beginning so you can use that list instead of creating new ones.
The way you implemented the check to see if it was the first play would make it so that i would be 1 everytime. (I changed to see if you are receiving a None last move).
Check your indentation in the play_round method
Hope this helps
I have made a dice roll game on Python 3 but want to add a betting function.
I have tried a few things but I can only play one game. I want the game to have multiple rounds.
How do I make it a game where the player(s) can bet on multiple rounds until money ends at 0, or possibly keep playing until they want to stop?
import random
import time
print("this is a dice roll game")
def main():
player1 = 0
player1wins = 0
player2 = 0
player2wins = 0
rounds = 1
while rounds != 5:
print("Round" + str(rounds))
time.sleep(1)
player1 = dice_roll()
player2 = dice_roll()
print("Player 1 rolled " + str(player1))
time.sleep(1)
print("Player 2 rolled " + str(player2))
time.sleep(1)
if player1 == player2:
print("The round is a draw")
elif player1 > player2:
player1wins += 1
print("Player 1 wins the round")
else:
player2wins += 1
print("Player 2 wins the round")
rounds = rounds + 1
if player1wins == player2wins:
print("The game ended in a draw")
elif player1wins > player2wins:
print("Player 1 wins the game, Rounds won: " + str(player1wins))
else:
print("Player 2 wins the game, Rounds won: " + str(player2wins))
def dice_roll():
diceroll = random.randint(1,6)
return diceroll
main()
Adding to the comment by John Coleman, you can modify your while loop so that it does not end when the number of rounds is different to 5, something like:
while True:
// Rest of code...
if moneyP1 <= 0 OR moneyP2 <=0:
print("Someone ran out of money")
// Implement deciding who won
break
user_confirmation = raw_input("Keep playing? (YES/NO): ")
if user_confirmation == "NO":
break
My code is not working. It says required argument 'HumanMove'.
I pretty much don't understand what python is trying to tell me.
see the code below.
The computer is bugging at this line: HumanMove = self.HumanPlayer.move()
import random
#Create player class
class Player:
def move(self):
return 'rock'
def learn(self, my_move, their_move):
pass
#Create random player class
class RandomPlayer:
def __init__(self):
Player.__init__(self)
def move(self, RandomPlayerMove):
self.move = RandomPlayerMove
#use imported random function
RandomPlayerMove = random.randint(1,3)
#Computer choice is either rock, paper, or scissors
if RandomPlayerMove == ("Rock"):
print("The computer choses ROCK")
elif RandomPlayerMove == ("Paper"):
print("The computer choses PAPER")
else:
print("The computer choses SCISSORS")
#return value
return RandomPlayerMove
#Create human player class
class HumanPlayer:
def __init__(self):
Player.__init__(self)
def move(self, HumanMove):
return HumanMove
##class that remembers what move the opponent played last round
class ReflectPlayer:
def __init__(self, ReflectPlayer):
Player.__init__(self)
self.ReflectPlayer = ReflectPlayer
#def move
def move(self, move):
self.move = move
def getmove(self, move):
return self.move
#define cycleplayer class that remembers what move it played last round,
# and cycles through the different moves.
class CyclePlayer:
def __init__(self, CyclePlayer):
Player.__init__(self)
self.CyclePlayer = CyclePlayer
self.human_player_history = {} # stores the frequency of human player
moves
for move in moves:
self.human_player_history[move] = 0
def move(self, max_move):
max_move = max(self.human_player_history.items(), key=lambda elem:
elem[1])[0]
if max_move == 'rock':
return 'paper'
if max_move == 'scissors':
return 'rock'
if max_move == 'paper':
return 'rock'
def beats(one, two):
return ((one == 'rock' and two == 'scissors') or
(one == 'scissors' and two == 'paper') or
(one == 'paper' and two == 'rock'))
#Create game class
class Game:
def __init__(self, HumanPlayer, RandomPlayer):
self.HumanPlayer = HumanPlayer
self.RandomPlayer = RandomPlayer
def play_round(self):
HumanMove = self.HumanPlayer.move()
RandomPlayerMove = self.RandomPlayer.move()
print(f"HumanPlayer: {HumanMove} RandomPlayer: {RandomPlayerMove}")
self.HumanPlayer.learn(HumanMove, RandomPlayerMove)
self.RandomPlayer.learn(RandomPlayerMove, HumanMove)
if beats(HumanMove, RandomPlayerMove):
print("HumanPlayer wins this round")
self.HumanPlayer.score += 1
elif beats(RandomPlayerMove, HumanMove):
print("RandomPlayer wins this round")
self.RandomPlayer.score += 1
else:
print("It's Tie, Play again!")
print(f"Scores, HumanPlayer: {self.p1.score} RandomPlayer:
{self.p2.score}")
def move(self, HumanMove):
^^^^^^^^^
return HumanMove
You defined move with the parameter HumanMove. When you call the method you must supply an argument for that parameter.