Created
May 4, 2014 18:58
-
-
Save KrisKusano/cf6fd47b254680f59ab0 to your computer and use it in GitHub Desktop.
Play a game of "Chutes and Ladders" in MATLAB
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function p = chutes_and_ladders() | |
%% Chutes and ladder game | |
% Plays chutes and ladders game on a 10x10 board. All players start off the | |
% board (position 0). Players take turns rolling a 6-sided dice and moving up | |
% the board. There are 10 chutes and 9 ladders that can skip players ahead. | |
% Rolling a 6 allows the player to roll again. Rolling 3 consecutive 6's, | |
% however, sends the player back to space 1. The player is stuck at space 1 | |
% until they roll a 6 again. | |
% | |
% chutes_and_ladders.m | |
% Kristofer D. Kusano - 05/04/14 | |
n = 1; % number of players | |
assert(n > 0, 'need at least 1 player') | |
do_print = false; % debug printing (to see how one game progresses) | |
if do_print | |
clc; | |
end | |
% initialize game | |
b = create_gameboard(); | |
p = create_players(n); | |
p.moves(1, :) = zeros(1, p.players); % everyone starts at 0 (off board) | |
last_roll = cell(1, p.players); % store last roll | |
% who starts? | |
if (p.players > 1) | |
b.t = randi(p.players, 1); | |
else | |
b.t = 1; | |
end | |
% play game | |
if do_print | |
disp('Game Start'); | |
end | |
while (check_gameon(p)) | |
if do_print | |
fprintf(' Player %d''s turn. ', p.names(b.t)) | |
end | |
% roll the dice | |
droll = rolldice(); | |
if do_print | |
fprintf(' rolled a %d\n', droll) | |
end | |
% store consecutive rolls | |
if all(droll == last_roll{b.t}) | |
last_roll{b.t} = [last_roll{b.t}, droll]; | |
else | |
last_roll{b.t} = droll; % not consecutive, store | |
end | |
% check if player is stuck at beginning | |
if (p.stuck(b.t)) | |
if droll == 6 | |
p.stuck(b.t) = false; % player is no longer stuck | |
if do_print | |
fprintf(' Player %d is no longer stuck\n',... | |
p.names(b.t)) | |
end | |
else | |
p.turns(b.t) = p.turns(b.t) + 1; | |
b.t = next_turn(b.t, p.players, last_roll{b.t}); | |
if do_print | |
fprintf(' Player %d is still stuck, skipping turn\n\n',... | |
p.names(b.t)) | |
end | |
continue; % don't get to move | |
end | |
end | |
% move piece | |
pos_orig = p.pos(b.t); | |
pos_roll = pos_orig + droll; | |
if do_print | |
fprintf(' %d to %d...', pos_orig, pos_roll); | |
end | |
% check for chute or ladder | |
p.pos(b.t) = check_chute_ladder(pos_roll, b); | |
% did we go over 100? | |
if p.pos(b.t) > 100 | |
p.pos(b.t) = pos_orig; % need to roll 100 exactly | |
end | |
% print move | |
if do_print | |
if p.pos(b.t) > pos_roll | |
fprintf(' up a ladder to %d :)\n', p.pos(b.t)); | |
elseif p.pos(b.t) == pos_orig | |
fprintf(' back to %d, (need to roll %d to get to 100 exactly)\n',... | |
p.pos(b.t), 100 - p.pos(b.t)) | |
elseif p.pos(b.t) < pos_roll | |
fprintf(' down a chute to %d :(\n', p.pos(b.t)); | |
else | |
disp(' ') | |
end | |
end | |
% turn is over | |
p.turns(b.t) = p.turns(b.t) + 1; % turn count | |
p.moves(p.turns(b.t) + 1, b.t) = p.pos(b.t); % store this move | |
% is this player stuck? | |
if (~isempty(last_roll{b.t}) ... | |
&& all(last_roll{b.t} == 6) ... | |
&& length(last_roll{b.t}) >= 3) | |
% go back to space 1 | |
p.pos(b.t) = 1; | |
% player is now stuck at 1 until another 6 is rolled | |
p.stuck(b.t) = true; | |
last_roll{b.t} = 9; % reset roll count | |
if do_print | |
fprintf(['Player %d rolled 6 three times in a row.',... | |
' They are stuck at 1 until they roll 6 again'],... | |
p.names(b.t)) | |
end | |
end | |
% decide who goes next | |
b.t = next_turn(b.t, p.players, last_roll{b.t}); | |
if do_print | |
disp(' ') | |
end | |
end | |
if do_print | |
disp('Game Is Over'); | |
end | |
% who won? | |
iwon = p.pos >= 100; | |
assert(sum(iwon) == 1, 'only one player can win'); | |
p.winner(iwon) = true; % mark winner | |
if do_print | |
fprintf('Player %d won the game in %d turns\n',... | |
p.names(iwon), p.turns(iwon)); | |
end | |
% clean up moves | |
for i = 1:size(p.moves, 1) | |
if any(p.moves(i, :) >= 100) | |
pm = p.moves; | |
pm(i+1:end, :) = []; | |
p.moves = pm; | |
break; | |
end | |
end | |
end | |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
% Functions | |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
function b = create_gameboard() | |
%% creat a the game board according to Milton-Bradley 10x10 | |
% there are 10 chutes and 9 ladders | |
% location of chutes and ladders | |
% Nx2 matrix. first column is start, second is end | |
c = [16, 6; 47, 26; 49, 11; 56, 53; 62, 19; 64, 60; 87, 24; 93, 73; 95, 75; 98, 78]; | |
d = [1, 38; 4, 14; 9, 31; 28, 84; 21, 42; 36, 44; 51, 67; 71, 91; 80, 100]; | |
% check | |
assert(all(diff(c, 1, 2) < 0), 'all chutes must point down'); | |
assert(all(diff(d, 1, 2) > 0), 'all ladders must point up'); | |
% struct for output | |
b = struct(... | |
's', 10,... % number of sides | |
'c', c,... % Chute locations | |
'd', d,... % laDder locations | |
't', NaN ... % index of player who's turn it is? | |
); | |
end | |
function p = create_players(n) | |
%% create the players of the game | |
p = struct(... | |
'players', n,... % total number of players | |
'names', 1:n,... % names of players | |
'pos', zeros(1, n),... % current position on board (start off board) | |
'turns', zeros(1, n),... % total number of turns | |
'moves', NaN(1e4, n),... % store all moves | |
'winner', false(1, n),... % who won the game? | |
'stuck', false(1, n)... % is this player stuck at 1? | |
); | |
end | |
function n = rolldice() | |
%% roll a 6-sided dice | |
n = randi(6, 1, 1); | |
end | |
function is_gameon = check_gameon(p) | |
%% return true if game is still being played, false if player has won | |
is_gameon = true; | |
if (any(p.pos >= 100)) | |
is_gameon = false; | |
end | |
end | |
function new_pos = check_chute_ladder(pos, b) | |
%% check if current position is a chute or ladder, move peice | |
% logical | |
c = pos == b.c(:, 1); | |
d = pos == b.d(:, 1); | |
sc = sum(c); | |
sd = sum(d); | |
assert(sc + sd < 2, 'position is on a chute and ladder at the same time?') | |
% do move | |
if sc == 1 | |
new_pos = b.c(c, 2); % down a chute | |
elseif sd == 1 | |
new_pos = b.d(d, 2); % up a ladder | |
else | |
new_pos = pos; % no change | |
end | |
end | |
function t = next_turn(bt, players, last_roll) | |
%% decide who's turn it is next | |
if (~isempty(last_roll) && all(last_roll) == 6) | |
% rolled a 6, you get to go again | |
t = bt; | |
else | |
t = bt + 1; % increment | |
if t > players | |
t = 1; % back to 1 | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment