'How to reduce the amount of lines needed for this logic?
I have a simple Python game where two players deal some damage to each other in turns until one player has 0 or less than 0 HP. I don't like how much I've repeated myself but I'm unsure how to fix this. I thought about using a list of players but then I'm unsure how to index the next player when it's their turn, without running into the list index out of range error.
If this kind of question is not allowed please let me know and I will remove it.
Below is my game logic to determine when a player has won. I may not have pasted in the exact code I have but it runs how it's expected locally.
def check_win_state(current_player):
if current_player.get_player_health() > 0:
return True
elif current_player.get_player_health() <= 0:
return False
def main():
player1 = player.Player("Me")
player2 = player.Player("You")
while True:
if check_win_state(player1):
take_turn(player1, player2)
else:
print(f"\n{player2.get_player_name()} ({player2.get_player_health()} HP) wins! {player1.get_player_name()} has {player1.get_player_health()} HP left.\n")
break
if check_win_state(player2):
take_turn(player2, player1)
else:
print(f"\n{player1.get_player_name()} ({player1.get_player_health()} HP) wins! {player2.get_player_name()} has {player2.get_player_health()} HP left.\n")
break
Solution 1:[1]
The easiest approach to reduce code duplication in situations like these is to use a secondary variable to hold the primary variable. Here, instead of having different code for player1 and player2, we instead have just one code, and use the variables current_player and opposing_player to hold player1 and player2, and swap with every iteration.
def main():
player1 = player.Player("Me")
player2 = player.Player("You")
current_player = player1
opposing_player = player2
while True:
if check_win_state(current_player):
take_turn(current_player, opposing_player)
else:
print(f"\n{opposing_player.get_player_name()} ({opposing_player.get_player_health()} HP) wins! {current_player.get_player_name()} has {current_player.get_player_health()} HP left.\n")
break
current_player, opposing_player = opposing_player, current_player
If you have more than two players, then a more extensible approach might be to have a list of players, and have an index rotate through the list with each iteration to specify which player is the 'current' one.
also, you can simplify check_win_state():
def check_win_state(current_player):
return current_player.get_player_health() > 0
because the check a > b returns a boolean anyway.
Solution 2:[2]
You can make the first function short using this logic:-
def check_win_state(current_player):
return current_player.get_player_health() > 0:
And now you can create another function to do the work of inside while loop
def work_in_while(pl, another_pl):
if check_win_state(pl):
take_turn(pl, another_pl)
else:
print(f"\n{another_pl.get_player_name()} ({another_pl.get_player_health()} HP) wins! {pl.get_player_name()} has {pl.get_player_health()} HP left.\n")
return "kill"
And use it like:-
while True:
if work_in_while(player1, player2) == "kill":
break
if work_in_while(player2, player1) == "kill":
break
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Green Cloak Guy |
| Solution 2 | I-am-developer-9 |
