Feb-27-2022, 08:46 AM
Very good code, it would greatly simplify the one I have, but I insist that I can only use the new code, I only need to create the get_winner, which now I do not understand because I have to enter the new parameter.
Rock paper scissors in python with "algorithm"
|
Feb-27-2022, 08:46 AM
Very good code, it would greatly simplify the one I have, but I insist that I can only use the new code, I only need to create the get_winner, which now I do not understand because I have to enter the new parameter.
Feb-27-2022, 04:03 PM
This is a fairly simple programming task. You have a list of opponent plays. You need to determine which play appears most often in the list. This is your prediction of what the opponent will play next. You chose a play that defeats this play.
Write out the algorithm any way you want (other than using Python). Use natural language, pseudo code, draw pictures. Once the algorithm is defined well enough that you can describe it to others, implement the algorithm in Python. Programming and coding are two different tasks. Don't let despair make a mountain out of this molehill.
Feb-27-2022, 05:42 PM
(This post was last modified: Feb-28-2022, 08:34 AM by Yoriz.
Edit Reason: removed unnecessary quote of previous post
)
I understand but I've been like this for several days and I can't, I don't know how to create it.
Feb-27-2022, 06:08 PM
(This post was last modified: Feb-27-2022, 06:09 PM by deanhystad.)
Write the algorithm and post it here. Don't worry about what you partner wrote, just focus on what needs to be done to pick a move that beats the most common move made by the opponent.
After doing that, convert it to Python and write a standalone test program to verify it works. Something like this: def get_winning_move(history): # your code goes here return selected_move print(get_winning_move([1, 1, 1, 0, 0]), "should be 2: scissors") print(get_winning_move([1, 2, 1, 2, 0]), "should be 0: rock") print(get_winning_move([1, 0, 2, 0, 0]), "should be 1: paper")Once you have that working it should be easier to see how this code can be integrated with the existing code. For entertainment purposes the program below plays Rock, Paper, Scissors, Lizard, Spock using a history based AI. It can also play Rock, Paper, Scissors or any other similarly constructed game based on rules you provide. Notice the lack of aggravating enumerated types and rediculously long function and variable names. """ Rock-Paper-Scissors like rule based game creator.""" import random class Player: """A human player. Human players enter play by typing in a one letter abbreviation""" def __init__(self, plays, name=None): self.name = "Player" if name is None else name self.abbr = {play.abbr:play for play in plays.values()} prefix = "Select" if name is None else f"{name} select" self.prompt = f"{prefix} {', '.join([play.menu_name for play in plays.values()])}: " def choice(self, _): """Get player choice""" while True: abbr = input(self.prompt).upper() if abbr in self.abbr: return self.abbr[abbr] print(f"{abbr} is not a valid selection") class Computer: """A computer player. The computer's choice is based on opponent's move history""" def __init__(self, plays, name="Computer"): self.name = name self.plays = plays self.play_names = list(plays.keys()) def choice(self, history=[]): """Predict what opponent will do based on history. Select move that defeats predicted move""" opp_choice = self.plays[random.choice(self.play_names + history)] winning_plays = [play for play in self.plays.values() if play.beats(opp_choice)] return random.choice(winning_plays) class Play: """A play in a Rock/Paper/Scissor type game""" def __init__(self, name, plays): self.rules = {} self.name = name self.key = name.upper() # Pick a unique abbreviation for player selection abbr = [play.abbr.upper() for play in plays.values()] for index, self.abbr in enumerate(self.key): if self.abbr not in abbr: break self.menu_name = name.replace(name[index], f"({name[index]})", 1) def add_rule(self, loser, rule): """Tell me how I beat other moves""" self.rules[loser.upper()] = rule def beats(self, other): """Return rule if I beat other, else None""" return self.rules.get(other.key, None) class Game: """ Create a Rock/Paper/Scissor type game based on a list of rules in the form: MOVE_A defeats MOVE_B """ def __init__(self, rules): # Create plays. Rules start and end with a play name. self.plays = {} for rule in rules: words = rule.split() winner = words[0] loser = words[-1] key = winner.upper() # Make case insensitive if key not in self.plays: self.plays[key] = Play(winner, self.plays) self.plays[key].add_rule(loser, rule) def play(self, rounds=-1, p1=None, p2=None): """Play the game. Use rounds to set how many rounds are played. if < 0, play til someone wins Use p1 to set player 1 name. If None, player name is "Player". Use p2 to set select player 2 type. If None, player 2 is Computer, else Player(p1)""" player = [Player(self.plays, p1), Computer(self.plays) if p2 is None else Player(self.plays, p2)] results = { player[0].name: 0, player[1].name: 0, "Draw":0 } history = [] # Play game while rounds != 0: rounds -= 1 play = [p.choice(history) for p in player] history.append(play[0].key) # TBD: Change to only record player[0] wins? if play[0] == play[1]: results["Draw"] += 1 print("Both player select {play[0].name. Draw.\n") else: winner, rule = 0, play[0].beats(play[1]) if rule is None: winner, rule = 1, play[1].beats(play[0]) results[player[winner].name] += 1 print( f"{player[0].name} selects {play[0].name}, " f"{player[1].name} selects {play[1].name}. " f"{rule}. {player[winner].name} wins!\n") if rounds < 0: return # Game was play until winner print("\nResults") for name, count in results.items(): print(f"{name:10} : {count}") # Single player Rock/Paper/Scissors/Lizard/Spock game Game([ "Rock crushes scissors", "Rock crushes lizard", "Paper covers rock", "Paper disproves Spock", "Scissors cuts paper", "Scissors decapitates lizard", "Lizard eats paper", "Lizard poisons Spock", "Spock smashes scissors", "Spock vaporizes Rock", ]).play(-1) # Bert and Ernie play Rock/Paper/Scissors 3 times # Game(["Rock crushes scissors", "Paper covers rock", "Scissors cuts Paper"]).play(3, "Bert", "Ernie")
In the end I was able to do it thanks to what I was looking for through the dictionary of victory made
Feb-28-2022, 12:29 AM
(This post was last modified: Feb-28-2022, 12:31 AM by deanhystad.)
Please post entire error trace.
You get an error because computer_action is an integer, not a GameAction. from enum import IntEnum class GameAction(IntEnum): Piedra = 0 Papel = 1 Tijeras = 2 Lagarto = 3 Spock = 4 x = 1 y = GameAction(x) print(x, y) x is an int, y is a GameAction. You need to convert the computed computer_action from int to a GameAction.
Feb-28-2022, 10:43 AM
(This post was last modified: Mar-01-2022, 03:19 PM by Agat0.
Edit Reason: removed unnecessary quote of previous post
)
In the end I was able to do it thanks to what I was looking for through the dictionary of victory madeon]
In the end I was able to do it thanks to what I was looking for through the dictionary of victory made
Feb-28-2022, 07:09 PM
(This post was last modified: Feb-28-2022, 08:48 PM by deanhystad.)
Trying to stay within the restraints of the original code I would write the code like this:
import random from enum import IntEnum class GameResults(IntEnum): Win = 0 Lose = 1 Draw = 2 class GameAction(IntEnum): Piedra = 0 Papel = 1 Tijeras = 2 def __str__(self): """Return str more suited for program.""" return f"{self.name}[{self.value}]" winning_results = { (GameAction.Piedra, GameAction.Tijeras) : "Piedra smashes tijeras", (GameAction.Papel, GameAction.Piedra) : "Papel covers piedra", (GameAction.Tijeras, GameAction.Papel) : "Tijeras cuts Papel", } def get_user_action(): """Get user selection""" prompt = f"""\nPick {", ".join([str(action) for action in GameAction])}: """ while True: try: action = input(prompt) return GameAction(int(action)) except ValueError: print(f"{action} is not a valid choice") def get_computer_action(): """Get computer selection""" return random.choice(list(GameAction)) def assess_game(user_action, computer_action): if user_action == computer_action: return GameResults.Draw, "" if (user_action, computer_action) in winning_results: return GameResults.Win, winning_results[(user_action, computer_action)] return GameResults.Lose, winning_results[(computer_action, user_action)] def main(): """Play a game of rock, paper, scissors""" while True: user_action = get_user_action() computer_action = get_computer_action() result, rule = assess_game(user_action, computer_action) if result == GameResults.Draw: print("Player and computer pick {}. Draw".format(user_action.name)) elif result == GameResults.Win: print("Player picks {}, computer picks {}. {}. Player wins!".format( user_action.name, computer_action.name, rule)) else: print("Player picks {}, computer picks {}. {}. Computer wins.".format( user_action.name, computer_action.name, rule)) if input("\nAnother round? (y/n): ").upper() != "Y": break if __name__ == "__main__": main()I don't think the enumerated types add value, but they aren't too onerous. Adding in the history based AI is just a few new lines. import random from enum import IntEnum class GameResults(IntEnum): Win = 0 Lose = 1 Draw = 2 class GameAction(IntEnum): Piedra = 0 Papel = 1 Tijeras = 2 def __str__(self): """Return str more suited for program.""" return f"{self.name}[{self.value}]" winning_results = { (GameAction.Piedra, GameAction.Tijeras) : "Piedra smashes tijeras", (GameAction.Papel, GameAction.Piedra) : "Papel covers piedra", (GameAction.Tijeras, GameAction.Papel) : "Tijeras cuts Papel", } def get_user_action(): """Get user selection""" prompt = f"""\nPick {", ".join([str(action) for action in GameAction])}: """ while True: try: action = input(prompt) return GameAction(int(action)) except ValueError: print(f"{action} is not a valid choice") def get_computer_action(history=[]): """Get computer selection. Use history to predict what user will do""" user_action = random.choice(history + list(GameAction)) computer_actions = [action for action in list(GameAction) if (action, user_action) in winning_results] return random.choice(computer_actions) def assess_game(user_action, computer_action): if user_action == computer_action: return GameResults.Draw, "" if (user_action, computer_action) in winning_results: return GameResults.Win, winning_results[(user_action, computer_action)] return GameResults.Lose, winning_results[(computer_action, user_action)] def main(): """Play a game of rock, paper, scissors""" history = [] while True: user_action = get_user_action() computer_action = get_computer_action(history) result, rule = assess_game(user_action, computer_action) if result == GameResults.Draw: print("Player and computer pick {}. Draw".format(user_action.name)) elif result == GameResults.Win: print("Player picks {}, computer picks {}. {}. Player wins!".format( user_action.name, computer_action.name, rule)) else: print("Player picks {}, computer picks {}. {}. Computer wins.".format( user_action.name, computer_action.name, rule)) if input("\nAnother round? (y/n): ").upper() != "Y": break history.append(user_action) if __name__ == "__main__": main()Adding lizard and Spock is easy with the right infrastructure. import random from enum import IntEnum class GameResults(IntEnum): Win = 0 Lose = 1 Draw = 2 class GameAction(IntEnum): Piedra = 0 Papel = 1 Tijeras = 2 Lagarto = 3 Spock = 4 def __str__(self): """Return str more suited for program.""" return f"{self.name}[{self.value}]" winning_results = { (GameAction.Tijeras, GameAction.Papel) : "Tijeras cuts Papel", (GameAction.Papel, GameAction.Piedra) : "Papel covers piedra", (GameAction.Piedra, GameAction.Lagarto) : "Piedra crushes lagarto", (GameAction.Lagarto, GameAction.Spock) : "Lagarto poisons Spock", (GameAction.Spock, GameAction.Tijeras) : "Spock smashes tijeras", (GameAction.Tijeras, GameAction.Lagarto) : "Tijeras decapitates lagarto", (GameAction.Lagarto, GameAction.Papel) : "Lagarto eats papel", (GameAction.Papel, GameAction.Spock) : "Papel disproves Spock", (GameAction.Spock, GameAction.Piedra) : "Spock vaporizes piedra", (): "\nand as it always has\n", (GameAction.Piedra, GameAction.Tijeras) : "Piedra smashes tijeras", def get_user_action(): """Get user selection""" prompt = f"""\nPick {", ".join([str(action) for action in GameAction])}: """ while True: try: action = input(prompt) return GameAction(int(action)) except ValueError: print(f"{action} is not a valid choice") def get_computer_action(history=[]): """Get computer selection. Use history to predict what user will do.""" user_action = random.choice(history + list(GameAction)) computer_actions = [action for action in list(GameAction) if (action, user_action) in winning_results] return random.choice(computer_actions) def assess_game(user_action, computer_action): if user_action == computer_action: return GameResults.Draw, "" if (user_action, computer_action) in winning_results: return GameResults.Win, winning_results[(user_action, computer_action)] return GameResults.Lose, winning_results[(computer_action, user_action)] def main(): """Play a game of rock, paper, scissors""" print("\n".join(["\nRules of the game:\n"] + [rule for rule in winning_results.values()])) history = [] while True: user_action = get_user_action() computer_action = get_computer_action(history) result, rule = assess_game(user_action, computer_action) if result == GameResults.Draw: print("Player and computer pick {}. Draw".format(user_action.name)) elif result == GameResults.Win: print("Player picks {}, computer picks {}. {}. Player wins!".format( user_action.name, computer_action.name, rule)) else: print("Player picks {}, computer picks {}. {}. Computer wins.".format( user_action.name, computer_action.name, rule)) if input("\nAnother round? (y/n): ").upper() != "Y": break history.append(user_action) if __name__ == "__main__": main()
Feb-28-2022, 07:49 PM
(This post was last modified: Feb-28-2022, 07:49 PM by deanhystad.)
You should be getting the most frequent USER action, not COMPUTER action. get_winning_action() will return an action that defeats the predicted user action.
|
|