Skip to main content

Section Homework 3

Before you begin ...

Permitted MATLAB Functions & Commands for Homework 3.

The following built-in MATLAB functions and commands are permitted for this assignment.
Vector/Matrix
Operations:
round β€’ mod β€’ floor β€’ ceil β€’ sum β€’ max β€’ min
Size/Dimensions:
length β€’ numel β€’ size β€’ height β€’ width
Creation:
zeros β€’ ones β€’ true β€’ false
Logical:
all β€’ any
Flow Control
Conditional:
if β€’ switch-case β€’ try-catch
Loops:
for β€’ while β€’ continue β€’ break β€’ return
Strings and Character Arrays
Operations:
join β€’ replace
Conversion:
num2str β€’ str2num β€’ str2double β€’ string β€’ char
Other
Printing Text:
fprintf β€’ disp β€’ display β€’ input β€’ assert
Random Generators:
rand β€’ randi β€’ rng
Special Variables:
nargin
Type Detection:
isnan β€’ isfield β€’ isempty
Points will be deducted from any programs using functions outside this list.

Summary.

The aim of this assignment is to set up a foundation for programming a Dice Poker Game. The programs below will eventually be the helper functions that perform specific tasks in the full-fledged game. Each one can be written and tested independent from the rest. They are not ordered by difficulty, so if you are struggling with one try a different one.
In homework 1, you wrote a program called list_occurrences. I think you will find this function useful and I recommend adding it to your current directory so that you can call it inside this assignment’s programs. If any of your programs use it, include it with your submission to this assignment.

Subsection roll_dice

Generates a random roll of \(n\) six-sided dice and plays a dice-throw sound if the media file is available.
Inputs:
n (1x1) positive integer β€” number of dice to roll.
Outputs:
roll (1 x n) integer vector β€” contains random integers from 1 - 6.
Details:
β–Έ Download the sound file, throw_dice.mat, and place it in your current working directory.
β–Έ Within a try/catch block, attempt to:
(1) Load the sound file with the command
sound_data = load('throw_dice.mat','y','fs')
(2) Play it with the command
sound(sound_data.y, sound_data.fs)
If the file is missing or audio fails, β€œsilently” continue.
 1 
By β€œsilently”, I mean don’t print a warning in the catch block.
β–Έ Use the randi command to produce the roll.
Examples: (Note: you should hear a dice rolling sound in each example.)
r = roll_dice(5)   % Outputs are random and will vary
% returns:  r  =  2  6  1  1  5
r = roll_dice(3)   % Outputs are random and will vary
% returns:  r =  6  6  3

Subsection get_face_counts

Counts how many times each die face (1-6) appears in a 5-die roll.
Inputs:
roll (1 x 5) integer vector β€” roll die face values.
Outputs:
counts (1 x 6) integer vector β€” counts for each die face in roll.
Details:
β–Έ None.
Examples:
counts = get_face_counts([2 6 6 1 5])
% returns counts =  1  1  0  0  1  2
counts = get_face_counts([3 3 3 5 5])
% returns counts =  0  0  3  0  2  0

Subsection sort_by_rank

Reorders a dice roll into rank-preferred order based on face counts and values. Higher counts come first, and within the same count, higher face values come first.
Inputs:
raw_roll (1 x 5) integer vector β€” dice values sorted into rank order.
counts (1 x 6) integer vector β€” counts of each die face in roll.
Outputs:
sorted_roll (1 x 5) integer vector β€” the dice values reordered so that higher multiplicities and values appear earlier.
Details:
β–Έ Both roll and counts are provided as inputs. You may use one or both to code this. If one is not used, replace the input variable with ~.
β–Έ Remember, you can make for loop counters decrease rather than increase using a step of -1. For example, k = 3:-1:1 = [3 2 1].
Examples:
raw_roll = [2 5 5 2 5];  % full-house
rc = [0 2 0 0 3 0];
sorted_roll = sort_by_rank(raw_roll, rc)
% returns sorted_roll =  5  5  5  2  2
raw_roll = [3 4 6 1 6];  % one-pair
rc = [1 0 1 1 0 2];
sorted_roll = sort_by_rank(raw_roll, rc)
% returns sorted_roll =  6  6  4  3  1
raw_roll = [4 5 1 3 2];  % straight
rc = [1 1 1 1 1 0];
sorted_roll = sort_by_rank(raw_roll, rc)
% returns sorted_roll =  5  4  3  2  1

Subsection is_5kind

Checks whether a given roll contains a five-of-a-kind. A five-of-a-kind consists of all dice with the same face value. For example,
\begin{equation*} \LARGE ⚁\ ⚁\ ⚁\ ⚁\ ⚁ \end{equation*}
Inputs:
roll (1 x 5) integer vector β€” dice values sorted into rank order.
counts (1 x 6) integer vector β€” counts of each die face in roll.
Outputs:
tf (1x1) logical β€” true if roll is a five-of-a-kind; false otherwise.
Details:
β–Έ You may assume that the input roll will be sorted by rank.
β–Έ Both roll and counts are provided as inputs. You may use one or both to code this. If one is not used, replace the input variable with ~.
β–Έ Your list_occurrences program may be useful.
Examples:
tf = is_5kind([4 4 2 2 5], [0 2 0 2 1 0])
% returns tf  =  (logical)  0
tf = is_5kind([3 3 3 3 3], [0 0 5 0 0 0])
% returns tf  =  (logical)  1

Subsection is_4kind

Checks whether a given roll contains a four-of-a-kind. A four-of-a-kind consists of 4 dice with the same face value and one single of a different value. For example,
\begin{equation*} \LARGE ⚁\ ⚁\ ⚁\ βš‚\ ⚁ \end{equation*}
Inputs:
roll (1 x 5) integer vector β€” dice values sorted into rank order.
counts (1 x 6) integer vector β€” counts of each die face in roll.
Outputs:
tf (1x1) logical β€” true if roll is a four-of-a-kind; false otherwise.
Details:
β–Έ You may assume that the input roll will be sorted by rank.
β–Έ Both roll and counts are provided as inputs. You may use one or both to code this. If one is not used, replace the input variable with ~.
β–Έ Your list_occurrences program may be useful.
Examples:
tf = is_4kind([4 4 2 2 5], [0 2 0 2 1 0])
% returns tf  =  (logical)  0
tf = is_4kind([3 3 3 3 1], [1 0 4 0 0 0])
% returns tf  =  (logical)  1

Subsection is_3kind

Checks whether a given roll contains a three-of-a-kind. A three-of-a-kind consists of all dice with the same face value and the other two are unique singles. For example,
\begin{equation*} \LARGE ⚁\ ⚁\ ⚁\ βš‚\ βš€ \end{equation*}
Inputs:
roll (1 x 5) integer vector β€” dice values sorted into rank order.
counts (1 x 6) integer vector β€” counts of each die face in roll.
Outputs:
tf (1x1) logical β€” true if roll is a three-of-a-kind; false otherwise.
Details:
β–Έ You may assume that the input roll will be sorted by rank.
β–Έ Both roll and counts are provided as inputs. You may use one or both to code this. If one is not used, replace the input variable with ~.
β–Έ Your list_occurrences program may be useful.
Examples:
tf = is_3kind([4 4 2 2 5], [0 2 0 2 1 0])
% returns tf  =  (logical)  0
tf = is_3kind([3 3 3 5 4], [0 0 3 1 1 0])
% returns tf  =  (logical)  1

Subsection is_1pair

Checks whether a given roll contains a single pair. A pair consists of two of the same dice faces and the rest unique singles. For example,
\begin{equation*} \LARGE βš„\ βš‚\ βšƒ\ ⚁\ βš„ \end{equation*}
Inputs:
roll (1 x 5) integer vector β€” dice values sorted into rank order.
counts (1 x 6) integer vector β€” counts of each die face in roll.
Outputs:
tf (1x1) logical β€” true if roll contains a pair; false otherwise.
Details:
β–Έ You may assume that the input roll will be sorted by rank.
β–Έ Both roll and counts are provided as inputs. You may use one or both to code this. If one is not used, replace the input variable with ~.
β–Έ Your list_occurrences program may be useful.
Examples:
tf = is_1pair([4 4 6 5 2], [0 1 0 2 1 1])
% returns tf  =  (logical)  1
tf = is_1pair([3 3 1 1 4], [2 0 2 1 0 0])
% returns tf  =  (logical)  0

Subsection is_2pair

Checks whether a given roll contains two distinct pairs of dice. A two-pair consists of two dice of one face value, two dice of another, and a fifth die of a different value. For example,
\begin{equation*} \LARGE βš‚\ βš‚\ ⚁\ ⚁\ βš„ \end{equation*}
Inputs:
roll (1 x 5) integer vector β€” dice values sorted into rank order.
counts (1 x 6) integer vector β€” counts of each die face in roll.
Outputs:
tf (1x1) logical β€” true if roll contains two-pairs; false otherwise.
Details:
β–Έ You may assume that the input roll will be sorted by rank.
β–Έ Both roll and counts are provided as inputs. You may use one or both to code this. If one is not used, replace the input variable with ~.
β–Έ You may use the MATLAB command isequal(v1,v2) to compare the equality of vectors, v1 & v2.
Examples:
tf = is_2pair([4 4 2 2 5], [0 2 0 2 1 0])
% returns tf  =  (logical)  1
tf = is_2pair([3 3 3 5 5], [0 0 3 0 2 0])
% returns tf  =  (logical)  0
tf = is_2pair([6 6 6 6 2], [0 1 0 0 0 4])
% returns tf  =  (logical)  0

Subsection is_straight

Checks whether a given dice roll corresponds to a straight. A straight is a roll with values:
\begin{equation*} {\LARGE βš€\ ⚁\ βš‚\ βšƒ\ βš„\ }\qquad{\LARGE ⚁\ βš‚\ βšƒ\ βš„\ βš…\ } \end{equation*}
Inputs:
roll (1 x 5) integer vector β€” dice values sorted into rank order.
counts (1 x 6) integer vector β€” counts of each die face in roll.
Outputs:
tf (1x1) logical β€” true if roll is a straight; false otherwise.
Details:
β–Έ You may assume that the input roll will be sorted by rank.
β–Έ Both roll and counts are provided as inputs. You may use one or both to code this. If one is not used, replace the input variable with ~.
β–Έ You may use the MATLAB command isequal(v1,v2) to compare the equality of vectors, v1 & v2.
Examples:
tf = is_straight([5 4 3 2 1], [1 1 1 1 1 0])
% returns tf  =  (logical)  1
tf = is_straight([6 5 4 3 2], [0 1 1 1 1 1])
% returns tf  =  (logical)  1
tf = is_straight([1 3 4 5 6], [1 0 1 1 1 1])
% returns tf  =  (logical)  0

Subsection is_fullhouse

Checks whether a given roll forms a full house. A full house consists of three dice of one face value and two dice of another. For example,
\begin{equation*} \LARGE βš‚\ βš‚\ βš‚\ βšƒ\ βšƒ \end{equation*}
Inputs:
roll (1 x 5) integer vector β€” dice values sorted into rank order.
counts (1 x 6) integer vector β€” counts of each die face in roll.
Outputs:
tf (1x1) logical β€” true if roll is a full-house; false otherwise.
Details:
β–Έ You may assume that the input roll will be sorted by rank.
β–Έ Both roll and counts are provided as inputs. You may use one or both to code this. If one is not used, replace the input variable with ~.
β–Έ You may use the MATLAB command isequal(v1,v2) to compare the equality of vectors, v1 & v2.
Examples:
tf = is_fullhouse([5 5 5 1 1], [2 0 0 0 3 0])
% returns tf  =  (logical)  1
tf = is_fullhouse([1 1 1 1 6], [4 0 0 0 0 1])
% returns tf  =  (logical)  0

Subsection is_between

Checks if all elements of a list lie between two bounds \(a\) and \(b\text{,}\) inclusive.
Inputs:
list (1 x N) double vector β€” values to check.
a (1x1) double β€” lower bound.
b (1x1) double β€” upper bound.
Outputs:
tf (1x1) logical β€” true if every value of list is between \(a\) & \(b\) OR is empty; false otherwise.
Details:
β–Έ You may use logical vectors to code this.
Examples:
tf = is_between([2 3 4], 1, 5)
% returns tf  =  (logical)  1
tf = is_between([0 2 4], 1, 5)
% returns tf  =  (logical)  0
tf = is_between([], 1, 5)
% returns tf  =  (logical)  1

Subsection get_winner

