> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.3-vJ3s3QN6c/rev.487
 * 
 * authors: 
 *   Thiago Claro

 * license (unless otherwise specified): 
 *   creative commons attribution-share alike 3.0 license.
 *   https://creativecommons.org/licenses/by-sa/3.0/ 
 */ 



int linhas; 
int colunas; 
int tamanho =20;
Quad[] labirinto;
ArrayList caminho;
boolean fim = false;

int atual;

void setup() {
  size(600,400);
  frameRate(120);
  linhas = floor(height / tamanho);
  colunas = floor(width / tamanho);
  labirinto = new Quad[linhas * colunas];
  caminho = new ArrayList(); 
  int cont = 0;
  for (int j = 0; j < linhas; j++)
    for (int i = 0; i < colunas; i++) {
      Quad q = new Quad(i * tamanho, j * tamanho);
      labirinto[cont++] = q;
    }
  atual = floor(cont / 2);
}

void draw() {
  
  ArrayList vizinhos = new ArrayList();
  int posX = atual % colunas;
  int posY = floor(atual / colunas);
  labirinto[atual].visitado = true;
  labirinto[atual].atual = true;
  
  //chega a vizinhança listando os não visitados
  if (posX > 0 && !labirinto[atual - 1].visitado)
    vizinhos.add(atual - 1);
  
  if (posX < colunas - 1 && !labirinto[atual + 1].visitado)
    vizinhos.add(atual + 1);
  
  if (posY < linhas - 1 && !labirinto[atual + colunas].visitado)
    vizinhos.add(atual + colunas);
  
  if (posY > 0 && !labirinto[atual - colunas].visitado)
    vizinhos.add(atual - colunas);

  //Se ainda tem vizinhos pra visitar
  if (vizinhos.size() > 0) {
      
    //sorteia um deles e vai pra lá.
    int iSort = floor(random(vizinhos.size()));
    int proximo = (int)vizinhos.get(iSort); 
    caminho.add(atual);
    
    //Descobre em que direção ele foi, pra apagar as linhas entre eles.
    if (atual == proximo - 1) {
      labirinto[atual].dir = false;
      labirinto[proximo].esq = false;
    }
    if (atual == proximo + 1) {
      labirinto[atual].esq = false;
      labirinto[proximo].dir = false;
    }
    if (atual == proximo - colunas) {
      labirinto[atual].baixo = false;
      labirinto[proximo].cima = false;
    }
    if (atual == proximo + colunas) {
      labirinto[atual].cima = false;
      labirinto[proximo].baixo = false;
    }
    
    atual = proximo;
  }
  else {
      
    //se não tem mais vizinhos, começa a voltar por onde veio  
    if (caminho.size() > 0) { 
      atual = (int)caminho.get(caminho.size() - 1);
      caminho.remove(caminho.size() -1);
    }
    else
    {
        
      //se não tem vizinhos pra visitar, nem caminho pra percorrer, é pq acabou!
      labirinto[atual].atual = false;
      fim = true;
 
    }
  }
  
  for (Quad q : labirinto) {
    q.desenhar();
  }
 
  if (fim) { 
      fill(255,255,0);
      ellipse(tamanho/ 2, tamanho/ 2, tamanho / 2, tamanho / 2 );
      fill(0,255,0);
      ellipse(width - tamanho/ 2, height - tamanho/ 2, tamanho / 2 , tamanho / 2);
  }
}

class Quad {
  int x;
  int y;
  
  boolean cima = true;
  boolean esq = true;
  boolean dir = true;
  boolean baixo = true;
  boolean atual = false;
  boolean visitado = false;
  
  Quad(int x, int y) {
    this.x = x;
    this.y = y;
  }
  
  void desenhar() {
    stroke(255);
    if (cima)
      line(x, y, x+tamanho, y);
    if (esq)
      line(x, y, x, y + tamanho);
    if (dir)
      line (x + tamanho, y, x+tamanho, y+tamanho);
    if (baixo)
      line (x, y+ tamanho,  x+tamanho, y+tamanho);
    noStroke();
    if (atual) {
      fill(255,0,0,150);
      atual = false;
    }
    else {
      if (visitado)
        fill (50,50,200);
      else
        fill (255,255,255);
    }
    rect (x + 1, y + 1, x + tamanho , y + tamanho);
  }
  
}