Files
lab_dice/yahtzee.py
caglazir f97db27370 Edited the docstrings on the Yathzee.
Checkpoint 2: I think writing the docstrings GREATLY helped me understand the code.
I would love to get in the habit of utilizing this for any new code that I might
encounter, if time permitting. It helped me analyze the step=by=step process of
the running code. It was different in a sense that I thought it was more intentional
than writing the code. When I write code I start with a very rough draft of it
then fixing it as I go. I think if I start thinking of code in the way I wrote these
docstrings, my understanding and skills of coding would improve.
2025-11-16 21:22:33 -05:00

160 lines
5.8 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):
"""Determines the starting conditions.
Sets the score to 0 to begin with, defines the goals and prepares 5 dices for the 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 a round 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):
"""Sets the screen and rolls 5 dice.
After setting up the screen with 80 = signs, 5 dice are rolled and the results are shown
to the player. The player then is left to choose a goal from the list provided and their
score is updated.
"""
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):
"""Print the status line
Provides the player important info such as score, remaining number of rolls and
their dice upon rolling.
"""
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):
"""Allows the user to choose the goal option.
Appends the unused goal options. Depending on the player input, re-rolls the dice.
"""
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):
"""Provides the player set of options.
Enumerates the options as an integer list and present it to the player.
"""
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):
"""Determines the validity of player choice.
Based on the integer list of choices, determines the validity of input such as
non-positive, non-integer and longer than allowed inputs.
"""
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):
"""Counts the number of unused goals.
"""
return len(self.get_unused_goals())
def get_unused_goals(self):
"""Determines the unused goals.
If a goal isn't used, appends that goal to the list of remaining goals to be used.
"""
unused_goals = []
for goal in self.goals:
if not goal.used:
unused_goals.append(goal)
return unused_goals
def reroll(self):
"""Rerolls the dice
Decreases the number of rerolls left by one and for the selected dice,
performs the reroll action.
"""
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):
"""Allows the user to choose which dice to reroll.
Creates an empty array for the player input of dice to reroll. Removes the chosen
dice from the faces and sends the chosen list of dice for the reroll action.
"""
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):
"""Prompts the user to choose their dice to reroll.
Asks the player which dice they want to reroll. If their input isn't valid,
asks the player to enter numbers of the dice to reroll. The digit input is stored in
the choice integers list.
"""
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):
"""Removes the reroll dice choice from the faces.
Checks if the choices string element is a digit or not. If the digit is a dice face,
removes the face as it is to be rerolled.
"""
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