0

I am tring to make an ai to complete the 2048 game. I have the game made, but I'm on the first step of adding the ai in JavaScript and I've run into a problem. The game looks OK before anything is clicked, the left, and right keys work fine but the up and down keys both cause the game to display undefined in the squares on the grid that should display a number. I have no idea why this is happening I've looked at everything but I've had no luck here is my code:

document.addEventListener('DOMContentLoaded', () => {
  const gridDisplay = document.querySelector('.grid');
  const scoreDisplay = document.getElementById('score');
  const resultDisplay = document.getElementById('result');
  let squares = [];
  const width = 4;
  let score = 0;

  // Initialize the game state
  const gameState = {
    grid: [],
    score: 0,
  };

  // Create the playing board
  function createBoard() {
    for (let i = 0; i < width * width; i++) {
      const square = document.createElement('div');
      square.innerHTML = 0;
      gridDisplay.appendChild(square);
      squares.push(square);
    }
    createInitialState(); // Create the initial game state
    addColours();
  }
  createBoard();

  // Generate a new number for the game state
  function generateGameState() {
    const emptyCells = [];
    for (let i = 0; i < gameState.grid.length; i++) {
      if (gameState.grid[i] === 0) {
        emptyCells.push(i);
      }
    }
    if (emptyCells.length > 0) {
      const randomIndex = emptyCells[Math.floor(Math.random() * emptyCells.length)];
      gameState.grid[randomIndex] = Math.random() < 0.9 ? 2 : 4; // 90% chance of 2, 10% chance of 4
    }
  }

  // Create the initial game state
  function createInitialState() {
    for (let i = 0; i < width * width; i++) {
      gameState.grid.push(0);
    }
    generate();
    generate();
  }

  // Generate a new number in an empty cell
  function generate() {
    const emptyCells = [];
    for (let i = 0; i < gameState.grid.length; i++) {
      if (gameState.grid[i] === 0) {
        emptyCells.push(i);
      }
    }
    if (emptyCells.length > 0) {
      const randomIndex = emptyCells[Math.floor(Math.random() * emptyCells.length)];
      gameState.grid[randomIndex] = Math.random() < 0.9 ? 2 : 4; // 90% chance of 2, 10% chance of 4
      addColours();
    }
  }

  function moveRight() {
    for (let i = 0; i < width * width; i += width) {
      const row = gameState.grid.slice(i, i + width);
      const newRow = moveArrayRight(row);
      for (let j = 0; j < width; j++) {
        gameState.grid[i + j] = newRow[j];
      }
    }
    generate();
    addColours();
  }

  function moveArrayRight(arr) {
    const nonZeroValues = arr.filter(num => num !== 0);
    const zeros = Array(width - nonZeroValues.length).fill(0);
    const newRow = zeros.concat(nonZeroValues);
    return newRow;
  }

  function moveLeft() {
    for (let i = 0; i < width * width; i += width) {
      const row = gameState.grid.slice(i, i + width);
      const newRow = moveArrayLeft(row);
      for (let j = 0; j < width; j++) {
        gameState.grid[i + j] = newRow[j];
      }
    }
    generate();
    addColours();
  }

  function moveArrayLeft(arr) {
    const nonZeroValues = arr.filter(num => num !== 0);
    const zeros = Array(width - nonZeroValues.length).fill(0);
    const newRow = nonZeroValues.concat(zeros);
    return newRow;
  }

  function moveUp() {
    for (let i = 0; i < width; i++) {
      const column = [];
      for (let j = i; j < width * width; j += width) {
        column.push(gameState.grid[j]);
      }

      const newColumn = moveArrayUp(column); // Use moveArrayUp function

      for (let j = i; j < width * width; j += width) {
        gameState.grid[j] = newColumn[j / width];
      }
    }
    generate();
    addColours();
  }

  function moveDown() {
    for (let i = 0; i < width; i++) {
      const column = [];
      for (let j = width * (width - 1) + i; j >= i; j -= width) {
        column.push(gameState.grid[j]);
      }
      const newColumn = moveArrayDown(column); // Use moveArrayDown function

      for (let j = width * (width - 1) + i; j >= i; j -= width) {
        gameState.grid[j] = newColumn[(width * width - j - 1) / width];
      }
    }
    generate();
    addColours();
  }

  function moveArrayUp(arr) {
    const nonZeroValues = arr.filter(num => num !== 0);
    const zeros = Array(width - nonZeroValues.length).fill(0);
    const newColumn = nonZeroValues.concat(zeros);
    return newColumn;
  }

  function moveArrayDown(arr) {
    const nonZeroValues = arr.filter(num => num !== 0);
    const zeros = Array(width - nonZeroValues.length).fill(0);
    const newColumn = zeros.concat(nonZeroValues);
    return newColumn;
  }

  function combineRow() {
    for (let i = 0; i < 15; i++) {
      if (squares[i].innerHTML === squares[i + 1].innerHTML) {
        let combinedTotal = parseInt(squares[i].innerHTML) + parseInt(squares[i + 1].innerHTML)
        squares[i].innerHTML = combinedTotal
        squares[i + 1].innerHTML = 0
        score += combinedTotal
        scoreDisplay.innerHTML = score
      }
    }
    checkForWin()
  }

  function combineColumn() {
    for (let i = 0; i < 12; i++) {
      if (squares[i].innerHTML === squares[i + width].innerHTML) {
        let combinedTotal = parseInt(squares[i].innerHTML) + parseInt(squares[i + width].innerHTML)
        squares[i].innerHTML = combinedTotal
        squares[i + width].innerHTML = 0
        score += combinedTotal
        scoreDisplay.innerHTML = score
      }
    }
    checkForWin()
  }

  //assign functions to keyCodes
  function control(e) {
    if (e.keyCode === 37) {
      keyLeft()
    } else if (e.keyCode === 38) {
      keyUp()
    } else if (e.keyCode === 39) {
      keyRight()
    } else if (e.keyCode === 40) {
      keyDown()
    }
  }
  document.addEventListener('keyup', control)

  function keyRight() {
    moveRight()
    combineRow()
    moveRight()
    generate()
  }

  function keyLeft() {
    moveLeft()
    combineRow()
    moveLeft()
    generate()
  }

  function keyUp() {
    moveUp()
    combineColumn()
    moveUp()
    generate()
  }

  function keyDown() {
    moveDown()
    combineColumn()
    moveDown()
    generate()
  }

  // Example usage:
  createInitialState(); // Initialize the game state

  //check for the number 2048 in the squares to win
  function checkForWin() {
    for (let i = 0; i < squares.length; i++) {
      if (squares[i].innerHTML == 2048) {
        resultDisplay.innerHTML = 'You WIN'
        document.removeEventListener('keyup', control)
        setTimeout(() => clear(), 3000)
      }
    }
  }

  //check if there are no zeros on the board to lose
  function checkForGameOver() {
    let zeros = 0
    for (let i = 0; i < squares.length; i++) {
      if (squares[i].innerHTML == 0) {
        zeros++
      }
    }
    if (zeros === 0) {
      resultDisplay.innerHTML = 'You LOSE'
      document.removeEventListener('keyup', control)
      setTimeout(() => clear(), 3000)
    }
  }

  //clear timer
  function clear() {
    clearInterval(myTimer)
  }


  //add colours
  function addColours() {
    for (let i = 0; i < squares.length; i++) {
      const row = Math.floor(i / width);
      const col = i % width;
      const value = gameState.grid[row * width + col];

      squares[i].innerHTML = value;

      if (value === 0) squares[i].style.backgroundColor = '#afa192';
      else if (value === 2) squares[i].style.backgroundColor = '#eee4da';
      else if (value === 4) squares[i].style.backgroundColor = '#ede0c8';
      else if (value === 8) squares[i].style.backgroundColor = '#f2b179';
      else if (value === 16) squares[i].style.backgroundColor = '#ffcea4';
      else if (value === 32) squares[i].style.backgroundColor = '#e8c064';
      else if (value === 64) squares[i].style.backgroundColor = '#ffab6e';
      else if (value === 128) squares[i].style.backgroundColor = '#fd9982';
      else if (value === 256) squares[i].style.backgroundColor = '#ead79c';
      else if (value === 512) squares[i].style.backgroundColor = '#76daff';
      else if (value === 1024) squares[i].style.backgroundColor = '#beeaa5';
      else if (value === 2048) squares[i].style.backgroundColor = '#d7d4f0';
    }
  }
  addColours()

  var myTimer = setInterval(addColours, 50)

});
body {
  background-color: #faf8ef;
  display: flex;
  justify-content: center;
  font-family: "Clear Sans", "Helvetica Neue";
}

