:p

Relatos durante o desenvolvimento do projeto

Relatos durante o desenvolvimento do jogo da vida.

View source
2023-07-10 pt-br
javascript

Jogo da Vida

Eu não conhecia esse jogo e achei bem interessante e logo de cara tive ideias para sua implementação usando somente HTML, CSS e JavaScript. A primeira ideia foi usar como base um projeto de campo minado feito por mim também usando essas linguagens, inclusive está no meu github:

Campo Minado

O que me deu ideia de descrever essa parte do processo é os resultados que estou tendo tentando implementar a lógica das gerações.

gif demonstação

Eu sei que não está funcionando corretamente como o esperado mas oque eu achei mais interessante no resultado é a gerações de como se fossem labirintos…

No gif acima são duas abas diferentes e em alguns momentos esses “labirintos” se conectam dando um resultado legal.


class gameOfLife {
  constructor() {
    this.grid = []
    this.gridX = 10;
    this.gridY = 10;
  };

  makeGrid() {
    let arr = new Array(this.gridX);
    for (let i = 0; i < arr.length; i++) {
      arr[i] = new Array(this.gridY);
      for (let j = 0; j < arr.length; j++) {
        arr[i][j] = new cell();
      };
    };
    this.grid = arr;
  };

  checkNeighbors(x, y) {
    let Neighbors = [];
    for (let i = x - 1; i <= x + 1; i++) {
      for (let j = y - 1; j <= y + 1; j++) {
        if (i >= 0 && i < this.grid.length && j >= 0 && j < this.grid[i].length) {
          Neighbors.push(this.grid[i][j])
        }
      }
    }
    return Neighbors;
  };

  newGeneration() {
    let arr = this.grid;
    for (let i = 0; i < arr.length; i++) {
      for (let j = 0; j < arr.length; j++) {
        let cell = arr[i][j];
        let neighbors = this.checkNeighbors(i, j);
        let aliveNeighbors = neighbors.filter(neighbor => neighbor.isAlive());
        if (cell.isAlive()) {
          if (aliveNeighbors.length < 2 || aliveNeighbors.length > 3) {
            cell.makeDead();
          }
        }
        else {
          if (aliveNeighbors.length === 3) {
            cell.makeAlive();
          }
        }
      };
    };
  };

  updateGrid() {
    let arr = this.grid;
    for (let i = 0; i < arr.length; i++) {
      for (let j = 0; j < arr.length; j++) {
        let cell = arr[i][j];
        let cellElement = document.getElementById(`${i}-${j}`);
        if (cell.isAlive()) {
          cellElement.classList.remove('dead');
          cellElement.classList.add('alive');
        } else {
          cellElement.classList.remove('alive');
          cellElement.classList.add('dead');
        }
      };
    };
  };
};

Essa é a classe que estou utilizando para geração do gif acima.


1 dia depois

Finalmente!! Consegui fazer o jogo da vida funcionar como o esperado, primeira coisa que percebi foi que precisava trocar a responsabilidade de saber as celulas vizinhas para a propria celula, já que no codigo acima não estava desse jeito.

Após criar o método que me retornasse as celulas vizinhas começei a testar e ler sobre as regras do jogo, já que o meu não estava se comportando como o esperado, e após perguntar para uma inteligência artificial o porque de não estár se comportando exatamente como o esperado ela me deu a ideia de criar uma array clone e após fazer a implementação da lógica mesclar as duas arrays, e após isso, magicamente temos o jogo implementado.

// A responsabilidade de retornar as celulas vizinhas foi para a celula
checkNeighbors(cell) {
    const neighborsCell = cell.getNeighbors(this.grid);
    return neighborsCell;
  };

// Método para clonar o estado atual do jogo
  cloneGrid() {
    let arr = this.grid;
    let newArr = new Array(arr.length);
    for (let i = 0; i < arr.length; i++) {
      newArr[i] = new Array(arr[i].length);
      for (let j = 0; j < arr[i].length; j++) {
        newArr[i][j] = new cell(arr[i][j].x, arr[i][j].y);
        newArr[i][j].alive = arr[i][j].alive;
      }
    }
    return newArr;
  };

// Gerar uma nova geração
  newGeneration() {

    let arr = this.grid;
    let newArr = this.cloneGrid();

    for (let i = 0; i < arr.length; i++) {
      for (let j = 0; j < arr.length; j++) {
        let cell = arr[i][j];
        let neighbors = this.checkNeighbors(cell);
        let aliveNeighbors = neighbors.filter(neighbor => neighbor.isAlive());
        
        if (cell.isAlive()) {
          if (aliveNeighbors.length < 2 || aliveNeighbors.length > 3) {
            newArr[i][j].makeDead();
          };
        }
        else {
          if (aliveNeighbors.length === 3) {
            newArr[i][j].makeAlive();
          };
        }
      };
    };
    this.grid = newArr;
  };

gif demonstação final

No gif acima apenas troquei o tamanho do grid para 50x50.

Powered by Coffee and Music.

$>_ echo "Konami code for surprise"
“If you find that you're spending almost all your time on theory, start turning some attention to practical things; it will improve your theories. If you find that you're spending almost all your time on practice, start turning some attention to theoretical things; it will improve your practice.” —Donald Knuth