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.