ги, поки грав в гру, то в голову прийшла думка, як ту штуку оптимізувати. 
Що ми робимо:
 стаємо в якусь рандомну клітинку. Додаємо цю клітинку в "стек". Потім шукаємо по сторонам (діагональ не включається) такі клітинки, в котрих ми ще не були. Тобто, такі клітинки, котрих немає в "стеку".
Коли знайшли таку клітинку, то відкриваємо дверцята, що між поточною і знайденою клітинками, після чого позначаємо знайдену клітинку як поточну і додаємо її в "стек".
Якщо ми зайшли в куток, в котрому немає сусідніх клітинок, котрі, також, не знаходяться в "стеку", то ми витягуємо з стеку клітинки, починаючи з самої останньої, котру додали, і робимо її поточною, після чого знову шукаємо потрібну нам клітинку, якщо не знаходимо, то знову витягаємо зі "стеку" клітинку. Тобто, рухаємося назад.
Проблема:
якщо ми спочатку зайдемо в кут, в котрому не буде потрібних клітинок, то остання клітинка, котру ми додали, залишається в "стеку". Далі ми рухаємось назад, знаходимо потрібні клітинки, котрі також додаємо в "стек", після чого можемо знову зайти в глухий кут, і почати хід назад. Але коли ми проходимо ту кількість кроків, котра дорівнює кількості доданих клітинок, після того, як ми пішли назад, з попереднього глухого кута, то ми автоматом перецибуємо в ту клітинку, котру ми додали в "останньою", перед тим, як піти назад.
Озьдо я схематично намалював

Коли голівка повертається після 20 кроку, вона робить 4 кроки назад. Воно проходить 4 клітинки, котрі ми щойно додали в стек, після чого воно бере наступну клітинку зі стеку, індекс котрої на одиницю менший, і потрапляє в не ту, що треба, клітинку, на 25 кроці.  А мало б зайти в клітинку, що позначена кроком 13 та 16.
Спочатку я намутив хтозна-що з усілякими індексами і т.д. А потім просто зрозумів, що після "руху назад", нові клітинки треба додавати в стек не на самий верх, чи низ, а запихувати її на той індекс, котрий ми отримаємо, якщо відняти від максимального індексу кількість кроків, котрі ми пройшли "назад". Тоді індекси клітинок, котрі ми додали перед тим, як зайти в глухий кут, залишаться ”зверху” стека, і ми не зайдемо в ті клітинки, коли будемо рухатись назад.
Коротше кажучи, треба було просто створити змінну для поточного індексу, і при додаванні нової клітинки інкрементувати той індекс, а при "русі назад" зменшувати на 1.
хоча я помітив, що воно знову якось трохи не так робе
Озьдо лайнокід, включно з закоментованим ще більшим лайнокодом.
Мова - Java, середовище розробки - Processing, можете запустити та погратись
class Stack<T>
{
  private ArrayList<T> items;
  private int back=0;
  public int addInARow=0;
  public int backStart=0;
  public int currentIndex=0;
  
  public Stack()
  {
    items = new ArrayList<T>();
  }
  
  public void Push(T item)
  {
    items.add(currentIndex, item);
    currentIndex++;
    
   /* if(back>0){
      backStart=items.size()-back-1;
      back=0;
      addInARow=0;
      
     // println("remembered index: "+backStart+"  "+((int[])items.get(backStart))[0]+" "+((int[])items.get(backStart))[1]);
    }
    addInARow++;*/
    
  }
  
  public T Pop()
  {
    /*if(items.size()>0)
    {
      T result;
      int index = items.size()-1-back;
      back++;
      if(back-1==addInARow)
      {
       // println("oh yah! popping: "+backStart+"  back: "+back+" addInARow: "+addInARow);
        result = items.get(backStart);
        back = items.size()-backStart;
      }
      else
      {
       // println("popping: "+index+"  "+((int[])items.get(index))[0]+" "+((int[])items.get(index))[1]);
        result = items.get(index);
      }
      //items.remove(items.size()-1);
      return result;
    }
    return null;*/
    currentIndex--;
    if(currentIndex<0)
      currentIndex=0;
    return items.get(currentIndex);
  }
  
  public boolean Exists(int[] item)
  {
    for(int i =0; i<items.size(); i++)
    {
      int[] it = (int[])items.get(i);
      if(it[0]==item[0] && it[1] == item[1])
      {
        return true;
      }
    }
    return false;
  }
}
class Maze
{
  
  public int ww, wl, w, h, xOffset, yOffset; //ww - wall width, wl - wall length, w  - width, h - height
  
  class Room
  {
    class Wall
    {
      public boolean state;
    }
    
    public String visited=" ";
    
    public Room ()
    {
      top=new Wall();
      right=new Wall();
      bottom = new Wall();
      left = new Wall();
    }
    
    public Wall top, right, bottom, left;
  }
  
  private Room[][] rooms;
  
  public Maze(int roomX, int roomY, int wallWidth, int wallLength, int xOffset, int yOffset)
  {
    w=roomX;
    h=roomY;
    ww = wallWidth;
    wl = wallLength;
    this.xOffset = xOffset;
    this.yOffset = yOffset;
    
    rooms = new Room[roomX][roomY];
        
    for(int i =0; i<roomX; i++)
    {
      for(int j = 0; j<roomY; j++)
      {
        rooms[i][j]=new Room();
        if(i>0)
        {
          rooms[i][j].left = rooms[i-1][j].right;
        }
        if(j>0)
        {
          rooms[i][j].top = rooms[i][j-1].bottom;
        }
      }
    }
    
   /* rooms[roomX/2-1][roomY/2-1].right.state=true;
    rooms[roomX/2][roomY/2-1].bottom.state=true;
    rooms[roomX/2][roomY/2].left.state=true;
    rooms[roomX/2-1][roomY/2].top.state=true;*/
  }
  
  public void OpenRoom(int fromX, int fromY, int toX, int toY)
  {
    int x = toX-fromX;
    int y = toY-fromY;
    
    if(x==1)
    {
      rooms[fromX][fromY].right.state = true;
    } else
    if(x==-1)
    {
      rooms[fromX][fromY].left.state = true;
    } else
    if(y==1)
    {
      rooms[fromX][fromY].bottom.state = true;
    } else
    if(y==-1)
    {
      rooms[fromX][fromY].top.state = true;
    }
  }
  
