I'm building a RPSLS game and I have an error that I am running into. Regardless of what input player 1 selects, player 2 always win.
# 10 winning pairs, defined as (winner,loser)
winningPairs = [("scissors,paper"),
("scissors,lizard"),
("Spock,scissors"),
("Spock,rock"),
("lizard,Spock"),
("lizard,paper"),
("rock,lizard"),
("rock,scissors"),
("paper,rock"),
("paper,Spock")]
# ask players for their name
print()
namePlayerOne = input("Player 1, enter your name: ")
namePlayerTwo = input("Player 2, enter your name: ")
print()
# Options that can be selected by any user
options = ["Rock","Paper","Scissors","Lizard","Spock"]
# set two variables for keeping score
playerOneScore = 0
playerTwoScore = 0
while True:
# asking players for their choice
playerOneOption = input(f"{namePlayerOne} select your option (scissors, Spock, lizard, rock, paper): ").lower()
playerTwoOption = input(f"{namePlayerTwo} select your option (scissors, Spock, lizard, rock, paper): ").lower()
if playerOneOption == playerTwoOption: # if both players select the same option, it's always a draw
results = "Draw"
elif (playerOneOption,playerTwoOption) in winningPairs: # check if the order of the input is the same as an element in the winningPairs list, if it is Player one wins (who selects first)
results = f"{namePlayerOne} wins" # print their win
playerOneScore = 1 # add 1 score to their name
else: # if the elif is not true, it means player two wins
results = f"{namePlayerTwo} wins" # print their win
playerTwoScore = 1 # add 1 score to their name
print("-"*20)
print(f"{namePlayerOne} chose {playerOneOption}\n{namePlayerTwo} chose {playerTwoOption}") # print each player's pick
print(results) # print results
print()
print(f"{namePlayerOne} score: {playerOneScore}\n{namePlayerTwo} score: {playerTwoScore}") # print player scores
print("-"*20)
playAgain = input("Play again? (y/n): ") # ask if players want to play again
if playAgain.lower() != "y":
break
Below is the output of what happens. The player selects their names and subsequently picks their options.
Player 1, enter your name: name1
Player 2, enter your name: name2
name1 select your option (scissors, Spock, lizard, rock, paper): rock
name2 select your option (scissors, Spock, lizard, rock, paper): scissors
--------------------
name1 chose rock
name2 chose scissors
name2 wins
name1 score: 0
name2 score: 1
--------------------
Play again? (y/n): n
In this example, player 1 selects rock
, and player 2 selects scissors
, which means that player 1 should win.
CodePudding user response:
Your winning pairs must be defined as a list of tuples, which contain 2 strings:
winningPairs = [("scissors","paper"),
("scissors","lizard"),
("Spock","scissors"),
("Spock","rock"),
("lizard","Spock"),
("lizard","paper"),
("rock","lizard"),
("rock","scissors"),
("paper","rock"),
("paper","Spock")]
To clarify, this is because you are checking whether a tuple of two strings, player1 and player2's choices respectively, is in the list. The list now contained just strings, since a tuple of 1 element is defined as (item,)
. But, replace your winningPairs
list with this one and it will be all good.
CodePudding user response:
Let's define the "winningPairs" as tuples (a pair of strings in beating order) and extract your crucial algorithm, the evaluation of win, into a function:
# pair (A,B) means: A beats B
def beating_tuples = [
("paper", "rock"),
("rock", "scissor"),
# etc.
]
# returns a result statement
def evaluate_winner(player1_choice, player2_choice):
if player1_choice == player2_choice:
return "Draw"
if (player1_choice, player2_choice) in beating_tuples:
player1_score = 1
return f"{player1_name} wins"
if (player2_choice, player1_choice) in beating_tuples:
player2_score = 1
return f"{player2_name} wins"
return f"Error: Choices of both unequal or not in beating-pairs (player2, player1): {(player2_choice, player1_choice)}"
Note: Instead of a defaulting else
a final catching return indicates failure.
Further improvements could be a Player
class, where each player object has common attributes as name
, choice
, score
.
See also: