Skip to content
Advertisement

Repeating function calls

When i change a frame size, like 3×3, 4×4, 5×5 etc. canvas draw n number of times constantly calculation in progression. I can’t figure out where the error might be. Can you help me fix this bug. I suspect that the problem is in the function call in the class, or in one of the functions.

Code snippet and screenshot picture i attached

Code bug

const defaultFrame = 4;

class GeneratePage {
  constructor() {
    this.element = `
      <div class="wrapper">
          <div class="control">
                  <button type="button" class="btn btn__start"><span>Shuffle and start</span></button>
                  <button type="button" class="btn btn__stop"><span>Stop</span></button>
                  <button type="button" class="btn btn__save"><span>Save</span></button>
                  <button type="button" class="btn btn__results"><span>Results</span></button>
              </div>
              <div class="info">
                  <p class="info__moves">Move: <span class="info__step">0</span></p>
                  <p class="info__time">Time: <span class="info__timepass">00:00</span></p>
              </div>
              <div class="frame">
                  <p class="frame__title">Frame: <span class="frame__selection">4x4</span></p>
                  <div class="frame__wrapper">
                      <p class="frame__select">Choose frame size:</p>
                      <select class="frame__list" name="frames">
                          <option class="frame__option" value="3">3x3</option>
                          <option class="frame__option" value="4" selected>4x4</option>
                          <option class="frame__option" value="5">5x5</option>
                          <option class="frame__option" value="6">6x6</option>
                          <option class="frame__option" value="7">7x7</option>
                          <option class="frame__option" value="8">8x8</option>
                      </select>
                  </div>
              </div>
          </div>
      </div>
    `;
    this.generate();
  }

  generate = () => {
    document.body.innerHTML = this.element;
  };
}

class Game {
  constructor(context, cellSize, framesize) {
    this.nowstate = framesize;
    console.log(this.nowstate);
    this.list = document.querySelector('.frame__list');
    this.selection = document.querySelector('.frame__selection');
    this.color = '#008aff';

    this.context = context;
    this.cellSize = cellSize;

    this.clicks = 0;

    this.state = Game.checkSize(this.nowstate);
    this.eventHandlers();
  }

  eventHandlers = () => {
    this.list.addEventListener('change', (e) => this.changeSize(e));
  };

  changeSize = (e) => {
    e.preventDefault();
    const nowstate = e.target.value;
    this.selection.textContent = `${nowstate}x${nowstate}`;
    Game.createPuzzle(nowstate);
  };

  static getClicks() {
    return this.clicks;
  }

  static checkSize = (n) => {
    const matrix = [];
    for (let i = 0; i < n; i += 1) {
      matrix.push([]);
    }
    for (let i = 0; i < n; i += 1) {
      for (let j = 0; j < n; j += 1) {
        matrix[i][j] = n * i + j + 1;
      }
    }
    matrix[n - 1][n - 1] = 0;
    return matrix;
  };

  cellView = (x, y) => {
    this.context.fillStyle = this.color;
    this.context.fillRect(
      x + 1,
      y + 1,
      this.cellSize - 2,
      this.cellSize - 2,
    );
  };

  numView = () => {
    this.context.font = '1.8em Montserrat';
    this.context.textAlign = 'center';
    this.context.textBaseline = 'middle';
    this.context.fillStyle = '#000';
  };

  draw = () => {
    for (let i = 0; i < this.nowstate; i += 1) {
      for (let j = 0; j < this.nowstate; j += 1) {
        if (this.state[i][j] > 0) {
          this.cellView(
            j * this.cellSize,
            i * this.cellSize,
          );
          this.numView();
          this.context.fillText(
            this.state[i][j],
            j * this.cellSize + this.cellSize / 2,
            i * this.cellSize + this.cellSize / 2,
          );
        }
      }
    }
  };

  getNullCell = () => {
    for (let i = 0; i < this.nowstate; i += 1) {
      for (let j = 0; j < this.nowstate; j += 1) {
        if (this.state[j][i] === 0) {
          return { x: i, y: j };
        }
      }
    }
    return false;
  };

  move = (x, y) => {
    const nullCell = this.getNullCell();
    const canMoveVertical = (x - 1 === nullCell.x || x + 1 === nullCell.x) && y === nullCell.y;
    const canMoveHorizontal = (y - 1 === nullCell.y || y + 1 === nullCell.y) && x === nullCell.x;

    if (canMoveVertical || canMoveHorizontal) {
      this.state[nullCell.y][nullCell.x] = this.state[y][x];
      this.state[y][x] = 0;
      this.clicks += 1;
    }
  };

  victory = () => {
    const combination = this.checkSize(this.nowstate);
    let res = true;
    for (let i = 0; i < this.nowstate; i += 1) {
      for (let j = 0; j < this.nowstate; i += 1) {
        if (combination[i][j] !== this.state[i][j]) {
          res = false;
          break;
        }
      }
    }
    return res;
  };

  static getRandomBool = () => {
    if (Math.floor(Math.random() * 2) === 0) {
      return true;
    }
    return false;
  };

  mix = (count, n) => {
    let x;
    let y;
    for (let i = 0; i < count; i += 1) {
      const nullCell = this.getNullCell();

      const verticalMove = Game.getRandomBool();
      const upLeft = Game.getRandomBool();

      if (verticalMove) {
        x = nullCell.x;
        if (upLeft) {
          y = nullCell.y - 1;
        } else {
          y = nullCell.y + 1;
        }
      } else {
        y = nullCell.y;
        if (upLeft) {
          x = nullCell.x - 1;
        } else {
          x = nullCell.x + 1;
        }
      }

      if (x >= 0 && x <= n - 1 && y >= 0 && y <= n - 1) {
        this.move(x, y);
      }
    }

    this.clicks = 0;
  };

  static createPuzzle = (n) => {
    let canvas = document.getElementById('puzzle');
    if (canvas) {
      canvas.remove();
      console.log('remove');
    }
    const wrapper = document.querySelector('.wrapper');
    canvas = document.createElement('canvas');
    canvas.setAttribute('id', 'puzzle');
    canvas.classList.add('game');
    console.log(canvas);
    wrapper.insertBefore(canvas, document.querySelector('.frame'));

    // canvas = document.getElementById('puzzle');

    canvas.width = 280;
    canvas.height = 280;

    const context = canvas.getContext('2d');
    context.fillRect(0, 0, canvas.width, canvas.height);

    const cellSize = canvas.width / n;
    const game = new Game(context, cellSize, n);
    game.mix(300, n);
    game.draw();
  };
}

class Application {
  constructor() {
    new GeneratePage;
    Game.createPuzzle(defaultFrame);
  }
}

new Application();
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:rgba(0,0,0,0)}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline;-webkit-text-decoration:underline dotted currentColor;text-decoration:underline dotted currentColor}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}
@font-face{font-family:"Montserrat";src:url(fonts/Montserrat-Light.ttf) format("truetype");font-weight:300;font-style:normal;font-display:swap}@font-face{font-family:"Montserrat";src:url(fonts/Montserrat-Regular.ttf) format("truetype");font-weight:400;font-style:normal;font-display:swap}@font-face{font-family:"Montserrat";src:url(fonts/Montserrat-Medium.ttf) format("truetype");font-weight:500;font-style:normal;font-display:swap}@font-face{font-family:"Montserrat";src:url(fonts/Montserrat-Bold.ttf) format("truetype");font-weight:700;font-style:normal;font-display:swap}.btn{background-image:linear-gradient(135deg, #008aff, #86d472);border-radius:6px;box-sizing:border-box;color:#fff;display:block;height:50px;font-size:1em;font-weight:700;padding:4px;position:relative;text-decoration:none;width:7em;z-index:2;border:none;outline:none;cursor:pointer}.btn span{align-items:center;background:#0e0e10;border-radius:6px;display:flex;justify-content:center;height:100%;transition:background .5s ease;width:100%}.btn span:hover{background:rgba(0,0,0,0)}.btn:hover{color:#fff}html{scroll-behavior:smooth}*{padding:0;margin:0;box-sizing:border-box}body{font-family:"Montserrat",sans-serif;display:flex;flex-direction:column;align-items:center;padding:40px 20px 20px 20px}.wrapper{margin:0 auto;display:flex;flex-direction:column;align-items:center}.control{display:flex;flex-wrap:wrap;justify-content:center;gap:10px}.info{display:flex;gap:50px;margin-top:15px;font-weight:500;font-size:1.3rem}.game{margin-top:15px;border:1px solid #000}.frame{margin-top:15px;display:flex;flex-direction:column;align-items:center}.frame__title{font-weight:400;font-size:1.1rem}.frame__wrapper{margin-top:15px;display:flex;align-items:baseline}.frame__list{border:none;outline:none;max-width:100%;font-size:1.1rem;font-weight:400;padding:8px 10px 8px 10px;background-color:rgba(0,0,0,0);cursor:pointer}.frame__list:active,.frame__list:focus{outline:none;box-shadow:none}.frame__select{display:inline;margin-right:10px;font-size:1.1rem;font-weight:400}
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta name="description" content="gem puzzle game">
        <meta name="keywords" content="rsschool puzzle">
        <title>Gem Puzzle</title>
    </head>
    <body>
    </body>
</html>

Advertisement

Answer

Because you don’t deleting the event from frame__list.

Error

You can delete event by using EventTarget.removeEventListener()

Or

By replacing node box.replaceWith(box.cloneNode(true));

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement