Mbed Mini Project: Snakes and Ladders Games
Overview
This project uses mbedLPC1768 as platform developing a simple Snake&Ladders game. A navigation switch is used to control two dices. Pushing the Up bottom will control the first dice, and pushing the Down bottom will control the second dice. As seen in the image below, each chess piece start from position-0 and run by the number of the dice. When either of the chess pieces arrives the position-16, the game stops. The one first arrives the position-16 is the winner. During the game, position-3 and position-11 are two special positions. When a chess piece arrives position-4, it will jump to position-8 immediately. When a chess piece arrives position-11, it will drop back to position-3. Sound effects load from MicroSD Card are accompanied with the events like rolling dice, jumping, dropping and winning the games. At the end the game, an image will be loaded from the MicroSD Card as the ending visual effect. Followed by that, the winner will be displayed as text in the uLCD screen.
Game Logic
Game Interface


Wiring
SparkfunNav Switch Breakout
WikiPage https://developer.mbed.org/users/4180_1/notebook/using-a-navigation-switch-digital-joystick/ /handbook
mbed LPC1768 SparkfunNav Switch Breakout gnd - p25 U - up p22 D - down nc -using internal pullups +
uLCD-144-G2 128 by 128 Smart Color LCD
WikiPage https://developer.mbed.org/users/4180_1/notebook/ulcd-144-g2-128-by-128-color-lcd/ /handbook
mbed uLCD Header uLCD cable 5V=VU 5V 5V Gnd Gnd Gnd TX=P9 RX TX RX=P10 TX RX P11 Reset Reset
SparkFun MicroSD Breakout Board
WikiPage https://developer.mbed.org/cookbook/SD-Card-File-System /handbook
MicroSD Breakout mbed CS o-------------o 8 (DigitalOut cs) DI o-------------o 5 (SPI mosi) VCC o-------------o VOUT SCK o-------------o 7 (SPI sclk) GND o-------------o GND DO o-------------o 6 (SPI miso) CD o
Sparkfun Class D audio amp breakout board
WikiPage https://developer.mbed.org/users/4180_1/notebook/using-a-speaker-for-audio-output/ /handbook
mbed TPA2005D1 Speaker gnd pwr - (gnd), in - Vout pwr + p14 in + out + + out - -
Import programSnake_Ladders_Games
Using mbed LPC1768, navigation swith (Joystick), uLCD-144-G2, microSD Transflash Breakout, Class D high-efficiency audio amp and a small speaker.
Codes
main
#include "mbed.h"
#include "uLCD_4DGL.h"
#include "SDFileSystem.h"
#include "wave_player.h"
DigitalOut led1(LED1);
DigitalOut led2(LED2);
SDFileSystem sd(p5, p6, p7, p8, "sd"); // the pinout on the mbed Cool Components workshop board
uLCD_4DGL uLCD(p13,p14,p11); // serial tx, serial rx, reset pin;
AnalogOut DACout(p18);
wave_player waver(&DACout);
Serial pc(USBTX, USBRX);
void sanke_ladder(){
//ladder
uLCD.line(84, 20, 84, 44, WHITE);
uLCD.line(92, 20, 92, 44, WHITE);
uLCD.line(84, 24, 92, 24, WHITE);
uLCD.line(84, 40, 92, 40, WHITE);
//sanke
uLCD.line(72, 24, 72, 56, WHITE);
uLCD.line(64, 32, 72, 24, WHITE);
uLCD.line(72, 24, 80, 32, WHITE);
}
void playdice(){
FILE *wave_file;
wave_file=fopen("/sd/Dice.wav","r");
waver.play(wave_file);
fclose(wave_file);
wait(0.01);
}
void playTaDa(){
FILE *wave_file;
wave_file=fopen("/sd/TaDa.wav","r");
waver.play(wave_file);
fclose(wave_file);
wait(0.01);
}
void playSad(){
FILE *wave_file;
wave_file=fopen("/sd/Sad.wav","r");
waver.play(wave_file);
fclose(wave_file);
wait(0.01);
}
void rollingdice1(){
playdice();
uLCD.filled_rectangle(17, 91, 47, 121, 0xFF0000);
uLCD.filled_rectangle(17, 91, 47, 121, 0x000000);
uLCD.filled_rectangle(17, 91, 47, 121, 0xFF0000);
uLCD.filled_rectangle(17, 91, 47, 121, 0x000000);
wait(1);
}
void rollingdice2(){
playdice();
uLCD.filled_rectangle(81, 91, 111, 121, 0x0080FF);
uLCD.filled_rectangle(81, 91, 111, 121, 0x000000);
uLCD.filled_rectangle(81, 91, 111, 121, 0x0080FF);
uLCD.filled_rectangle(81, 91, 111, 121, 0x000000);
wait(1);
}
class Nav_Switch
{
public:
Nav_Switch(PinName up,PinName down);
//int read();
//boolean functions to test each switch
bool up();
bool down();
private:
BusIn _pins;
};
Nav_Switch::Nav_Switch (PinName up,PinName down):
_pins(up, down)
{
_pins.mode(PullUp); //needed if pullups not on board or a bare nav switch is used - delete otherwise
wait(0.1); //delays just a bit for pullups to pull inputs high
}
inline bool Nav_Switch::up()
{
return !(_pins[0]);
}
inline bool Nav_Switch::down()
{
return !(_pins[1]);
}
Nav_Switch myNav( p25, p22); //pin order on Sparkfun breakout
int main()
{
pc.printf("GAME START\r\n");
//draw the board
//horizongtal line
uLCD.line(32, 16, 96, 16, WHITE);
uLCD.line(32, 32, 96, 32, WHITE);
uLCD.line(32, 48, 96, 48, WHITE);
uLCD.line(32, 64, 96, 64, WHITE);
uLCD.line(32, 80, 96, 80, WHITE);
//veritical line
uLCD.line(32, 16, 32, 80, WHITE);
uLCD.line(48, 16, 48, 80, WHITE);
uLCD.line(64, 16, 64, 80, WHITE);
uLCD.line(80, 16, 80, 80, WHITE);
uLCD.line(96, 16, 96, 80, WHITE);
//sanke%ladder
sanke_ladder();
//draw the dice1
//horizontal
uLCD.line(16, 90, 48, 90, WHITE);
uLCD.line(16, 122, 48, 122, WHITE);
//vertical
uLCD.line(16, 90, 16, 122, WHITE);
uLCD.line(48, 90, 48, 122, WHITE);
//draw the dice2
//horizontal
uLCD.line(80, 90, 112, 90, WHITE);
uLCD.line(80, 122, 112, 122, WHITE);
//vertical
uLCD.line(80, 90, 80, 122, WHITE);
uLCD.line(112, 90, 112, 122, WHITE);
//initialize the positions of dot1 and dot 2
int p1=0;
int p2=0;
while(1) {
//Push to roll the dice1
if(myNav.up()) {
led1=1;led2=0;
pc.printf("rolling Dice 1\r\n");
wait(0.5);
int move1=rand()%6+1;
pc.printf(" Move1:%d\r\n",move1);
switch (move1){
case 1:
rollingdice1();
uLCD.filled_circle(32, 106, 3, 0xFF0000);
break;
case 2:
rollingdice1();
uLCD.filled_circle(40, 98, 3, 0xFF0000);
uLCD.filled_circle(24, 114, 3, 0xFF0000);
break;
case 3:
rollingdice1();
uLCD.filled_circle(40, 98, 3, 0xFF0000);
uLCD.filled_circle(32, 106, 3, 0xFF0000);
uLCD.filled_circle(24, 114, 3, 0xFF0000);
break;
case 4:
rollingdice1();
uLCD.filled_circle(24, 98, 3, 0xFF0000);
uLCD.filled_circle(40, 98, 3, 0xFF0000);
uLCD.filled_circle(24, 113, 3, 0xFF0000);
uLCD.filled_circle(40, 113, 3, 0xFF0000);
break;
case 5:
rollingdice1();
uLCD.filled_circle(24, 98, 3, 0xFF0000);
uLCD.filled_circle(40, 98, 3, 0xFF0000);
uLCD.filled_circle(24, 113, 3, 0xFF0000);
uLCD.filled_circle(40, 113, 3, 0xFF0000);
uLCD.filled_circle(32, 105, 3, 0xFF0000);
break;
case 6:
rollingdice1();
uLCD.filled_circle(24, 98, 3, 0xFF0000);
uLCD.filled_circle(40, 98, 3, 0xFF0000);
uLCD.filled_circle(24, 105.5, 3, 0xFF0000);
uLCD.filled_circle(40, 105.5, 3, 0xFF0000);
uLCD.filled_circle(24, 113, 3, 0xFF0000);
uLCD.filled_circle(40, 113, 3, 0xFF0000);
break; }//end of switch move1
//draw dot 1
if (p1 + move1>16){
//clear screen
int x1; int y1;
x1=(((p1%4)+3)%4)*16+36;
y1=((p1-((((p1%4)+3)%4)+1))/4)*16+20;
uLCD.filled_circle(x1, y1, 3, 0x000000);
//new P1
p1 =16-(p1+move1 -16);
pc.printf("New P1: %d\r\n",p1);
//draw P1 dot
x1=(((p1%4)+3)%4)*16+36;
y1=((p1-((((p1%4)+3)%4)+1))/4)*16+20;
pc.printf("x1:%d\r\n",x1);
pc.printf("y1:%d\r\n\n",y1);
//draw P1 dot
sanke_ladder();
uLCD.filled_circle(x1, y1, 3, 0xFF0000);
wait(1);
//snake and ladder
if(p1==4){
uLCD.filled_circle(x1, y1, 3, 0x000000);
sanke_ladder();
playTaDa();
p1=8;
x1=(((p1%4)+3)%4)*16+36;
y1=((p1-((((p1%4)+3)%4)+1))/4)*16+20;
uLCD.filled_circle(x1, y1, 3, 0xFF0000);
pc.printf("x1 jump to:%d\r\n",x1);
pc.printf("y1 jump to:%d\r\n\n",y1);
}//end of if(p1==4)
else if (p1==11) {
uLCD.filled_circle(x1, y1, 3, 0x000000);
sanke_ladder();
playSad();
p1=3;
x1=(((p1%4)+3)%4)*16+36;
y1=((p1-((((p1%4)+3)%4)+1))/4)*16+20;
uLCD.filled_circle(x1, y1, 3, 0xFF0000);
pc.printf("x1 drop to:%d\r\n",x1);
pc.printf("y1 drop to:%d\r\n\n",y1);
}//end of else if (p1==1)
}//end of if(p1 + move1>16)
else {
//clear screen
int x1; int y1;
x1=(((p1%4)+3)%4)*16+36;
y1=((p1-((((p1%4)+3)%4)+1))/4)*16+20;
uLCD.filled_circle(x1, y1, 3, 0x000000);
//new P1
p1 =p1 + move1;
pc.printf("New P1:%d\r\n",p1);
//calculate P1 (x,y)
x1=(((p1%4)+3)%4)*16+36;
y1=((p1-((((p1%4)+3)%4)+1))/4)*16+20;
pc.printf("x1:%d\r\n",x1);
pc.printf("y1:%d\r\n\n",y1);
sanke_ladder();
uLCD.filled_circle(x1, y1, 3, 0xFF0000);
wait(0.1);
//snake and ladder
if(p1==4){
uLCD.filled_circle(x1, y1, 3, 0x000000);
sanke_ladder();
playTaDa();
p1=8;
x1=(((p1%4)+3)%4)*16+36;
y1=((p1-((((p1%4)+3)%4)+1))/4)*16+20;
uLCD.filled_circle(x1, y1, 3, 0xFF0000);
pc.printf("x1 jump to:%d\r\n",x1);
pc.printf("y1 jump to:%d\r\n\n",y1);
}//end of if(p1==4)
else if (p1==11) {
uLCD.filled_circle(x1, y1, 3, 0x000000);
sanke_ladder();
playSad();
p1=3;
x1=(((p1%4)+3)%4)*16+36;
y1=((p1-((((p1%4)+3)%4)+1))/4)*16+20;
uLCD.filled_circle(x1, y1, 3, 0xFF0000);
pc.printf("x1 drop to:%d\r\n",x1);
pc.printf("y1 drop to:%d\r\n\n",y1);
} //end of elseif(p1==11)
//draw P1 dot
uLCD.filled_circle(x1, y1, 3, 0xFF0000);
wait(1);
}//end of else_p1<16
if (p1 ==16){
//SD card needed with image and video files for last two demos
uLCD.cls();
uLCD.media_init();
uLCD.set_sector_address(0x0000, 0x0000);
uLCD.display_image(0,0);
//Play the wave file
FILE *wave_file;
//printf("\n\n\nHello, wave world!\n");
wave_file=fopen("/sd/Cheering.wav","r");
waver.play(wave_file);
fclose(wave_file);
wait(0.01);
pc.printf("P1 WIN!");
uLCD.cls();
uLCD.color(RED);
uLCD.locate(2,6);
uLCD.text_width(2);
uLCD.text_height(2);
uLCD.printf("P1 WON!");
break;
}//end of if(p1==16)
wait(0.5);
}//end of if(myNav.up())
//push to roll the dice2
else if(myNav.down()){
led1=0;
led2=1;
pc.printf("rolling Dice 2\r\n");
int move2 = rand()%6+1;
pc.printf("DICE2: %d\r\n\n",move2);
switch (move2){
case 1:
rollingdice2();
uLCD.filled_circle(96, 106, 3, 0x0080FF);
break;
case 2:
rollingdice2();
uLCD.filled_circle(104, 98, 3, 0x0080FF);
uLCD.filled_circle(88, 114, 3, 0x0080FF);
break;
case 3:
rollingdice2();
uLCD.filled_circle(104, 98, 3, 0x0080FF);
uLCD.filled_circle(96, 106, 3, 0x0080FF);
uLCD.filled_circle(88, 114, 3, 0x0080FF);
break;
case 4:
rollingdice2();
uLCD.filled_rectangle(81, 91, 111, 121, 0x000000);
uLCD.filled_circle(88, 98, 3, 0x0080FF);
uLCD.filled_circle(104, 98, 3, 0x0080FF);
uLCD.filled_circle(88, 113, 3, 0x0080FF);
uLCD.filled_circle(104, 113, 3, 0x0080FF);
break;
case 5:
rollingdice2();
uLCD.filled_rectangle(81, 91, 111, 121, 0x000000);
uLCD.filled_circle(88, 98, 3, 0x0080FF);
uLCD.filled_circle(104, 98, 3, 0x0080FF);
uLCD.filled_circle(88, 113, 3, 0x0080FF);
uLCD.filled_circle(104, 113, 3, 0x0080FF);
uLCD.filled_circle(96, 105, 3, 0x0080FF);
break;
case 6:
rollingdice2();
uLCD.filled_circle(88, 98, 3, 0x0080FF);
uLCD.filled_circle(104, 98, 3, 0x0080FF);
uLCD.filled_circle(88, 105.5, 3, 0x0080FF);
uLCD.filled_circle(104, 105.5, 3, 0x0080FF);
uLCD.filled_circle(88, 113, 3, 0x0080FF);
uLCD.filled_circle(104, 113, 3, 0x0080FF);
break;
}//end of switch move2
//draw dot 2
if (p2 + move2>16){
//clear screen
int x2; int y2;
x2=(((p2%4)+3)%4)*16+36;
y2=((p2-((((p2%4)+3)%4)+1))/4)*16+28;
uLCD.filled_circle(x2, y2, 3, 0x000000);
//new P2
p2 =16-(p2+move2 -16);
pc.printf("New P2: %d\r\n",p2);
//draw P1 dot
x2=(((p2%4)+3)%4)*16+36;
y2=((p2-((((p2%4)+3)%4)+1))/4)*16+28;
pc.printf("x2:%d\r\n",x2);
pc.printf("y2:%d\r\n\n",y2);
//draw P1 dot
uLCD.filled_circle(x2, y2, 3, 0x0080FF);
wait(1);
//snake and ladder
if(p2==4){
uLCD.filled_circle(x2, y2, 3, 0x000000);
sanke_ladder();
playTaDa();
p2=8;
pc.printf("P2 jump to:%d\r\n",p2);
x2=(((p2%4)+3)%4)*16+36;
y2=((p2-((((p2%4)+3)%4)+1))/4)*16+28;
pc.printf("x2 jump to:%d\r\n",x2);
pc.printf("y2 jump to:%d\r\n\n",y2);
uLCD.filled_circle(x2, y2, 3, 0x0080FF);
}//end of if(p2==4)
else if (p2==11) {
uLCD.filled_circle(x2, y2, 3, 0x000000);
sanke_ladder();
playSad();
p2=3;
pc.printf("P2 drop to:%d\r\n",p2);
x2=(((p2%4)+3)%4)*16+36;
y2=((p2-((((p1%4)+3)%4)+1))/4)*16+28;
pc.printf("x2 drop to:%d\r\n",x2);
pc.printf("y2 drop to:%d\r\n\n",y2);
uLCD.filled_circle(x2, y2, 3, 0x0080FF);
}//end of elseif(p2==1)
}//end of if(p2 + move2>16)
else {
//clear screen
int x2; int y2;
x2=(((p2%4)+3)%4)*16+36;
y2=((p2-((((p2%4)+3)%4)+1))/4)*16+28;
uLCD.filled_circle(x2, y2, 3, 0x000000);
//new P2
p2 =p2 + move2;
pc.printf("New P2:%d\r\n",p2);
//calculate P2(x,y)
x2=(((p2%4)+3)%4)*16+36;
y2=((p2-((((p2%4)+3)%4)+1))/4)*16+28;
pc.printf("x2:%d\r\n",x2);
pc.printf("y2:%d\r\n\n",y2);
//draw P2 dot
sanke_ladder();
uLCD.filled_circle(x2, y2, 3, 0x0080FF);
wait(0.5);
//snake and ladder
if(p2==4){
uLCD.filled_circle(x2, y2, 3, 0x000000);
sanke_ladder();
playTaDa();
p2=8;
pc.printf("P2 jump to:%d\r\n",p2);
x2=(((p2%4)+3)%4)*16+36;
y2=((p2-((((p2%4)+3)%4)+1))/4)*16+28;
pc.printf("x2 jump to:%d\r\n",x2);
pc.printf("y2 jump to:%d\r\n\n",y2);
uLCD.filled_circle(x2, y2, 3, 0x0080FF);
}//end of if
else if (p2==11) {
uLCD.filled_circle(x2, y2, 3, 0x000000);
sanke_ladder();
playSad();
p2=3;
pc.printf("P2 drop to:%d\r\n",p2);
x2=(((p2%4)+3)%4)*16+36;
y2=((p2-((((p1%4)+3)%4)+1))/4)*16+28;
pc.printf("x2 drop to:%d\r\n",x2);
pc.printf("y2 drop to:%d\r\n\n",y2);
uLCD.filled_circle(x2, y2, 3, 0x0080FF);
} //end of elseif
wait(1);
}//end of else
if (p2 ==16){
//SD card needed with image and video files for last two demos
uLCD.cls();
uLCD.media_init();
uLCD.set_sector_address(0x0000, 0x0000);
uLCD.display_image(0,0);
//Play the wave file
FILE *wave_file;
//printf("\n\n\nHello, wave world!\n");
wave_file=fopen("/sd/Cheering.wav","r");
waver.play(wave_file);
fclose(wave_file);
wait(0.01);
pc.printf("P2 WIN!");
uLCD.cls();
uLCD.color(BLUE);
uLCD.locate(2,6);
uLCD.text_width(2);
uLCD.text_height(2);
uLCD.printf("P2 WON!");
break;
}//end of if(p2 ==16)
wait(0.5);
}//end of else if(myNav.down())
wait(0.02);
}//end of while(1)
}//end of main
Video Demo
With better Sound Quality
The bit resolution is changed to 16 bit, and the sampling rate is change to 1,6000 Hz.
Please log in to post comments.
