# CS 21: Algorithmic Problem Solving

## HW #5: Yahtzee

Part 1 -- due 11:59pm Tuesday, February 27
Part 2 -- due 11:59pm Tuesday, March 6

Remember to run update21 to get the files needed for this assignment. The program handin21 will only submit files in the cs21/homework/5 directory.

Your programs are graded on both correctness and style. Please review the comments regarding programming style on the main page

Some of the problems will have optional components that allow you to further practice your skills in Python. Optional portions will not be graded, but may be interesting for those wanting some extra challenges.

The game of Yahtzee

In this two part assignment, you will write a Python version of the popular dice game Yahtzee. For those of you who may not be familiar with Yahtzee (or who need a refresher) here are the rules of the game.

The rules outlined below were borrowed heavily from the Wikipedia entry on Yahtzee, and many years of personal experience. If you would like to try out the game for yourself, there is an online working demo as a Java applet. The game is played with five six-sided dice. Each game consists of thirteen rounds. In this assignment, you will simulate one of these rounds. The rules for playing a round are as follows:

1. The player rolls all five dice.
2. The player selects and re-rolls zero or more dice.
3. The player selects and re-rolls zero or more dice again. Dice that were not re-rolled on the second roll may be re-rolled on the third roll.
4. The player scores the dice.

To score a set of five dice, the player picks one of thirteen categories in which to score. A category chosen in one round cannot be used again in a successive round. Because your are only implementing one round this week, you do not need to worry about this yet. The thirteen categories are: ones, twos, threes, fours, fives, sixes, three-of-a-kind, four-of-a-kind, full house, small straight, large straight, Yahtzee, and chance. Each category assigns a score to a set of dice as outlined below. In each category, the order of the dice do not matter, thus a roll of 1, 2, 3, 1, 2" is the same as "1, 1, 2, 2, 3". If you have questions about the scoring, try playing the game online, ask a friend, or ask us. We'll be happy to explain.

• ones: The player scores the total sum of all dice that display one. If none of the dice are one, the player scores zero points. The maximum score in this category is achieved when the player has 5 ones: 1+1+1+1+1 = 5*1 = 5.
• twos: The player scores the total sum of all dice that display two. The maximum score in this category is 5*2 = 10.
• threes, fours, fives, sixes: Scoring is similar to ones and twos.
• three-of-a-kind: If the dice have one die value that occurs three or more times, the player scores the sum of all five dice. Otherwise, the player scores 0.
• four-of-a-kind: If the dice have one die value that occurs four or more times, the player scores the sum of all five dice. Otherwise, the player scores 0.
• full house: If three dice display the same value and the other pair of remaining dice have the same value as each other, the player scores 25 points. Otherwise the score is zero. Note that if all five dice display the same value, this is also a full house.
• small straight: If the player has four dice that display four consecutive values, the player scores 30 points. Otherwise, the player scores 0. Note there are only three possible small straights "1 2 3 4", "2 3 4 5", and "3 4 5 6". The value on the fifth die is irrelevant, as is the order of the individual dice (i.e. "3 5 4 6" is also a small straight).
• large straight: If the player has five dice that display five consecutive values, the player scores 40 points. Otherwise, the player scores 0. Note there are only two possible small straights "1 2 3 4 5", or "2 3 4 5 6". Again, the order of the dice do not matter, so "5 3 2 1 4" is also a large straight.
• Yahtzee: If all five dice display the same value, the player scores 50 points. Otherwise, the player scores 0.
• Chance: The player scores the sum of all five dice

These rules are sufficient for the first part of the assignment. Next week we will add a few additional rules regarding bonuses, but this does not effect the scoring of a single category

Part One

In Part One of the assignment, you will writing many of the foundational components of the game. Below is a list of the functions that your program must have, along with a brief description of what each function should do. (As per Python's help, the functions below are listed in alphabetical order.)

```    fourOfAKind(dielist)
Returns the sum of the dice if these dice represent 4 of a kind;
otherwise, returns 0.

For example:
fourOfAKind([5, 3, 5, 5, 5]) => 23
fourOfAKind([3, 3, 3, 5, 3]) => 17
fourOfAKind([3, 3, 3, 3, 3]) => 15
fourOfAKind([1, 3, 1, 3, 3]) => 0

fullHouse(dielist)
Returns 25 if these dice represent a full house; returns 0 otherwise.

A full house occurs when three of the dice are all of one value
and the remaining two have the same value.  For example:
fullHouse([4, 4, 4, 5, 5]) => 25
fullHouse([5, 4, 5, 4, 5]) => 25
fullHouse([5, 5, 5, 4, 5]) => 0
fullHouse([3, 3, 1, 3, 1]) => 25

Note that 5 of a kind is considered to be a full house.  For
example:
fullHouse([5, 5, 5, 5, 5]) => 25

hasAtLeastN(dielist, n)
Returns True if the list of dice contain at least n of some value.

In other words, this returns True if the list of dice could be
described as having 'n' of a kind.  For example:
hasAtLeastN([5, 3, 5, 5, 5], 4) => True
hasAtLeastN([5, 3, 5, 5, 5], 3) => True
hasAtLeastN([5, 3, 5, 5, 5], 5) => False
hasAtLeastN([1, 2, 3, 2, 1], 2) => True

hasExactlyN(dielist, n)
Returns True if these dice contain exactly 'n' of a particular
value.  For example:
hasExactlyN([2, 5, 2, 4, 2], 3) => True (there are exactly three 2's)
hasExactlyN([2, 5, 2, 4, 2], 2) => False
hasExactlyN([2, 5, 2, 4, 2], 1) => True (exactly one 4 and one 5)
hasExactlyN([2, 5, 2, 4, 2], 0) => True (exactly zero 1's, 3's and 6's)

largeStraight(dielist)
Returns 40 if these dice have a large straight; else returns 0.

A large straight is a list of dice which contain any 5 dice with
consecutive values.  For example:
largeStraight([1, 2, 3, 4, 5]) => 40
largeStraight([6, 4, 5, 2, 3]) => 40
largeStraight([2, 3, 4, 1, 2]) => 0
largeStraight([6, 4, 5, 2, 1]) => 0

reroll(dielist)
Queries the user as to which dice should be re-rolled and does the
re-rolling.

The user is presented a prompt where they can choose the dice that
they wish to re-roll.  Each selected die is then re-rolled and the
list is changed in-place, so no list is returned from this
function.

roll()
Rolls 5 standard 6-sided dice and returns a list of the 5 values.

showdice(dielist)
Displays the current values of the 5 dice.

showscores(dielist)
Displays the possible score that the 5 dice would receive in each
of the 13 scoring slots.

smallStraight(dielist)
Returns 30 if these dice have a small straight; otherwise returns 0.

A small straight is a list of dice which contain any 4 dice with
consecutive values.  For example:
smallStraight([1, 2, 3, 4, 5]) => 30
smallStraight([2, 3, 4, 1, 2]) => 30
smallStraight([6, 4, 5, 3, 1]) => 30
smallStraight([6, 4, 5, 2, 1]) => 0

sumDice(dielist)
Returns the sum of the dice.

For example:
sumDice([1, 2, 3, 4, 5]) => 15
sumDice([2, 2, 5, 2, 3]) => 14

sumOfN(dielist, num)
Returns the sum of only those dice whose value is num.

For example:
sumOfN([5, 4, 5, 2, 5], 2) => 2
sumOfN([5, 4, 5, 2, 5], 3) => 0
sumOfN([5, 4, 5, 2, 5], 4) => 4
sumOfN([5, 4, 5, 2, 5], 5) => 15

threeOfAKind(dielist)
Returns the sum of the dice if these dice represent 3 of a kind;
otherwise, returns 0.

For example:
threeOfAKind([5, 3, 5, 3, 5]) => 21
threeOfAKind([3, 3, 3, 5, 3]) => 17
threeOfAKind([3, 3, 3, 3, 3]) => 15
threeOfAKind([1, 3, 1, 2, 3]) => 0

yahtzee(dielist)
Returns 50 if these dice represent a Yahtzee (5 of a kind);
otherwise returns 0.

For example:
yahtzee([5, 5, 5, 5, 5]) => 50
yahtzee([2, 2, 2, 2, 2]) => 50
yahtzee([2, 1, 2, 2, 2]) => 0

```

We have provided for you the main function. When you run the program (and have completed each of the above functions), you should have output similar to the following:

```Position:   A  B  C  D  E
Value:   1  6  2  3  3
Enter dice to re-roll: ABC

Position:   A  B  C  D  E
Value:   1  2  2  3  3
Enter dice to re-roll: A

Position:   A  B  C  D  E
Value:   2  2  2  3  3

Slot   Points
Ones        0
Twos        6
Threes        6
Fours        0
Fives        0
Sixes        0
3/Kind       12
4/Kind        0
Full Hse       25
Sm Strt        0
Lg Strt        0
Chance       12
Yahtzee        0
```

If the player wishes to re-roll none of the dice, they can just press enter at the prompt to re-roll. In the below example, the player rolled a Large Straight on the opening roll and didn't want to change anything:

```Position:   A  B  C  D  E
Value:   5  4  6  2  3
Enter dice to re-roll:

Position:   A  B  C  D  E
Value:   5  4  6  2  3
Enter dice to re-roll:

Position:   A  B  C  D  E
Value:   5  4  6  2  3

Slot   Points
Ones        0
Twos        2
Threes        3
Fours        4
Fives        5
Sixes        6
3/Kind        0
4/Kind        0
Full Hse        0
Sm Strt       30
Lg Strt       40
Chance       20
Yahtzee        0
```

To help you manage this large project, you should write functions one at a time and test each of them before moving on to the next function. You should begin by writing (and testing) the roll and reroll functions. Then, you can write the showdice and showscores functions. Once those four functions are in place, the main function we provided for you will work.

Now you can move on to writing each of the scoring functions. The easiest scoring function to write is Chance. Write this function and make sure it is working before proceeding. You should try to write the scoring functions in this order (approximately reflecting easiest to hardest):

1. Chance
2. Yahtzee
3. Three of a Kind, Four of a Kind
4. One, Two, Three, Four, Five, Six.
5. Full House
6. Small Straight, Large Straight
Remember to be sure to test each function before proceeding on to the next one.
Part Two
See Homework 6.