Files
lab_dice/yahtzee.py

151 lines
5.2 KiB
Python

from die import Die
class Yahtzee:
"""A command-line Yahtzee game.
This version of Yahtzee is initialized with a list of goals.
"""
def __init__(self, goals):
"""Initialize a new game. Sets the starting score to zero,
strores the list of goals and creates five dice for game.
"""
self.score = 0
self.goals = goals
self.dice = [Die() for num in range(5)]
def play(self):
"""Play an entire game. Starts by greeting the user, then plays rounds
until all the goals have been used. When the game is over, tells the player
their final score.
"""
print("Welcome to Yachtzee!")
self.score = 0
for goal in self.goals:
goal.used = False
while self.count_unused_goals() > 0:
self.play_round()
print(f"Your final score was {self.score}")
def play_round(self):
"""Play one round. Rolls all dice, displays game status,
allows player to re roll or choose a goal and updates score.
"""
print("=" * 80)
self.rolls_left = 3
for die in self.dice:
die.roll()
self.show_status()
goal = self.choose_goal()
goal.used = True
self.score += goal.score(self.dice)
def show_status(self):
"""Displays current game status. Shows player's score,
remaining rolls, and current values of all five dice.
"""
dice = ', '.join([str(die) for die in self.dice])
print(f"Score: {self.score}. Rolls left: {self.rolls_left}. Dice: {dice}.")
def choose_goal(self):
"""Allow player to choose a goal or re roll dice. Displays
available goals and re roll options, then processes player's choice.
"""
options = []
unused_goals = self.get_unused_goals()
for goal in unused_goals:
option = goal.prompt(self.dice)
options.append(option)
if self.rolls_left > 0:
options.append("Re-roll")
choice = self.get_choice(options)
if options[choice] == "Re-roll":
self.reroll()
self.show_status()
return self.choose_goal()
else:
return unused_goals[choice]
def get_choice(self, options):
"""Get choice from player. Displays numbered options and repeatedly
asks for input until the player enters a valid choice.
"""
print("What would you like to do?")
for i, option in enumerate(options):
print(f"{i}. {option}")
choice = input("> ")
while not self.option_choice_is_valid(choice, options):
print("Sorry, that's not a valid choice.")
choice = input("> ")
return int(choice)
def option_choice_is_valid(self, choice, options):
"""Check if choice is valid. Ensures choice is a number within range.
"""
if not choice.isdigit():
return False
if int(choice) < 0:
return False
if int(choice) >= len(options):
return False
return True
def count_unused_goals(self):
"""Count how many goals remain unused. Returns number of goals
not yet been scored.
"""
return len(self.get_unused_goals())
def get_unused_goals(self):
"""Get all unused goals. Returns a list of goals that have not
been selected yet.
"""
unused_goals = []
for goal in self.goals:
if not goal.used:
unused_goals.append(goal)
return unused_goals
def reroll(self):
"""Re - roll selected dice. Decreases the number of rolls left
and rolls only the dice chosen by the player.
"""
self.rolls_left -= 1
choices = self.get_reroll_choices()
dice_to_reroll = self.get_dice_to_reroll(choices)
for die in dice_to_reroll:
die.roll()
def get_dice_to_reroll(self, choice_ints):
"""Determine which dice to re roll. Matches player's selected values
to dice and returns the corresponding dice.
"""
dice_to_reroll = []
for die in self.dice:
if die.face in choice_ints:
choice_ints.remove(die.face)
dice_to_reroll.append(die)
return dice_to_reroll
def get_reroll_choices(self):
"""Gets dice values the player wants to re - roll. Player enter
dice values and returns them as a integers.
"""
print("Which dice do you want to re-roll?")
choices = input("> ")
while not self.reroll_choices_are_valid(choices):
print("Please enter the numbers on dice you want to re-roll.")
choices = input("> ")
choice_ints = [int(digit) for digit in choices]
return choice_ints
def reroll_choices_are_valid(self, choices_str):
"""Check re roll input is valid. Makes sure entered values
are nummbers that match dice.
"""
if not choices_str.isdigit():
return False
choice_ints = [int(digit) for digit in choices_str]
for die in self.dice:
if die.face in choice_ints:
choice_ints.remove(die.face)
return len(choice_ints) == 0