h1 {
  font-size: 80px;
  line-height: 0.7;
  color: #776E65;
  margin: 0px;
}

.container {
  width: 468px;
  margin-top: 10px;
}

.info {
  display: flex;
  justify-content: space-between;
  margin-bottom: 20px;
}

.grid {
  display: flex;
  flex-wrap: wrap;
  width: 456px;
  height: 456px;
  background-color: #BBADA0;
  border: 7px solid #BBADA0;
  border-radius: 6px;
  margin-top: 20px;
}

.grid div {
  width: 100px;
  height: 100px;
  margin: 7px;
  border-radius: 3px;
  background-color: #EEE4DA;
  color: #afa192;
  font-weight: bold;
  text-align: center;
  font-size: 60px;
  line-height: 1.6;
}

.score-container {
  text-align: center;
  width: 70px;
  height: 60px;
  border-radius: 3px;
  background-color: #8f7a66;
  color: #FFFFFF;
}

#score {
  font-size: 30px;
}

.score-title {
  font-size: 16px;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">

<head>
  <meta charset="utf-8">
  <title>2048 Game Online</title>
  <link rel="stylesheet" href="2408 styling.css">
  <script src="2408 scripting.js" charset="utf-8"></script>
</head>

<body>
  <div class="container">
    <div class="info">
      <h1>2048</h1>
      <div class="score-container">
        <div class="score-title">score</div>
        <span id="score">0</span>
      </div>
    </div>
    <span id="result">Join the numbers and get to the <b>2048</b> tile!</span>
    <div class="grid"></div>
  </div>
  </div>
</body>

</html>

I know the code is long but I know that a problem could be anywhere when coding.

VLAZ
  • 26,331
  • 9
  • 49
  • 67
  • 3
    [How to debug small programs](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) and [What is a debugger and how can it help me diagnose problems?](https://stackoverflow.com/q/25385173) – VLAZ Aug 20 '23 at 19:25
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. – Community Aug 22 '23 at 12:57

0 Answers0