User prompt
fix where the ai chooses the already taken cell from the player and also make sure it works correctly so that it doesn't freeze the game
User prompt
Fix Bug: 'Timeout.tick error: forkMoveIndex is not defined' in or related to this line: 'var chosenCell = winningMoveIndex !== -1 ? winningMoveIndex : blockMoveIndex !== -1 ? blockMoveIndex : opponentForkMoveIndex !== -1 ? opponentForkMoveIndex : forkMoveIndex !== -1 ? forkMoveIndex : self.availableCells[Math.floor(Math.random() * self.availableCells.length)];' Line Number: 47
User prompt
Fix Bug: 'Timeout.tick error: winConditions is not defined' in or related to this line: 'winConditions.forEach(function (condition) {' Line Number: 18
User prompt
Fix Bug: 'Timeout.tick error: winConditions is not defined' in or related to this line: 'winConditions.forEach(function (condition) {' Line Number: 59
User prompt
improve the ai with 4 features for the ai
User prompt
make sure that the ai doesn't make a move after the player wins
User prompt
fix where the game sometimes freezes cause of the ai
User prompt
reduce the cooldown for the ai
User prompt
Fix Bug: 'Timeout.tick error: Cannot read properties of undefined (reading 'includes')' in or related to this line: 'return self.aiMoves.includes(index);' Line Number: 20
User prompt
Improve the ai more
User prompt
make a new class where if both the player and ai get a tie make it so that it flashes brown four times and then after the flashes it restarts the game
User prompt
ensure the the ai can's choose where the x shape already is make sure it chooses one of the open green cells
User prompt
fix where the ai no longer makes a choice
User prompt
the red flashes are for the game over screen not the winning. make sure when the player win make the screen flash green. and if the ai wins make sure is show the game over screen with three red flashes
User prompt
make it so that the game over screen flashes red three times
User prompt
Fix Bug: 'Timeout.tick error: Cannot read properties of undefined (reading 'taken')' in or related to this line: 'if (!grid[chosenIndex].taken) {' Line Number: 87
User prompt
Fix Bug: 'Timeout.tick error: Cannot read properties of undefined (reading 'setPlayerValue')' in or related to this line: 'grid[chosenIndex].setPlayerValue('O');' Line Number: 87
User prompt
make the ai even more smarter without the game breaking
User prompt
make sure that the ai can't choose already taken cells from the player
User prompt
fix where the ai sometimes stops choosing and letting the player win
User prompt
add the decide call event in order to execute the decision making event
User prompt
implement a decision class and logic events to make the ai decide where to choose
User prompt
implement a way for the ai to observe the player's gamepplay
User prompt
make it so that the ai starts working
User prompt
Fix Bug: 'Timeout.tick error: Cannot set properties of undefined (setting 'value')' in or related to this line: 'newGrid[moveIndex].value = player;' Line Number: 164
/****
* Classes
****/
// Define the Cell class for the tic tac toe grid
var Cell = Container.expand(function (x, y, index) {
var self = Container.call(this);
self.index = index;
self.taken = false;
self.value = null;
var cellGraphics = self.attachAsset('cell', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = x;
self.y = y;
self.interactive = true;
self.on('down', function () {
if (!self.taken && !game.aiTurn) {
self.setPlayerValue('X');
game.checkGameState();
if (!game.gameOver) {
game.aiTurn = true;
game.aiPlay();
}
}
});
self.setPlayerValue = function (value) {
self.taken = true;
self.value = value;
var shape = value === 'X' ? 'xShape' : 'oShape';
var color = value === 'X' ? 0xFF0000 : 0x0000FF;
var playerShape = self.attachAsset(shape, {
anchorX: 0.5,
anchorY: 0.5,
color: color
});
};
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000 // Init game with black background
});
/****
* Game Code
****/
// Define the assets for the tic tac toe game
var grid = [];
// Initialize the tic tac toe grid
function initializeGrid() {
var gridSize = 3;
var cellSize = 200;
var startX = (2048 - gridSize * cellSize) / 2 + cellSize / 2;
var startY = (2732 - gridSize * cellSize) / 2 + cellSize / 2;
for (var i = 0; i < gridSize; i++) {
for (var j = 0; j < gridSize; j++) {
var index = i * gridSize + j;
var cell = new Cell(startX + j * cellSize, startY + i * cellSize, index);
game.addChild(cell);
grid.push(cell);
}
}
}
initializeGrid();
// Define game logic
game.aiTurn = false;
game.aiCooldown = 1000; // Cooldown time in milliseconds
game.gameOver = false;
game.checkGameState = function () {
// Check for win conditions
var winConditions = [[0, 1, 2], [3, 4, 5], [6, 7, 8],
// Rows
[0, 3, 6], [1, 4, 7], [2, 5, 8],
// Columns
[0, 4, 8], [2, 4, 6] // Diagonals
];
for (var i = 0; i < winConditions.length; i++) {
var condition = winConditions[i];
if (grid[condition[0]].value && grid[condition[0]].value === grid[condition[1]].value && grid[condition[0]].value === grid[condition[2]].value) {
game.gameOver = true;
LK.effects.flashScreen(0x00FF00, 1000);
var winner = grid[condition[0]].value === 'X' ? 'You Win!' : 'AI Wins!';
var winText = new Text2(winner, {
size: 150,
fill: "#ffffff"
});
winText.anchor.set(0.5, 0.5);
winText.x = 2048 / 2;
winText.y = 2732 / 2;
LK.gui.center.addChild(winText);
if (grid[condition[0]].value === 'O') {
LK.showGameOver();
} else {
LK.setTimeout(function () {
grid.forEach(function (cell) {
cell.destroy();
});
grid = [];
game.aiTurn = false; // Reset AI turn state
game.gameOver = false; // Reset game over state
initializeGrid();
}, 2000);
}
return;
}
}
// Check for draw
var draw = grid.every(function (cell) {
return cell.taken;
});
if (draw) {
game.gameOver = true;
LK.effects.flashScreen(0x000000, 1000);
game.aiTurn = false; // Reset AI turn state
game.gameOver = false; // Reset game over state
LK.showGameOver();
}
};
game.aiPlay = function () {
if (game.aiTurn) {
LK.setTimeout(function () {
var bestMove = minimax(grid, 'O').index;
if (bestMove !== undefined) {
grid[bestMove].setPlayerValue('O');
}
game.aiTurn = false;
game.checkGameState();
}, game.aiCooldown);
}
};
function minimax(newGrid, player) {
var availableCells = newGrid.map(function (cell) {
return {
index: cell.index,
taken: cell.taken,
value: cell.value
};
}).filter(function (cell) {
return !cell.taken;
});
if (checkWin(newGrid, 'X')) {
return {
score: -10
};
} else if (checkWin(newGrid, 'O')) {
return {
score: 10
};
} else if (availableCells.length === 0) {
return {
score: 0
};
}
var moves = [];
for (var i = 0; i < availableCells.length; i++) {
var move = {};
move.index = newGrid.indexOf(availableCells[i]);
var moveIndex = newGrid.findIndex(function (cell) {
return cell.index === move.index;
});
if (moveIndex !== -1) {
newGrid[moveIndex].value = player;
}
if (player == 'O') {
var result = minimax(newGrid, 'X');
move.score = result.score;
} else {
var result = minimax(newGrid, 'O');
move.score = result.score;
}
newGrid[move.index].value = null;
moves.push(move);
}
var bestMove;
if (player === 'O') {
var bestScore = -Infinity;
for (var i = 0; i < moves.length; i++) {
if (moves[i].score > bestScore) {
bestScore = moves[i].score;
bestMove = i;
}
}
} else {
var bestScore = Infinity;
for (var i = 0; i < moves.length; i++) {
if (moves[i].score < bestScore) {
bestScore = moves[i].score;
bestMove = i;
}
}
}
return moves[bestMove];
}
function checkWin(grid, player) {
var winConditions = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6]];
for (var i = 0; i < winConditions.length; i++) {
var condition = winConditions[i];
if (grid[condition[0]].value == player && grid[condition[1]].value == player && grid[condition[2]].value == player) {
return true;
}
}
return false;
}
// Start the game with the player's turn
game.aiTurn = false;