Last Updated or created 2023-04-21
Info:
- PlatformIO tested ( install StackArray.h in lib/StackArray/StackArray.h )
- Reset button and dipswitches for below options
- Visited pathmode ( dip switch 1)
- Preview maze generation ( dip switch 3)
- Hard mode – starts at first position when hitting a wall ( dip 2 )
- Longest path mode (longest stackarray before stack.pop (dip 4 )
- Prints serial info, like a drawn maze
- Pixel remapping for other displays ( Below mapping i had to use, see source sketch )
- Visited pathmode ( dip switch 1)
- Reset button and dipswitches for below options
How is the maze generated?
It is generated using recursive backtracking:
Start at 0,0 mark visited, select a random direction from unvisited neighbours, push current on the stack, goto new location, and mark this visited.
Repeat until no possible directions.
pop from the stack a previous location, another direction possible? Take that path and repeat.
Repeat popping from stack, until stack empty .. now all cells are visited
longest pop : 41 maze ------------------------ | || || || | --- --- | || || || || | ------------ --- | || || || | --- --- --- | || || || | --- --- | || || || || || || | | || || || || || || || | --- | || || || || || | --------- --- | || | ------------------------ x y : 00 maze 4 |4|3|6|3|6|5|3|2| |2|12|9|12|9|6|9|10| |14|5|3|2|6|9|6|9| |14|3|12|11|10|6|13|3| |10|10|2|10|10|10|6|11| |8|10|10|10|10|10|10|10| |6|9|12|9|10|8|10|10| |12|5|5|5|13|5|9|8|
Easiest play mode: Preview Maze, Show visited path, NO reset to square 0,0 and NOT the longest path so :
Show visited DIP1 | Reset to 0,0 DIP2 | Preview DIP3 | Longest path DIP4 |
1 | 0 | 1 | 0 |
Hard mode:
Show visited DIP1 | Reset to 0,0 DIP2 | Preview DIP3 | Longest path DIP4 |
0 | 1 | 0 | 1 |
Todo: Battery / batterymanager / 3D case / better buttons
Some video shorts put together to show modes
CODE
#include <Arduino.h> #include <Adafruit_NeoPixel.h> #include "StackArray.h" // Pin Assign int up=25; int down=33; int left=32; int right=26; int trailsw=17; int restartsw=5; int showmazesw=18; int popendsw=19; int xend=7; int yend=7; int countpop=0; int currentpop=0; int directions[4]{}; int notalldone = 1; int tmpx=0; int tmpy=0; int xgen = 1; int ygen = 1; int x = 0; int y = 0; int showmaze = 0; // 0 easy = trail // 1 only red walls // 2 = reset to 0.0 int mode=0; //int trail=32; int trail=32; // Which pin on the Arduino is connected to the NeoPixels? #define LED_PIN 2 // How many NeoPixels are attached to the Arduino? #define LED_COUNT 64 // Declare our NeoPixel strip object: Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800); int maze[8][8] = { }; int displaymatrix[8][8] = { { 0,1,2,3,4,5,6,7 }, { 15,14,13,12,11,10,9,8 }, {16,17,18,19,20,21,22,23}, {31,30,29,28,27,26,25,24}, {32,33,34,35,36,37,38,39}, {47,46,45,44,43,42,41,40}, {48,49,50,51,52,53,54,55}, {63,62,61,60,59,58,57,56} }; int visitmatrix[10][10] = { 1,1,1,1,1,1,1,1,1,1, 1,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,1, 1,1,1,1,1,1,1,1,1,1 }; void(* resetFunc) (void) = 0; void drawmaze2(){ Serial.print("x y : "); Serial.print(x); Serial.println(y); Serial.print("maze "); Serial.println(maze[x][y]); for(int ledy=0;ledy<8;ledy++) { Serial.print("|"); for(int ledx=0;ledx<8;ledx++){ Serial.print(maze[ledx][ledy]); Serial.print("|"); if ( maze[ledx][ledy] != 0 ) { // mled.dot(ledx,ledy); // draw dot // mled.display(); // delay(50); } } Serial.println(""); } Serial.println(""); delay(100); } void drawmaze(){ Serial.println("maze "); for(int ledy=0;ledy<8;ledy++) { // 1st line for(int ledx=0;ledx<8;ledx++){ if(bitRead(maze[ledx][ledy], 3) == 0){ Serial.print("---"); } else { Serial.print(" "); } } Serial.println(""); // 2nd line for(int ledx=0;ledx<8;ledx++){ if(bitRead(maze[ledx][ledy], 0) == 1){ if(bitRead(maze[ledx][ledy], 2) == 1){ Serial.print(" "); } else { Serial.print(" |"); } } if(bitRead(maze[ledx][ledy], 0) == 0){ if(bitRead(maze[ledx][ledy], 2) == 1){ Serial.print("| "); } else { Serial.print("| |"); } } } Serial.println(""); } // last line int ledy=7; for(int ledx=0;ledx<8;ledx++){ if(bitRead(maze[ledx][ledy], 1) == 0){ Serial.print("---"); } else { Serial.print(" "); } } Serial.println(""); //Serial.println(""); delay(100); } void mazegen(){ visitmatrix[xgen][ygen]=1; StackArray <int> rowStack; StackArray <int> colStack; rowStack.push(xgen); colStack.push(ygen); while(notalldone == 1){ visitmatrix[xgen][ygen]=1; while(!rowStack.isEmpty()) { int count=0; //up if ( visitmatrix[xgen-1][ygen] == 0 ){ directions[count]=1; count++; } //right if ( visitmatrix[xgen][ygen+1] == 0 ){ directions[count]=2; count++; } //down if ( visitmatrix[xgen+1][ygen] == 0 ){ directions[count]=4; count++; } //left if ( visitmatrix[xgen][ygen-1] == 0 ){ directions[count]=8; count++; } if (showmaze == 1 ){ strip.setPixelColor(displaymatrix[xgen-1][ygen-1], 32, 32, 32); strip.show(); delay(50); } // no dir found if (count == 0 ) { if (digitalRead(popendsw) == 0 ){ currentpop = rowStack.count(); if (currentpop > countpop ) { countpop = currentpop; xend = xgen-1; yend = ygen-1; Serial.print("longest pop : "); Serial.println(currentpop); } } // mled.dot(x-1,y-1); // mled.display(); xgen = rowStack.pop(); ygen = colStack.pop(); // Serial.println("popping "); } else { // count random direction int dir = directions[random(count)]; //Serial.println("push "); rowStack.push(xgen); colStack.push(ygen); // Serial.print("nr dir : "); // Serial.println(count); //delay(100); // Serial.println(dir); // move 1,1 to 0,0 //mled.dot(x-1,y-1); //mled.display(); // set direction in maze, dit moet bit set worden int mybits = maze[xgen-1][ygen-1]; int storedir = mybits | dir; maze[xgen-1][ygen-1] = storedir; if ( dir == 1){ int getup = maze[xgen-2][ygen-1]; int storedir = getup | 4; maze[xgen-2][ygen-1] = storedir; } if ( dir == 2){ int getup = maze[xgen-1][ygen]; int storedir = getup | 8; maze[xgen-1][ygen] = storedir; } if ( dir == 4){ int getup = maze[xgen][ygen-1]; int storedir = getup | 1; maze[xgen][ygen-1] = storedir; } if ( dir == 8){ int getup = maze[xgen-1][ygen-2]; int storedir = getup | 2; maze[xgen-1][ygen-2] = storedir; } // maze[x-1][y-1] = dir; //set new square if (dir == 1){ xgen--; } if (dir == 2){ ygen++; } if (dir == 4){ xgen++; } if (dir == 8){ ygen--; } visitmatrix[xgen][ygen]=1; //drawmaze(); } } notalldone = 0; //#2 // if found 0 in 10x10 matrix visited, do for(int checkx=0;checkx<10;checkx++){ for(int checky=0;checky<10;checky++){ if ( visitmatrix[checkx][checky] == 0 ){ tmpx=xgen; tmpy=ygen; notalldone = 1; } } } } rowStack.push(tmpx); colStack.push(tmpy); } void setup() { pinMode(32, INPUT_PULLUP); pinMode(33, INPUT_PULLUP); pinMode(25, INPUT_PULLUP); pinMode(26, INPUT_PULLUP); pinMode(popendsw, INPUT_PULLUP); pinMode(trailsw, INPUT_PULLUP); pinMode(restartsw, INPUT_PULLUP); pinMode(showmazesw, INPUT_PULLUP); Serial.begin(115200); strip.begin(); strip.show(); // Initialize all pixels to 'off' strip.setBrightness(10); unsigned long seed = 0; for (int i=0; i<32; i++) { seed = seed | ((analogRead(A0) & 0x01) << i); } randomSeed(seed); if (digitalRead(showmazesw) == 0){ showmaze = 1; } mazegen(); drawmaze(); drawmaze2(); strip.fill(0, 0, 64); strip.show(); // Initialize all pixels to 'off' strip.setPixelColor(displaymatrix[x][y], 0, 0, 255); strip.setPixelColor(displaymatrix[xend][yend], 0, 255, 0); strip.show(); x=0; y=0; } uint32_t Wheel(byte WheelPos) { WheelPos = 255 - WheelPos; if(WheelPos < 85) { return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3); } if(WheelPos < 170) { WheelPos -= 85; return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3); } WheelPos -= 170; return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0); } void reset2start() { strip.setPixelColor(displaymatrix[x][y], 0, 0, 0); strip.show(); x = 0; y = 0; strip.begin(); strip.show(); // Initialize all pixels to 'off' strip.setBrightness(10); strip.setPixelColor(displaymatrix[x][y], 0, 0, 255); strip.setPixelColor(displaymatrix[xend][yend], 0, 255, 0); strip.show(); } void rainbow(uint8_t wait) { uint16_t i, j; for(j=0; j<256; j++) { for(i=0; i<strip.numPixels(); i++) { strip.setPixelColor(i, Wheel((i+j) & 255)); } strip.show(); delay(wait); } } void loop() { if (digitalRead(trailsw) == 0 ){ trail = 32; } else { trail = 0; } if (digitalRead(restartsw) == 0 ){ mode = 2; } else { mode = 0; } int isUp = (bitRead(maze[x][y], 1)); int isRight = (bitRead(maze[x][y], 2)); int isDown = (bitRead(maze[x][y], 3)); int isLeft = (bitRead(maze[x][y], 0)); //isUp = 1; //isDown = 1; //isLeft = 1; //isRight = 1; if (digitalRead(up) == 0) { if (isUp == 1){ strip.setPixelColor(displaymatrix[x][y], 0, 0, trail); y++; drawmaze(); if ( y > 7) { y=7;} strip.setPixelColor(displaymatrix[x][y], 0, 0, 255); strip.show(); } else { strip.setPixelColor(displaymatrix[x][y], 255, 0, 0); strip.show(); delay(100); strip.setPixelColor(displaymatrix[x][y], 0, 0, 255); strip.show(); if (mode == 2){ delay(1000); reset2start(); } } } if (digitalRead(down) == 0) { if (isDown == 1){ strip.setPixelColor(displaymatrix[x][y], 0, 0, trail); y--; drawmaze(); if ( y < 0) { y=0;} strip.setPixelColor(displaymatrix[x][y], 0, 0, 255); strip.show(); } else { strip.setPixelColor(displaymatrix[x][y], 255, 0, 0); strip.show(); delay(100); strip.setPixelColor(displaymatrix[x][y], 0, 0, 255); strip.show(); if (mode == 2){ delay(1000); reset2start(); } } } if (digitalRead(left) == 0) { drawmaze(); if (isLeft == 1){ strip.setPixelColor(displaymatrix[x][y], 0, 0, trail); x--; drawmaze(); if ( x < 0) { x=0;} strip.setPixelColor(displaymatrix[x][y], 0, 0, 255); strip.show(); } else { strip.setPixelColor(displaymatrix[x][y], 255, 0, 0); strip.show(); delay(100); strip.setPixelColor(displaymatrix[x][y], 0, 0, 255); strip.show(); if (mode == 2){ delay(1000); reset2start(); } } } if (digitalRead(right) == 0) { drawmaze(); if (isRight == 1){ strip.setPixelColor(displaymatrix[x][y], 0, 0, trail); x++; drawmaze(); if ( x > 7) { x=7;} strip.setPixelColor(displaymatrix[x][y], 0, 0, 255); strip.show(); } else { strip.setPixelColor(displaymatrix[x][y], 255, 0, 0); strip.show(); delay(100); strip.setPixelColor(displaymatrix[x][y], 0, 0, 255); strip.show(); if (mode == 2){ delay(1000); reset2start(); } } } if (x ==xend && y == yend){ strip.begin(); strip.show(); // Initialize all pixels to 'off' rainbow(20); } delay(200); }