Components and supplies
1,3" OLED Display SH1106 128x64 I2C
Arduino Nano Every
6 mm push-button switch
Breadboard - 830 contacts
Apps and platforms
Arduino IDE
Project description
Code
Hanoi
cpp
1/****** The Tower of Hanoi ******/ 2 3#include <U8g2lib.h> 4U8G2_SH1106_128X64_NONAME_F_HW_I2C 5 u8g2(U8G2_R0); 6 7int disksNumber=5; 8int speedDelay=400; 9int animDelay=7; 10 11int tower[3][10]; 12 13const int downPin=A7; 14const int upPin=2; 15const int startPin=3; 16volatile bool downPressed=false; 17volatile bool upPressed=false; 18volatile bool startPressed=false; 19 20/* Display the 3 towers on the screen */ 21 22void displayTowers(void) 23{ 24 u8g2.clearBuffer(); 25 26/* Draw the 3 rods */ 27 for(int i=0; i<3; i++) 28 u8g2.drawBox(30+32*i, 23, 3, 40); 29 30/* Draw the disks */ 31 for(int i=0; i<3; i++) 32 for(int j=0; j<10; j++) 33 if(tower[i][j]!=0) 34 u8g2.drawBox(28+32*i-tower[i][j], 35 60-4*(j), 36 8+2*tower[i][j], 3); 37 38 u8g2.sendBuffer(); 39} 40 41/* Manage the speed of the game by controlling 42 the speed delay with up and down push 43 buttons then by applying this delay */ 44 45void manageGameSpeed(void) 46{ 47 if(upPressed) 48 { 49 if(speedDelay>=100) speedDelay-=100; 50 upPressed=false; 51 } 52 if(downPressed) 53 { 54 if(speedDelay<1000) speedDelay+=100; 55 downPressed=false; 56 } 57 delay(speedDelay); 58} 59 60/* Adjust the number of disks with the up 61 and down push buttons then start the game 62 with the start push button */ 63 64void initGame(void) 65{ 66 bool buttonPressed=true; 67 68 while(!startPressed) 69 { 70 if(upPressed) 71 { 72 if(disksNumber<9) disksNumber++; 73 buttonPressed=true; 74 upPressed=false; 75 } 76 if(downPressed) 77 { 78 if(disksNumber>1) disksNumber--; 79 buttonPressed=true; 80 downPressed=false; 81 } 82 if(buttonPressed) 83 { 84/* Empty the 3 towers */ 85 for(int i=0; i<3; i++) 86 for(int j=0; j<10; j++) 87 tower[i][j]=0; 88/* Then put the right number of disks onto 89 the first tower */ 90 for(int i=0; i<disksNumber; i++) 91 tower[0][i]=disksNumber-i; 92 93 displayTowers(); 94 buttonPressed=false; 95 } 96 } 97 startPressed=false; 98} 99 100/* Calculate the height of a tower */ 101 102int height(int towerNumber) 103{ 104 int h; 105 106 for(h=0; tower[towerNumber][h]!=0; h++); 107 return h; 108} 109 110/* Move one disk from a tower to another. An 111 animation is obtained by some intermediate 112 positions */ 113 114void moveOnediskAnimated(int from, int to) 115{ 116 int hFrom; 117 int hTo; 118 int diskToMove; 119 120/* Calculate the heights of the two stacks */ 121 hFrom=height(from); 122 hTo=height(to); 123 diskToMove=tower[from][hFrom-1]; 124 125/* Lift the disk just above its original 126 position then wait for animDelay */ 127 tower[from][hFrom-1]=0; 128 tower[from][hFrom]=diskToMove; 129 displayTowers(); 130 delay(animDelay); 131 132/* Erase the disk then wait for animDelay. 133 Your brain will imagine that the disk is 134 between the two towers */ 135 tower[from][hFrom]=0; 136 displayTowers(); 137 delay(animDelay); 138 139/* Draw the disk just above its final position 140 then wait for animDelay */ 141 tower[to][hTo+1]=diskToMove; 142 displayTowers(); 143 delay(animDelay); 144 145/* Draw the disk at its final position */ 146 tower[to][hTo+1]=0; 147 tower[to][hTo]=diskToMove; 148 149 displayTowers(); 150 manageGameSpeed(); 151 152/* Manage the pause with the start push 153 button */ 154 if(startPressed) 155 { 156 startPressed=false; 157 while(!startPressed); 158 startPressed=false; 159 } 160} 161 162/* Recursive function that moves a stack 163 of n disks from a rod to another in the 164 minimal number of moves. If the stack 165 to be moved is not empty move the n-1 disks 166 which are above the stack towards the third 167 rod by calling the move function, then move 168 the disk which was at the bottom of the 169 stack towards its final position, then move 170 the disks which has been put on the third 171 rod towards the final rod by calling the 172 move function again. */ 173 174void move(int from, int to, int n) 175{ 176 if(n!=0) 177 { 178/* Calculate the intermediate rod number */ 179 int intermediate=3-to-from; 180 181 move(from, intermediate, n-1); 182 moveOnediskAnimated(from, to); 183 move(intermediate, to, n-1); 184 } 185} 186 187/* The 3 interrupt routines that are called 188 when you press a push button */ 189void interruptRoutineReadDown(void) 190{ 191 noInterrupts(); 192 delayMicroseconds(10000); 193 if(digitalRead(downPin)==LOW) 194 downPressed=true; 195 interrupts(); 196} 197 198void interruptRoutineReadUp(void) 199{ 200 noInterrupts(); 201 delayMicroseconds(10000); 202 if(digitalRead(upPin)==LOW) 203 upPressed=true; 204 interrupts(); 205} 206 207void interruptRoutineReadStart(void) 208{ 209 noInterrupts(); 210 delayMicroseconds(10000); 211 if(digitalRead(startPin)==LOW) 212 startPressed=true; 213 interrupts(); 214} 215 216void setup() 217{ 218 u8g2.begin(); 219 pinMode(downPin, INPUT_PULLUP); 220 pinMode(upPin, INPUT_PULLUP); 221 pinMode(startPin, INPUT_PULLUP); 222 attachInterrupt(digitalPinToInterrupt 223 (downPin), 224 interruptRoutineReadDown,FALLING); 225 attachInterrupt(digitalPinToInterrupt 226 (upPin), 227 interruptRoutineReadUp, FALLING); 228 attachInterrupt(digitalPinToInterrupt 229 (startPin), 230 interruptRoutineReadStart, FALLING); 231} 232 233void loop() 234{ 235 initGame(); 236 move(0, 2, disksNumber); 237 while(!startPressed); 238 startPressed=false; 239}
Downloadable files
Hanoi drawing
Hanoi drawing 1.jpg
Comments
Only logged in users can leave comments