  public void Draw()
  {    
    int i=0, j=0;
    
    int xstep = (wl+ww);
    int ystep =(wl+ww); //<>//
    
    for(i = 0; i<w; i++)
    {
      for(j = 0; j<h; j++)
      {
        stroke(100);
        strokeWeight(ww);
        
       // println("i: "+i+" j: "+j +"  rooms[0].length: "+rooms[0].length+"  rooms[1].length: "+rooms[1].length);
        
        Room room = rooms[i][j];
        
        textSize(15);
        String text = room.visited;
        fill(0, 0, 0, 250);
        text(text, xOffset+i*xstep+6/max(text.length(),1), yOffset+j*ystep+12); 
        
        if(room.top.state==false)
        {
          line(xOffset+i*xstep, yOffset+j*ystep, xOffset+i*xstep+wl, yOffset+j*ystep);
        }
        if(room.right.state==false)
        {
          line(xOffset+i*xstep+wl+ww, yOffset+j*ystep, xOffset+i*xstep+wl+ww, yOffset+j*ystep+wl);
        }
        if(room.bottom.state==false)
        {
          line(xOffset+i*xstep, yOffset+j*ystep+wl+ww, xOffset+i*xstep+wl, yOffset+j*ystep+wl+ww);
        }
        if(room.left.state==false)
        {
          line(xOffset+i*xstep, yOffset+j*ystep, xOffset+i*xstep, yOffset+j*ystep+wl);
        }
      }
    }
  }
}
Maze maze;
void setup()
{
  size(800, 800);
  background(233,216,185);
  
  maze= new Maze(10, 10, 5, 30, 50, 50);
  stack = new Stack<int[]>();
  initX = (int)random(0,maze.w);
  initY = (int)random(0,maze.h);
  currX=initX; currY=initY;
  numVisit=1;
  
  oldCx=0; oldCy=0;
  stack.Push(new int[]{initX, initY});
  
  //MakePath();
  
  maze.Draw();
  
}
boolean wait=true, canGo=false;
int value=-1;
void draw()
{   
 /* fill(value);
  if(wait)
  {
   // delay(5000);
    wait=false;
  }*/
  
  //if(canGo)
  {
    //canGo=false;
    clear();
    background(233,216,185);
    MakePath();
    maze.Draw();
  }
  delay(200);
}
void keyPressed() {
 canGo=true;
}
Stack<int[]> stack;
int initX;
int initY;
int currX, currY;
int numVisit;
int oldCx, oldCy;
void MakePath()
{
 // for(int i =0; i<200; i++){
  
   // println("curr X: "+currX+"  curr Y: "+currY);
    
   // while(true){    
    int tempX = 0;
    int tempY = 0;
  
    boolean found=false;
  
    ArrayList<int[]> ways = new ArrayList<int[]>();
    
    if(currX>0 && !stack.Exists(new int[]{currX-1, currY}))
    {
      ways.add(new int[]{-1,0});
    }
    if(currX<maze.w-1 && !stack.Exists(new int[]{currX+1, currY}))
    {
      ways.add(new int[]{1,0});
    }
    if(currY>0 && !stack.Exists(new int[]{currX, currY-1}))
    {
      ways.add(new int[]{0,-1});
    }
    if(currY<maze.h-1 && !stack.Exists(new int[]{currX, currY+1}))
    {
      ways.add(new int[]{0,1});
    }
    
    int index = -1;
    index = (int)random(0, ways.size());
    if(ways.size()>0)
    {
      tempX = currX + ways.get(index)[0];
      tempY = currY + ways.get(index)[1];
      
      found=true;
    }
    
   
   /* for(int x =-1; x<2; x++)
    {
      for(int y = -1; y<2; y++)
      {
        if(x!=0 && y!=0){
          continue;
        }
          
        tempX = x+currX;
        tempY = y+currY;
        
        if(tempX>=0 && tempX<maze.w && 
          tempY>=0 && tempY<maze.h &&
          !stack.Exists(new int[]{tempX, tempY}))
        {
          found=true;
          println("found: "+tempX+"  "+tempY);
          break;
        }
      }
      if(found)
        break;
    }*/
    
    if(!found)
    {
      if(currX==initX && currY ==initY){
       // println("end");
        return;
      }
      else
      {
        int[] back = stack.Pop();
        if(back==null)
        {
         // println("end #2");
          return;
        }
        else
        {
         // println("back: "+back[0]+" "+back[1]);
        }
        currX = back[0];
        currY = back[1];
        
       // println("\t\t\tpop: "+currX+"  "+currY+" add in a row: "+stack.addInARow+"  back: "+stack.back);
        maze.rooms[oldCx][oldCy].visited = "";
        maze.rooms[currX][currY].visited = "+";
        oldCx = currX;
        oldCy = currY;
        
        if(currX==initX && currY ==initY){
         // println("end");
          return;
        }
      }
    }
    else
    {
      maze.OpenRoom(currX, currY, tempX, tempY);
      currX = tempX;
      currY = tempY;
      
      maze.rooms[oldCx][oldCy].visited = "";
      maze.rooms[currX][currY].visited = "+";
      oldCx = currX;
      oldCy = currY;
      
      //println("\t\t\tpush: "+currX+"  "+currY+" add in a row: "+stack.addInARow+"  back: "+stack.back);
      stack.Push(new int[]{currX, currY});
    }
    //}
 // } 
}