Skip to content

Instantly share code, notes, and snippets.

@KrisKusano
Created May 4, 2014 18:58
Show Gist options
  • Save KrisKusano/cf6fd47b254680f59ab0 to your computer and use it in GitHub Desktop.
Save KrisKusano/cf6fd47b254680f59ab0 to your computer and use it in GitHub Desktop.
Play a game of "Chutes and Ladders" in MATLAB
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