Keep talking and nobody explodes Docs

Devos — Maze

Deze puzzel, gemaakt door David, is een labyrintspel waarbij de speler een stipje moeten navigeren van de startpositie naar het eindpunt. De speler bestuurt de bewegingen van het stipje met behulp van een afstandsbediening die infrarood signalen uitzendt. De positie van het stipje wordt weergegeven op een 8x8 led matrix.

Foto van de maze puzzel

  #include <ShiftRegister74HC595.h>
  #include <IRremote.h>
  #include <Servo.h>
  // https://blog.timodenk.com/shift-register-arduino-library/
  // https://learn.adafruit.com/74hc595/pinouts
  // https://osoyoo.com/2017/07/15/8x8-led-matrix/
  ShiftRegister74HC595<2> sr(10,13,2);  

  uint8_t binary[] = {
  B00000001,
  B00000010,
  B00000100,
  B00001000,
  B00010000,
  B00100000,
  B01000000,
  B10000000
  };    

  int RECV_PIN = 11;
  IRrecv irrecv(RECV_PIN);
  decode_results results;

  struct Vector{
    int x, y;
    Vector(){}
    Vector(int xpos, int ypos){
      x = xpos;
      y = ypos;
    }
  };
  struct HEXstring
  {
    long unsigned int h1;
    long unsigned int h2;
    Vector dir;
    HEXstring(long unsigned int hex1, long unsigned int hex2, Vector direction)
    {
      h1 = hex1;
      h2 = hex2;
      dir = direction;
    }
    bool Compare(long unsigned int hex)
    {
      return hex == h1 || hex == h2;
    }
  };
  static HEXstring upHEX = HEXstring(0x511DBB, 0xFF629D, Vector(0, 1));
  static HEXstring downHEX = HEXstring(0xA3C8EDDB, 0xFFA857, Vector(0, -1));
  static HEXstring leftHEX = HEXstring(0x20FE4DBB, 0xFFC23D, Vector(1, 0));
  static HEXstring rightHEX = HEXstring(0x52A3D41F, 0xFF22DD, Vector(-1, 0));

  static HEXstring IRhexes[4] = {upHEX, downHEX, leftHEX, rightHEX};
  struct Cell{
    const Vector m_pos;
    bool m_allowed[4];

    Cell(Vector pos, bool allowed[4])
    {
      m_pos = pos;
      for(int i = 0; i < 4; ++i){
        m_allowed[i] = allowed[i];
      }
      // !! up right down left !!
    }
  };

  class Player{
    Vector m_pos;
    Cell ** m_mazeRef;
    public:
    Player(Cell* maze[64], Vector pos)
    {
      m_pos = pos;
      m_mazeRef = maze;
    }
    bool move(Vector dir){
      bool checkMove = false;
      switch(dir.x){
        case 1:
        checkMove = m_mazeRef[m_pos.y*8 + m_pos.x]->m_allowed[1];
        break;
        case -1:
        checkMove = m_mazeRef[m_pos.y*8 + m_pos.x]->m_allowed[3];
        break;
      }
      switch(dir.y){
        case 1:
        checkMove = m_mazeRef[m_pos.y*8 + m_pos.x]->m_allowed[0];
        break;
        case -1:
        checkMove = m_mazeRef[m_pos.y*8 + m_pos.x]->m_allowed[2];
        break;
      } 
      if(checkMove){
        m_pos.x += dir.x;
        m_pos.y -= dir.y;
      }
      return checkMove;
    }
    Vector getPos(){
      return m_pos;
    }
  };
  class EndPoint{
    const Vector m_pos;
    public:
    EndPoint(Vector pos){
      m_pos = pos;
    }
    Vector getPos(){
      return m_pos;
    }
  };
  class MazeGame{
    Player * m_player;
    EndPoint * m_endPoint = nullptr;
    Cell ** m_maze;
    bool m_gameActive = false;
    public:
    MazeGame(){}
    MazeGame(Player * player, Cell * maze[64])
    {
      m_player = player;
      m_maze = maze;
    }
    void StartGame(EndPoint * endPoint)
    {
      m_endPoint = endPoint;
      m_gameActive = true;
    }
    void Update()
    {
      if(m_gameActive)
      {
        int IRresult = CheckIR();
        bool moveResult = true;
        switch(IRresult){
          case -1:
            moveResult = true;
            break;
          case 0:
            moveResult = m_player->move(Vector(0,1));
            IRresult = -1;
            break;
          case 1:
            moveResult = m_player->move(Vector(1,0));
            IRresult = -1;
            break;
          case 2:
            moveResult = m_player->move(Vector(0,-1));
            IRresult = -1;
            break;
          case 3:
            moveResult = m_player->move(Vector(-1,0));
            IRresult = -1;
            break;
        }
        WriteToScreen();
        m_gameActive = moveResult;
        if(!moveResult){
          //Serial.println("Hit a wall");
        }
        else{
          m_gameActive = CheckEnd();
        }

      }
    }
  void ClearScreen()
  {  
    uint8_t pinValues[] = {B00000000, B11111111};
    sr.setAll(pinValues);
  } 
    bool CheckEnd(){
      Vector ppos = m_player->getPos();
      Vector epos = m_endPoint->getPos();
      if(ppos.x == epos.x && ppos.y == epos.y){
        //Serial.println("YOU WIN");
        return false;
      }
      return true;
    }
    int CheckIR()
    {
      // !! up right down left !!
      int result = -1;
      // IR example
      if (irrecv.decode(&results)) {  
      for(HEXstring currHex : IRhexes){
        if(currHex.Compare(results.value))
        {
          switch(currHex.dir.x){
            case 1:
              result = 1;
              break;
            case -1:
              result = 3;
              break;
            default:
              switch(currHex.dir.y){
                case 1:
                  result = 0;
                  break;
                case -1:
                  result = 2;
                  break;
              }
            }
          }
        }
        irrecv.resume(); // Receive the next value
      }
      delay(100);
      return result;
    //
    }
    void WriteToScreen()
    {
      Vector currPos = m_player->getPos();
      
      uint8_t pinValues[] = {binary[currPos.y], B11111111 - binary[currPos.x]};
      sr.setAll(pinValues);
    }  
  };

  char testMaze[64] = {
  '9', '5', '5', '4', '9', '5', '5', '7', 
  '0', '9', '4', '9', '1', '9', '7', '0', 
  '0', '3', 'A', 'B', '9', '1', '0', '2', 
  '0', '9', '1', '0', '3', '7', '3', '7', 
  '0', '3', '7', '3', '7', '0', '9', 'B', 
  '3', '7', '0', '9', '1', '0', '0', '2', 
  '8', '0', '0', '0', '6', '1', '3', '7', 
  '3', 'C', '1', '3', '5', '5', '5', '1'
  };
  /*
  95549557
  09491970
  03AB9102
  09103737
  0373709B
  37091002
  80006137
  3C135551
  voort gemak
  https://www.mazegenerator.net/
  https://textfancy.com/character-wrapper/
  */

  MazeGame mazeGame;
  Cell* makeCell(int i) {
          Vector pos;
          pos.x = i%8;
          pos.y = i/8;
    switch(testMaze[i]){
      case '0':{      
        bool dirs[4] = {true, false, true, false};
        return new Cell(pos, dirs);
      }
      case '1':{
        bool dirs[4] = {true, false, false, true};
        return new Cell(pos, dirs);
      }
      case '2':{
        bool dirs[4] = {true, false, false, false};
        return new Cell(pos, dirs);
      }
      case '3':{
        bool dirs[4] = {true, true, false, false};
        return new Cell(pos, dirs);
      }
      case '4':{
        bool dirs[4] = {false, false, false, true};
        return new Cell(pos, dirs);
      }
      case '5':{
        bool dirs[4] = {false, true, false, true};
        return new Cell(pos, dirs);
      }
      case '6':{
        bool dirs[4] = {false, true, false, false};
        return new Cell(pos, dirs);
      }
      case '7':{
        bool dirs[4] = {false, false, true, true};
        return new Cell(pos, dirs);
      }
      case '8':{
        bool dirs[4] = {false, false, true, false};
        return new Cell(pos, dirs);
      }
      case '9':{
        bool dirs[4] = {false, true, true, false};
        return new Cell(pos, dirs);
      }
      case 'A':{
        bool dirs[4] = {false, true, true, true};
        return new Cell(pos, dirs);
      }
      case 'B':{
        bool dirs[4] = {true, false, true, true};
        return new Cell(pos, dirs);
      }
      case 'C':{
        bool dirs[4] = {true, true, false, true};
        return new Cell(pos, dirs);
      }
      case 'D':{
        bool dirs[4] = {true, true, true, false};
        return new Cell(pos, dirs);
      }
      case 'E':{
        bool dirs[4] = {true, true, true, true};
        return new Cell(pos, dirs);
      }
    }
    return nullptr;
  }

    Cell *maze[64];
  void setup() {
    for(int i = 0 ; i < 64 ; ++i)
    {
      maze[i] = makeCell(i);
    }

    mazeGame = MazeGame(new Player(maze, Vector(0,0)), maze);
    mazeGame.StartGame(new EndPoint(Vector(7,7)));
    irrecv.enableIRIn(); // Start the receiver
    //
    Serial.begin(9600);
    //Serial1.begin(115200);
  }


  void loop() {
    mazeGame.Update();
    Serial.write(Serial.read());
  }  
  
Tinkercad schema voor de maze puzzel