/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Cell = Container.expand(function (row, col) {
var self = Container.call(this);
self.row = row;
self.col = col;
self.value = 0; // 0 = empty, 1 = X, 2 = O
var background = self.attachAsset('cellBackground', {
anchorX: 0.5,
anchorY: 0.5
});
var symbol = null;
self.placeSymbol = function (playerSymbol) {
if (self.value !== 0) return false;
self.value = playerSymbol;
if (playerSymbol === 1) {
symbol = self.attachAsset('xSymbol', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0,
scaleY: 0
});
} else {
symbol = self.attachAsset('oSymbol', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0,
scaleY: 0
});
}
tween(symbol, {
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.elasticOut
});
LK.getSound('placeSymbol').play();
return true;
};
self.down = function (x, y, obj) {
if (gameState === 'playing' && currentPlayer === 1 && self.value === 0) {
if (self.placeSymbol(1)) {
currentPlayer = 2;
checkGameEnd();
if (gameState === 'playing') {
LK.setTimeout(function () {
aiMove();
}, 500);
}
}
}
};
return self;
});
var GameBoard = Container.expand(function () {
var self = Container.call(this);
self.cells = [];
self.winLine = null;
// Create 3x3 grid
for (var row = 0; row < 3; row++) {
self.cells[row] = [];
for (var col = 0; col < 3; col++) {
var cell = new Cell(row, col);
cell.x = (col - 1) * 220;
cell.y = (row - 1) * 220;
self.cells[row][col] = cell;
self.addChild(cell);
}
}
// Create grid lines
// Vertical lines
for (var i = 0; i < 2; i++) {
var vLine = self.attachAsset('gridLine', {
anchorX: 0.5,
anchorY: 0.5,
x: (i - 0.5) * 220,
y: 0
});
}
// Horizontal lines
for (var i = 0; i < 2; i++) {
var hLine = self.attachAsset('gridLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: (i - 0.5) * 220,
rotation: Math.PI / 2
});
}
self.getCell = function (row, col) {
return self.cells[row][col];
};
self.getBoardState = function () {
var state = [];
for (var row = 0; row < 3; row++) {
state[row] = [];
for (var col = 0; col < 3; col++) {
state[row][col] = self.cells[row][col].value;
}
}
return state;
};
self.checkWin = function (player) {
var board = self.getBoardState();
// Check rows
for (var row = 0; row < 3; row++) {
if (board[row][0] === player && board[row][1] === player && board[row][2] === player) {
return {
type: 'row',
index: row
};
}
}
// Check columns
for (var col = 0; col < 3; col++) {
if (board[0][col] === player && board[1][col] === player && board[2][col] === player) {
return {
type: 'col',
index: col
};
}
}
// Check diagonals
if (board[0][0] === player && board[1][1] === player && board[2][2] === player) {
return {
type: 'diag',
index: 0
};
}
if (board[0][2] === player && board[1][1] === player && board[2][0] === player) {
return {
type: 'diag',
index: 1
};
}
return null;
};
self.isBoardFull = function () {
var board = self.getBoardState();
for (var row = 0; row < 3; row++) {
for (var col = 0; col < 3; col++) {
if (board[row][col] === 0) return false;
}
}
return true;
};
self.showWinLine = function (winInfo) {
self.winLine = self.attachAsset('winLine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0,
alpha: 0.8
});
if (winInfo.type === 'row') {
self.winLine.x = 0;
self.winLine.y = (winInfo.index - 1) * 220;
self.winLine.rotation = 0;
} else if (winInfo.type === 'col') {
self.winLine.x = (winInfo.index - 1) * 220;
self.winLine.y = 0;
self.winLine.rotation = Math.PI / 2;
} else if (winInfo.type === 'diag') {
self.winLine.x = 0;
self.winLine.y = 0;
if (winInfo.index === 0) {
self.winLine.rotation = Math.PI / 4;
self.winLine.width = 650;
} else {
self.winLine.rotation = -Math.PI / 4;
self.winLine.width = 650;
}
}
tween(self.winLine, {
scaleX: 1
}, {
duration: 500,
easing: tween.easeOut
});
};
self.reset = function () {
for (var row = 0; row < 3; row++) {
for (var col = 0; col < 3; col++) {
var cell = self.cells[row][col];
cell.value = 0;
if (cell.children.length > 1) {
cell.removeChild(cell.children[cell.children.length - 1]);
}
}
}
if (self.winLine) {
self.removeChild(self.winLine);
self.winLine = null;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xF5F5F5
});
/****
* Game Code
****/
var gameBoard = null;
var gameState = 'playing'; // 'playing', 'won', 'lost', 'draw'
var currentPlayer = 1; // 1 = X (human), 2 = O (AI)
// Score tracking
var wins = storage.wins || 0;
var losses = storage.losses || 0;
var draws = storage.draws || 0;
// UI Elements
var statusText = new Text2('Your Turn (X)', {
size: 80,
fill: 0x333333
});
statusText.anchor.set(0.5, 0);
LK.gui.top.addChild(statusText);
statusText.y = 150;
var scoreText = new Text2('Wins: ' + wins + ' | Losses: ' + losses + ' | Draws: ' + draws, {
size: 50,
fill: 0x666666
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
scoreText.y = 250;
var restartButton = new Text2('Play Again', {
size: 60,
fill: 0x4CAF50
});
restartButton.anchor.set(0.5, 1);
LK.gui.bottom.addChild(restartButton);
restartButton.y = -100;
restartButton.alpha = 0;
// Initialize game board
gameBoard = new GameBoard();
gameBoard.x = 2048 / 2;
gameBoard.y = 2732 / 2;
game.addChild(gameBoard);
function checkGameEnd() {
var playerWin = gameBoard.checkWin(1);
var aiWin = gameBoard.checkWin(2);
if (playerWin) {
gameState = 'won';
statusText.setText('You Win!');
gameBoard.showWinLine(playerWin);
wins++;
storage.wins = wins;
LK.getSound('gameWin').play();
showRestartButton();
} else if (aiWin) {
gameState = 'lost';
statusText.setText('AI Wins!');
gameBoard.showWinLine(aiWin);
losses++;
storage.losses = losses;
LK.getSound('gameLose').play();
showRestartButton();
} else if (gameBoard.isBoardFull()) {
gameState = 'draw';
statusText.setText('Draw!');
draws++;
storage.draws = draws;
LK.getSound('gameDraw').play();
showRestartButton();
}
if (gameState !== 'playing') {
scoreText.setText('Wins: ' + wins + ' | Losses: ' + losses + ' | Draws: ' + draws);
}
}
function showRestartButton() {
tween(restartButton, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
}
function minimax(board, depth, isMaximizing) {
var aiWin = checkWinOnBoard(board, 2);
var playerWin = checkWinOnBoard(board, 1);
if (aiWin) return 10 - depth;
if (playerWin) return depth - 10;
if (isBoardFullArray(board)) return 0;
if (isMaximizing) {
var bestScore = -1000;
for (var row = 0; row < 3; row++) {
for (var col = 0; col < 3; col++) {
if (board[row][col] === 0) {
board[row][col] = 2;
var score = minimax(board, depth + 1, false);
board[row][col] = 0;
if (score > bestScore) {
bestScore = score;
}
}
}
}
return bestScore;
} else {
var bestScore = 1000;
for (var row = 0; row < 3; row++) {
for (var col = 0; col < 3; col++) {
if (board[row][col] === 0) {
board[row][col] = 1;
var score = minimax(board, depth + 1, true);
board[row][col] = 0;
if (score < bestScore) {
bestScore = score;
}
}
}
}
return bestScore;
}
}
function checkWinOnBoard(board, player) {
// Check rows
for (var row = 0; row < 3; row++) {
if (board[row][0] === player && board[row][1] === player && board[row][2] === player) {
return true;
}
}
// Check columns
for (var col = 0; col < 3; col++) {
if (board[0][col] === player && board[1][col] === player && board[2][col] === player) {
return true;
}
}
// Check diagonals
if (board[0][0] === player && board[1][1] === player && board[2][2] === player) {
return true;
}
if (board[0][2] === player && board[1][1] === player && board[2][0] === player) {
return true;
}
return false;
}
function isBoardFullArray(board) {
for (var row = 0; row < 3; row++) {
for (var col = 0; col < 3; col++) {
if (board[row][col] === 0) return false;
}
}
return true;
}
function aiMove() {
if (gameState !== 'playing' || currentPlayer !== 2) return;
var board = gameBoard.getBoardState();
var bestScore = -1000;
var bestMove = null;
for (var row = 0; row < 3; row++) {
for (var col = 0; col < 3; col++) {
if (board[row][col] === 0) {
board[row][col] = 2;
var score = minimax(board, 0, false);
board[row][col] = 0;
if (score > bestScore) {
bestScore = score;
bestMove = {
row: row,
col: col
};
}
}
}
}
if (bestMove) {
var cell = gameBoard.getCell(bestMove.row, bestMove.col);
cell.placeSymbol(2);
currentPlayer = 1;
checkGameEnd();
if (gameState === 'playing') {
statusText.setText('Your Turn (X)');
}
}
}
function resetGame() {
gameBoard.reset();
gameState = 'playing';
currentPlayer = 1;
statusText.setText('Your Turn (X)');
tween(restartButton, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn
});
}
restartButton.down = function (x, y, obj) {
if (gameState !== 'playing') {
resetGame();
}
};
game.update = function () {
if (gameState === 'playing' && currentPlayer === 1) {
statusText.setText('Your Turn (X)');
} else if (gameState === 'playing' && currentPlayer === 2) {
statusText.setText('AI Turn (O)');
}
}; ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,412 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1");
+
+/****
+* Classes
+****/
+var Cell = Container.expand(function (row, col) {
+ var self = Container.call(this);
+ self.row = row;
+ self.col = col;
+ self.value = 0; // 0 = empty, 1 = X, 2 = O
+ var background = self.attachAsset('cellBackground', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var symbol = null;
+ self.placeSymbol = function (playerSymbol) {
+ if (self.value !== 0) return false;
+ self.value = playerSymbol;
+ if (playerSymbol === 1) {
+ symbol = self.attachAsset('xSymbol', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 0,
+ scaleY: 0
+ });
+ } else {
+ symbol = self.attachAsset('oSymbol', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 0,
+ scaleY: 0
+ });
+ }
+ tween(symbol, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 300,
+ easing: tween.elasticOut
+ });
+ LK.getSound('placeSymbol').play();
+ return true;
+ };
+ self.down = function (x, y, obj) {
+ if (gameState === 'playing' && currentPlayer === 1 && self.value === 0) {
+ if (self.placeSymbol(1)) {
+ currentPlayer = 2;
+ checkGameEnd();
+ if (gameState === 'playing') {
+ LK.setTimeout(function () {
+ aiMove();
+ }, 500);
+ }
+ }
+ }
+ };
+ return self;
+});
+var GameBoard = Container.expand(function () {
+ var self = Container.call(this);
+ self.cells = [];
+ self.winLine = null;
+ // Create 3x3 grid
+ for (var row = 0; row < 3; row++) {
+ self.cells[row] = [];
+ for (var col = 0; col < 3; col++) {
+ var cell = new Cell(row, col);
+ cell.x = (col - 1) * 220;
+ cell.y = (row - 1) * 220;
+ self.cells[row][col] = cell;
+ self.addChild(cell);
+ }
+ }
+ // Create grid lines
+ // Vertical lines
+ for (var i = 0; i < 2; i++) {
+ var vLine = self.attachAsset('gridLine', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: (i - 0.5) * 220,
+ y: 0
+ });
+ }
+ // Horizontal lines
+ for (var i = 0; i < 2; i++) {
+ var hLine = self.attachAsset('gridLine', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 0,
+ y: (i - 0.5) * 220,
+ rotation: Math.PI / 2
+ });
+ }
+ self.getCell = function (row, col) {
+ return self.cells[row][col];
+ };
+ self.getBoardState = function () {
+ var state = [];
+ for (var row = 0; row < 3; row++) {
+ state[row] = [];
+ for (var col = 0; col < 3; col++) {
+ state[row][col] = self.cells[row][col].value;
+ }
+ }
+ return state;
+ };
+ self.checkWin = function (player) {
+ var board = self.getBoardState();
+ // Check rows
+ for (var row = 0; row < 3; row++) {
+ if (board[row][0] === player && board[row][1] === player && board[row][2] === player) {
+ return {
+ type: 'row',
+ index: row
+ };
+ }
+ }
+ // Check columns
+ for (var col = 0; col < 3; col++) {
+ if (board[0][col] === player && board[1][col] === player && board[2][col] === player) {
+ return {
+ type: 'col',
+ index: col
+ };
+ }
+ }
+ // Check diagonals
+ if (board[0][0] === player && board[1][1] === player && board[2][2] === player) {
+ return {
+ type: 'diag',
+ index: 0
+ };
+ }
+ if (board[0][2] === player && board[1][1] === player && board[2][0] === player) {
+ return {
+ type: 'diag',
+ index: 1
+ };
+ }
+ return null;
+ };
+ self.isBoardFull = function () {
+ var board = self.getBoardState();
+ for (var row = 0; row < 3; row++) {
+ for (var col = 0; col < 3; col++) {
+ if (board[row][col] === 0) return false;
+ }
+ }
+ return true;
+ };
+ self.showWinLine = function (winInfo) {
+ self.winLine = self.attachAsset('winLine', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 0,
+ alpha: 0.8
+ });
+ if (winInfo.type === 'row') {
+ self.winLine.x = 0;
+ self.winLine.y = (winInfo.index - 1) * 220;
+ self.winLine.rotation = 0;
+ } else if (winInfo.type === 'col') {
+ self.winLine.x = (winInfo.index - 1) * 220;
+ self.winLine.y = 0;
+ self.winLine.rotation = Math.PI / 2;
+ } else if (winInfo.type === 'diag') {
+ self.winLine.x = 0;
+ self.winLine.y = 0;
+ if (winInfo.index === 0) {
+ self.winLine.rotation = Math.PI / 4;
+ self.winLine.width = 650;
+ } else {
+ self.winLine.rotation = -Math.PI / 4;
+ self.winLine.width = 650;
+ }
+ }
+ tween(self.winLine, {
+ scaleX: 1
+ }, {
+ duration: 500,
+ easing: tween.easeOut
+ });
+ };
+ self.reset = function () {
+ for (var row = 0; row < 3; row++) {
+ for (var col = 0; col < 3; col++) {
+ var cell = self.cells[row][col];
+ cell.value = 0;
+ if (cell.children.length > 1) {
+ cell.removeChild(cell.children[cell.children.length - 1]);
+ }
+ }
+ }
+ if (self.winLine) {
+ self.removeChild(self.winLine);
+ self.winLine = null;
+ }
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0xF5F5F5
+});
+
+/****
+* Game Code
+****/
+var gameBoard = null;
+var gameState = 'playing'; // 'playing', 'won', 'lost', 'draw'
+var currentPlayer = 1; // 1 = X (human), 2 = O (AI)
+// Score tracking
+var wins = storage.wins || 0;
+var losses = storage.losses || 0;
+var draws = storage.draws || 0;
+// UI Elements
+var statusText = new Text2('Your Turn (X)', {
+ size: 80,
+ fill: 0x333333
+});
+statusText.anchor.set(0.5, 0);
+LK.gui.top.addChild(statusText);
+statusText.y = 150;
+var scoreText = new Text2('Wins: ' + wins + ' | Losses: ' + losses + ' | Draws: ' + draws, {
+ size: 50,
+ fill: 0x666666
+});
+scoreText.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreText);
+scoreText.y = 250;
+var restartButton = new Text2('Play Again', {
+ size: 60,
+ fill: 0x4CAF50
+});
+restartButton.anchor.set(0.5, 1);
+LK.gui.bottom.addChild(restartButton);
+restartButton.y = -100;
+restartButton.alpha = 0;
+// Initialize game board
+gameBoard = new GameBoard();
+gameBoard.x = 2048 / 2;
+gameBoard.y = 2732 / 2;
+game.addChild(gameBoard);
+function checkGameEnd() {
+ var playerWin = gameBoard.checkWin(1);
+ var aiWin = gameBoard.checkWin(2);
+ if (playerWin) {
+ gameState = 'won';
+ statusText.setText('You Win!');
+ gameBoard.showWinLine(playerWin);
+ wins++;
+ storage.wins = wins;
+ LK.getSound('gameWin').play();
+ showRestartButton();
+ } else if (aiWin) {
+ gameState = 'lost';
+ statusText.setText('AI Wins!');
+ gameBoard.showWinLine(aiWin);
+ losses++;
+ storage.losses = losses;
+ LK.getSound('gameLose').play();
+ showRestartButton();
+ } else if (gameBoard.isBoardFull()) {
+ gameState = 'draw';
+ statusText.setText('Draw!');
+ draws++;
+ storage.draws = draws;
+ LK.getSound('gameDraw').play();
+ showRestartButton();
+ }
+ if (gameState !== 'playing') {
+ scoreText.setText('Wins: ' + wins + ' | Losses: ' + losses + ' | Draws: ' + draws);
+ }
+}
+function showRestartButton() {
+ tween(restartButton, {
+ alpha: 1
+ }, {
+ duration: 500,
+ easing: tween.easeOut
+ });
+}
+function minimax(board, depth, isMaximizing) {
+ var aiWin = checkWinOnBoard(board, 2);
+ var playerWin = checkWinOnBoard(board, 1);
+ if (aiWin) return 10 - depth;
+ if (playerWin) return depth - 10;
+ if (isBoardFullArray(board)) return 0;
+ if (isMaximizing) {
+ var bestScore = -1000;
+ for (var row = 0; row < 3; row++) {
+ for (var col = 0; col < 3; col++) {
+ if (board[row][col] === 0) {
+ board[row][col] = 2;
+ var score = minimax(board, depth + 1, false);
+ board[row][col] = 0;
+ if (score > bestScore) {
+ bestScore = score;
+ }
+ }
+ }
+ }
+ return bestScore;
+ } else {
+ var bestScore = 1000;
+ for (var row = 0; row < 3; row++) {
+ for (var col = 0; col < 3; col++) {
+ if (board[row][col] === 0) {
+ board[row][col] = 1;
+ var score = minimax(board, depth + 1, true);
+ board[row][col] = 0;
+ if (score < bestScore) {
+ bestScore = score;
+ }
+ }
+ }
+ }
+ return bestScore;
+ }
+}
+function checkWinOnBoard(board, player) {
+ // Check rows
+ for (var row = 0; row < 3; row++) {
+ if (board[row][0] === player && board[row][1] === player && board[row][2] === player) {
+ return true;
+ }
+ }
+ // Check columns
+ for (var col = 0; col < 3; col++) {
+ if (board[0][col] === player && board[1][col] === player && board[2][col] === player) {
+ return true;
+ }
+ }
+ // Check diagonals
+ if (board[0][0] === player && board[1][1] === player && board[2][2] === player) {
+ return true;
+ }
+ if (board[0][2] === player && board[1][1] === player && board[2][0] === player) {
+ return true;
+ }
+ return false;
+}
+function isBoardFullArray(board) {
+ for (var row = 0; row < 3; row++) {
+ for (var col = 0; col < 3; col++) {
+ if (board[row][col] === 0) return false;
+ }
+ }
+ return true;
+}
+function aiMove() {
+ if (gameState !== 'playing' || currentPlayer !== 2) return;
+ var board = gameBoard.getBoardState();
+ var bestScore = -1000;
+ var bestMove = null;
+ for (var row = 0; row < 3; row++) {
+ for (var col = 0; col < 3; col++) {
+ if (board[row][col] === 0) {
+ board[row][col] = 2;
+ var score = minimax(board, 0, false);
+ board[row][col] = 0;
+ if (score > bestScore) {
+ bestScore = score;
+ bestMove = {
+ row: row,
+ col: col
+ };
+ }
+ }
+ }
+ }
+ if (bestMove) {
+ var cell = gameBoard.getCell(bestMove.row, bestMove.col);
+ cell.placeSymbol(2);
+ currentPlayer = 1;
+ checkGameEnd();
+ if (gameState === 'playing') {
+ statusText.setText('Your Turn (X)');
+ }
+ }
+}
+function resetGame() {
+ gameBoard.reset();
+ gameState = 'playing';
+ currentPlayer = 1;
+ statusText.setText('Your Turn (X)');
+ tween(restartButton, {
+ alpha: 0
+ }, {
+ duration: 300,
+ easing: tween.easeIn
+ });
+}
+restartButton.down = function (x, y, obj) {
+ if (gameState !== 'playing') {
+ resetGame();
+ }
+};
+game.update = function () {
+ if (gameState === 'playing' && currentPlayer === 1) {
+ statusText.setText('Your Turn (X)');
+ } else if (gameState === 'playing' && currentPlayer === 2) {
+ statusText.setText('AI Turn (O)');
+ }
+};
\ No newline at end of file