Decides the winner of a Dice Poker round by comparing player and dealer rolls. First compare rank IDs; if tied, compare the individual numeric die faces (i.e., roll) to determine a winner.
Inputs:
d_rank (1x1) integer β€” dealer’s rank ID (1-8).
d_roll (1 x 5) integer vector β€” dealer’s roll sorted by rank order.
p_rank (1x1) integer β€” player’s rank ID (1-8).
p_roll (1 x 5) integer vector β€” player’s roll sorted by rank order.
Outputs:
winner (1x1) integer β€” \(1\) for player, \(2\) for dealer, \(0\) for exact tie.
Details:
β–Έ A lower rank ID wins.
β–Έ To break a rank tie, compare the values on d_roll and p_roll.
β–Έ If all five dice are equal, return \(0\) (tie).
Examples:
% Example 1: rank decides
p_roll = [3 3 3 4 1];	% three-of-a-kind
p_rank = 5;
d_roll = [2 2 1 1 5];	% two-pair
d_rank = 6;
w = get_winner(d_rank, d_roll, p_rank, p_roll)
% returns  w  =  1  (player wins)
% Example 2: tie-break by dice values
p_roll = [5 5 4 2 1];	% one-pair, highest single: 4
p_rank = 7;
d_roll = [5 5 6 2 1];	% one-pair, highest single: 6
d_rank = 7;
w = get_winner(d_rank, d_roll, p_rank, p_roll)
% returns  w  =  2  (dealer wins)
% Example 3: exact tie
p_roll = [4 4 4 6 6];	% full-house, 4's over 6's
p_rank = 3;
d_roll = [4 4 4 6 6];	% full-house, 4's over 6's
d_rank = 3;
w = get_winner(d_rank, d_roll, p_rank, p_roll)
% returns  w  =  0  (tie)

Subsection get_player_reroll

Prompts the player to select which dice (positions 1-5) to reroll and validates the player’s answer. An empty or invalid response results in keeping all dice.
Inputs:
None (reads from user input).
Outputs:
sel (1 x M) integer vector β€” indices (1-5) of dice to reroll. If the player keeps all dice or the input is invalid, returns [].
Details:
β–Έ Get the user’s selection using the command:
sel = input('Select dice to reroll (1-5). ENTER to keep all: ','s')
β–Έ The 's' argument means that sel will be saved as a string from the player’s input.
β–Έ As long as the player entered numbers separated by spaces or commas, you can convert the input to a numerical vector using str2num.
β–Έ If non-number text was entered then str2num will return empty. If this happens, the player will keep all dice by default and the function should return empty.
β–Έ Next, validate the selection by calling your is_between helper function. If validation fails, print a brief message and set sel to empty (keep all). Otherwise, do nothing since sel is already set.
Helpers:
is_between
Examples:
% Example 1: player keeps all
sel = get_player_reroll()
% (Player presses ENTER)
% returns: sel  =  []
% Example 2: player rerolls dice in position 2 and 5
sel = get_player_reroll()
% (Player types: 2 5)
% returns: sel  =   2  5
% Example 3: invalid entry (e.g., "0 6" or "hello")
sel = get_player_reroll()
% prints: "Invalid selection. Keeping all."
% returns: sel  =  []

Subsection get_dealer_reroll

Chooses which dice the dealer will reroll based on the current roll. Use the following strategy for the dealer:
  • straight, full-house, five-of-a-kind ➜ keep all,
  • singles ➜ reroll 1,
  • otherwise ➜ reroll all β€œsingles” (dice appearing once in the roll).
Inputs:
rank (1x1) integer β€” dealer’s rank ID (1-8) from the initial roll.
roll (1 x 5) integer vector β€” dealer’s initial roll sorted by rank order.
counts (1 x 6) integer vector β€” counts of each die face in roll.
Outputs:
sel (1 x M) integer vector β€” positions (indices 1-5) of dice to reroll; [] if keeping all.
Details:
β–Έ Use the rank to determine if the dealer has a good roll and should keep all dice.
β–Έ Otherwise, return the locations of all the singles.
Examples:
% Example 1: straight => keep all
rank = 4;
roll = [6 5 4 3 2];
counts = [0 1 1 1 1 1];
sel = get_dealer_reroll(rank, roll, counts)
% returns sel  =  []
% Example 2: three-of-a-kind  => reroll singles in positions 4 & 5
rank = 5;
roll = [5 5 5 4 1];
counts = [1 0 0 1 3 0];
sel = get_dealer_reroll(rank, roll, counts)
% returns sel  =  4  5
% Example 3: singles  =>  reroll 1 in position 5
rank = 8;
roll = [6 4 3 2 1];
counts = [1 1 1 1 0 1];
sel = get_dealer_reroll(rank, roll, counts)
% returns sel  =  5