Code edit (6 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
User prompt
Tic-Tac-Toe Master
Initial prompt
AI does X or O randomly and Player does X or O randomly. Player goes first and Ai goes second. Has A difficulty level of hardness of MEDIUM HARD EASY BEGINNER buttons on the home screen. BEGINNER Mode will show you how to play game show how to win and what does three X's or O's in a row and what Ai does to.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var GridCell = Container.expand(function (row, col) { var self = Container.call(this); var cellBg = self.attachAsset('gridCell', { anchorX: 0.5, anchorY: 0.5 }); self.row = row; self.col = col; self.symbol = null; self.symbolGraphic = null; self.down = function (x, y, obj) { if (gameState === 'playing' && self.symbol === null && !waitingForAI) { self.placeSymbol(playerSymbol); LK.getSound('placeSymbol').play(); if (checkWin(gameBoard, playerSymbol)) { gameState = 'playerWin'; showGameResult('You Win!'); LK.getSound('gameWin').play(); return; } if (checkDraw(gameBoard)) { gameState = 'draw'; showGameResult('Draw!'); LK.getSound('gameDraw').play(); return; } waitingForAI = true; LK.setTimeout(function () { makeAIMove(); waitingForAI = false; }, 500); } }; self.placeSymbol = function (symbol) { if (self.symbol !== null) return; self.symbol = symbol; gameBoard[self.row][self.col] = symbol; var assetName = symbol === 'X' ? 'xSymbol' : 'oSymbol'; self.symbolGraphic = self.attachAsset(assetName, { anchorX: 0.5, anchorY: 0.5, scaleX: 0.1, scaleY: 0.1 }); tween(self.symbolGraphic, { scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.bounceOut }); }; return self; }); var MenuButton = Container.expand(function (text, difficulty) { var self = Container.call(this); var buttonBg = self.attachAsset('buttonBackground', { anchorX: 0.5, anchorY: 0.5 }); var buttonText = new Text2(text, { size: 60, fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); self.addChild(buttonText); self.difficulty = difficulty; self.isHovered = false; self.down = function (x, y, obj) { tween(buttonBg, { scaleX: 0.95, scaleY: 0.95 }, { duration: 100 }); currentDifficulty = self.difficulty; gameState = 'playing'; initializeGame(); }; self.up = function (x, y, obj) { tween(buttonBg, { scaleX: 1, scaleY: 1 }, { duration: 100 }); }; return self; }); var TutorialOverlay = Container.expand(function (message) { var self = Container.call(this); var overlay = self.attachAsset('tutorialOverlay', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); var messageText = new Text2(message, { size: 80, fill: 0xFFFFFF }); messageText.anchor.set(0.5, 0.5); self.addChild(messageText); self.down = function (x, y, obj) { self.destroy(); tutorialStep++; showNextTutorial(); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a1a1a }); /**** * Game Code ****/ var gameState = 'menu'; // menu, playing, playerWin, aiWin, draw var currentDifficulty = 'EASY'; var gameBoard = []; var gridCells = []; var playerSymbol = 'X'; var aiSymbol = 'O'; var waitingForAI = false; var tutorialStep = 0; var tutorialOverlay = null; // Menu elements var menuButtons = []; var gameGrid = null; var resultText = null; var playAgainButton = null; // Tutorial messages var tutorialMessages = ["Welcome to Tic-Tac-Toe!\nTap to continue...", "Goal: Get 3 symbols in a row\n(horizontal, vertical, or diagonal)", "You are X, AI is O\nYou go first - tap any cell!", "Watch how the AI responds\nto your moves!", "Good luck! Tap to start playing..."]; function initializeMenu() { gameState = 'menu'; // Clear existing elements if (gameGrid) { gameGrid.destroy(); gameGrid = null; } if (resultText) { resultText.destroy(); resultText = null; } if (playAgainButton) { playAgainButton.destroy(); playAgainButton = null; } // Create menu buttons var difficulties = ['BEGINNER', 'EASY', 'MEDIUM', 'HARD']; var buttonSpacing = 200; var startY = 1366 - difficulties.length * buttonSpacing / 2; for (var i = 0; i < difficulties.length; i++) { var button = new MenuButton(difficulties[i], difficulties[i]); button.x = 1024; button.y = startY + i * buttonSpacing; menuButtons.push(button); game.addChild(button); } // Title var titleText = new Text2('Tic-Tac-Toe Master', { size: 120, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 400; game.addChild(titleText); } function initializeGame() { // Clear menu for (var i = 0; i < menuButtons.length; i++) { menuButtons[i].destroy(); } menuButtons = []; // Random symbol assignment if (Math.random() < 0.5) { playerSymbol = 'X'; aiSymbol = 'O'; } else { playerSymbol = 'O'; aiSymbol = 'X'; } // Initialize game board gameBoard = [[null, null, null], [null, null, null], [null, null, null]]; // Create grid createGrid(); // Show tutorial for beginner mode if (currentDifficulty === 'BEGINNER') { tutorialStep = 0; showNextTutorial(); } } function createGrid() { gameGrid = new Container(); game.addChild(gameGrid); // Center the grid gameGrid.x = 1024; gameGrid.y = 1366; // Create grid background var gridBg = gameGrid.attachAsset('gridBackground', { anchorX: 0.5, anchorY: 0.5 }); // Create cells gridCells = []; for (var row = 0; row < 3; row++) { gridCells[row] = []; for (var col = 0; col < 3; col++) { var cell = new GridCell(row, col); cell.x = (col - 1) * 200; cell.y = (row - 1) * 200; gridCells[row][col] = cell; gameGrid.addChild(cell); } } } function showNextTutorial() { if (currentDifficulty !== 'BEGINNER' || tutorialStep >= tutorialMessages.length) { return; } tutorialOverlay = new TutorialOverlay(tutorialMessages[tutorialStep]); tutorialOverlay.x = 1024; tutorialOverlay.y = 1366; game.addChild(tutorialOverlay); } function makeAIMove() { var availableMoves = []; // Find available moves for (var row = 0; row < 3; row++) { for (var col = 0; col < 3; col++) { if (gameBoard[row][col] === null) { availableMoves.push({ row: row, col: col }); } } } if (availableMoves.length === 0) return; var move = null; switch (currentDifficulty) { case 'BEGINNER': case 'EASY': // Random move move = availableMoves[Math.floor(Math.random() * availableMoves.length)]; break; case 'MEDIUM': // Try to win, then block, then random move = findWinningMove(gameBoard, aiSymbol) || findWinningMove(gameBoard, playerSymbol) || availableMoves[Math.floor(Math.random() * availableMoves.length)]; break; case 'HARD': // Strategic AI move = getBestMove(gameBoard, aiSymbol); break; } if (move) { gridCells[move.row][move.col].placeSymbol(aiSymbol); if (checkWin(gameBoard, aiSymbol)) { gameState = 'aiWin'; showGameResult('AI Wins!'); LK.getSound('gameLose').play(); } else if (checkDraw(gameBoard)) { gameState = 'draw'; showGameResult('Draw!'); LK.getSound('gameDraw').play(); } } } function findWinningMove(board, symbol) { for (var row = 0; row < 3; row++) { for (var col = 0; col < 3; col++) { if (board[row][col] === null) { board[row][col] = symbol; if (checkWin(board, symbol)) { board[row][col] = null; return { row: row, col: col }; } board[row][col] = null; } } } return null; } function getBestMove(board, symbol) { var bestScore = -Infinity; var bestMove = null; for (var row = 0; row < 3; row++) { for (var col = 0; col < 3; col++) { if (board[row][col] === null) { board[row][col] = symbol; var score = minimax(board, 0, false, symbol); board[row][col] = null; if (score > bestScore) { bestScore = score; bestMove = { row: row, col: col }; } } } } return bestMove; } function minimax(board, depth, isMaximizing, aiSym) { var playerSym = aiSym === 'X' ? 'O' : 'X'; if (checkWin(board, aiSym)) return 10 - depth; if (checkWin(board, playerSym)) return depth - 10; if (checkDraw(board)) return 0; if (isMaximizing) { var bestScore = -Infinity; for (var row = 0; row < 3; row++) { for (var col = 0; col < 3; col++) { if (board[row][col] === null) { board[row][col] = aiSym; var score = minimax(board, depth + 1, false, aiSym); board[row][col] = null; bestScore = Math.max(score, bestScore); } } } return bestScore; } else { var bestScore = Infinity; for (var row = 0; row < 3; row++) { for (var col = 0; col < 3; col++) { if (board[row][col] === null) { board[row][col] = playerSym; var score = minimax(board, depth + 1, true, aiSym); board[row][col] = null; bestScore = Math.min(score, bestScore); } } } return bestScore; } } function checkWin(board, symbol) { // Check rows for (var row = 0; row < 3; row++) { if (board[row][0] === symbol && board[row][1] === symbol && board[row][2] === symbol) { return true; } } // Check columns for (var col = 0; col < 3; col++) { if (board[0][col] === symbol && board[1][col] === symbol && board[2][col] === symbol) { return true; } } // Check diagonals if (board[0][0] === symbol && board[1][1] === symbol && board[2][2] === symbol) { return true; } if (board[0][2] === symbol && board[1][1] === symbol && board[2][0] === symbol) { return true; } return false; } function checkDraw(board) { for (var row = 0; row < 3; row++) { for (var col = 0; col < 3; col++) { if (board[row][col] === null) { return false; } } } return true; } function showGameResult(message) { resultText = new Text2(message, { size: 100, fill: 0xFFFFFF }); resultText.anchor.set(0.5, 0.5); resultText.x = 1024; resultText.y = 800; game.addChild(resultText); // Play again button playAgainButton = new MenuButton('Play Again', 'playAgain'); playAgainButton.x = 1024; playAgainButton.y = 1000; playAgainButton.down = function () { initializeMenu(); }; game.addChild(playAgainButton); } // Initialize menu on start initializeMenu(); game.update = function () { // Main game loop - most logic handled in event handlers };
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,408 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1");
+
+/****
+* Classes
+****/
+var GridCell = Container.expand(function (row, col) {
+ var self = Container.call(this);
+ var cellBg = self.attachAsset('gridCell', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.row = row;
+ self.col = col;
+ self.symbol = null;
+ self.symbolGraphic = null;
+ self.down = function (x, y, obj) {
+ if (gameState === 'playing' && self.symbol === null && !waitingForAI) {
+ self.placeSymbol(playerSymbol);
+ LK.getSound('placeSymbol').play();
+ if (checkWin(gameBoard, playerSymbol)) {
+ gameState = 'playerWin';
+ showGameResult('You Win!');
+ LK.getSound('gameWin').play();
+ return;
+ }
+ if (checkDraw(gameBoard)) {
+ gameState = 'draw';
+ showGameResult('Draw!');
+ LK.getSound('gameDraw').play();
+ return;
+ }
+ waitingForAI = true;
+ LK.setTimeout(function () {
+ makeAIMove();
+ waitingForAI = false;
+ }, 500);
+ }
+ };
+ self.placeSymbol = function (symbol) {
+ if (self.symbol !== null) return;
+ self.symbol = symbol;
+ gameBoard[self.row][self.col] = symbol;
+ var assetName = symbol === 'X' ? 'xSymbol' : 'oSymbol';
+ self.symbolGraphic = self.attachAsset(assetName, {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 0.1,
+ scaleY: 0.1
+ });
+ tween(self.symbolGraphic, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 200,
+ easing: tween.bounceOut
+ });
+ };
+ return self;
+});
+var MenuButton = Container.expand(function (text, difficulty) {
+ var self = Container.call(this);
+ var buttonBg = self.attachAsset('buttonBackground', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var buttonText = new Text2(text, {
+ size: 60,
+ fill: 0xFFFFFF
+ });
+ buttonText.anchor.set(0.5, 0.5);
+ self.addChild(buttonText);
+ self.difficulty = difficulty;
+ self.isHovered = false;
+ self.down = function (x, y, obj) {
+ tween(buttonBg, {
+ scaleX: 0.95,
+ scaleY: 0.95
+ }, {
+ duration: 100
+ });
+ currentDifficulty = self.difficulty;
+ gameState = 'playing';
+ initializeGame();
+ };
+ self.up = function (x, y, obj) {
+ tween(buttonBg, {
+ scaleX: 1,
+ scaleY: 1
+ }, {
+ duration: 100
+ });
+ };
+ return self;
+});
+var TutorialOverlay = Container.expand(function (message) {
+ var self = Container.call(this);
+ var overlay = self.attachAsset('tutorialOverlay', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.8
+ });
+ var messageText = new Text2(message, {
+ size: 80,
+ fill: 0xFFFFFF
+ });
+ messageText.anchor.set(0.5, 0.5);
+ self.addChild(messageText);
+ self.down = function (x, y, obj) {
+ self.destroy();
+ tutorialStep++;
+ showNextTutorial();
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x1a1a1a
+});
+
+/****
+* Game Code
+****/
+var gameState = 'menu'; // menu, playing, playerWin, aiWin, draw
+var currentDifficulty = 'EASY';
+var gameBoard = [];
+var gridCells = [];
+var playerSymbol = 'X';
+var aiSymbol = 'O';
+var waitingForAI = false;
+var tutorialStep = 0;
+var tutorialOverlay = null;
+// Menu elements
+var menuButtons = [];
+var gameGrid = null;
+var resultText = null;
+var playAgainButton = null;
+// Tutorial messages
+var tutorialMessages = ["Welcome to Tic-Tac-Toe!\nTap to continue...", "Goal: Get 3 symbols in a row\n(horizontal, vertical, or diagonal)", "You are X, AI is O\nYou go first - tap any cell!", "Watch how the AI responds\nto your moves!", "Good luck! Tap to start playing..."];
+function initializeMenu() {
+ gameState = 'menu';
+ // Clear existing elements
+ if (gameGrid) {
+ gameGrid.destroy();
+ gameGrid = null;
+ }
+ if (resultText) {
+ resultText.destroy();
+ resultText = null;
+ }
+ if (playAgainButton) {
+ playAgainButton.destroy();
+ playAgainButton = null;
+ }
+ // Create menu buttons
+ var difficulties = ['BEGINNER', 'EASY', 'MEDIUM', 'HARD'];
+ var buttonSpacing = 200;
+ var startY = 1366 - difficulties.length * buttonSpacing / 2;
+ for (var i = 0; i < difficulties.length; i++) {
+ var button = new MenuButton(difficulties[i], difficulties[i]);
+ button.x = 1024;
+ button.y = startY + i * buttonSpacing;
+ menuButtons.push(button);
+ game.addChild(button);
+ }
+ // Title
+ var titleText = new Text2('Tic-Tac-Toe Master', {
+ size: 120,
+ fill: 0xFFFFFF
+ });
+ titleText.anchor.set(0.5, 0.5);
+ titleText.x = 1024;
+ titleText.y = 400;
+ game.addChild(titleText);
+}
+function initializeGame() {
+ // Clear menu
+ for (var i = 0; i < menuButtons.length; i++) {
+ menuButtons[i].destroy();
+ }
+ menuButtons = [];
+ // Random symbol assignment
+ if (Math.random() < 0.5) {
+ playerSymbol = 'X';
+ aiSymbol = 'O';
+ } else {
+ playerSymbol = 'O';
+ aiSymbol = 'X';
+ }
+ // Initialize game board
+ gameBoard = [[null, null, null], [null, null, null], [null, null, null]];
+ // Create grid
+ createGrid();
+ // Show tutorial for beginner mode
+ if (currentDifficulty === 'BEGINNER') {
+ tutorialStep = 0;
+ showNextTutorial();
+ }
+}
+function createGrid() {
+ gameGrid = new Container();
+ game.addChild(gameGrid);
+ // Center the grid
+ gameGrid.x = 1024;
+ gameGrid.y = 1366;
+ // Create grid background
+ var gridBg = gameGrid.attachAsset('gridBackground', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Create cells
+ gridCells = [];
+ for (var row = 0; row < 3; row++) {
+ gridCells[row] = [];
+ for (var col = 0; col < 3; col++) {
+ var cell = new GridCell(row, col);
+ cell.x = (col - 1) * 200;
+ cell.y = (row - 1) * 200;
+ gridCells[row][col] = cell;
+ gameGrid.addChild(cell);
+ }
+ }
+}
+function showNextTutorial() {
+ if (currentDifficulty !== 'BEGINNER' || tutorialStep >= tutorialMessages.length) {
+ return;
+ }
+ tutorialOverlay = new TutorialOverlay(tutorialMessages[tutorialStep]);
+ tutorialOverlay.x = 1024;
+ tutorialOverlay.y = 1366;
+ game.addChild(tutorialOverlay);
+}
+function makeAIMove() {
+ var availableMoves = [];
+ // Find available moves
+ for (var row = 0; row < 3; row++) {
+ for (var col = 0; col < 3; col++) {
+ if (gameBoard[row][col] === null) {
+ availableMoves.push({
+ row: row,
+ col: col
+ });
+ }
+ }
+ }
+ if (availableMoves.length === 0) return;
+ var move = null;
+ switch (currentDifficulty) {
+ case 'BEGINNER':
+ case 'EASY':
+ // Random move
+ move = availableMoves[Math.floor(Math.random() * availableMoves.length)];
+ break;
+ case 'MEDIUM':
+ // Try to win, then block, then random
+ move = findWinningMove(gameBoard, aiSymbol) || findWinningMove(gameBoard, playerSymbol) || availableMoves[Math.floor(Math.random() * availableMoves.length)];
+ break;
+ case 'HARD':
+ // Strategic AI
+ move = getBestMove(gameBoard, aiSymbol);
+ break;
+ }
+ if (move) {
+ gridCells[move.row][move.col].placeSymbol(aiSymbol);
+ if (checkWin(gameBoard, aiSymbol)) {
+ gameState = 'aiWin';
+ showGameResult('AI Wins!');
+ LK.getSound('gameLose').play();
+ } else if (checkDraw(gameBoard)) {
+ gameState = 'draw';
+ showGameResult('Draw!');
+ LK.getSound('gameDraw').play();
+ }
+ }
+}
+function findWinningMove(board, symbol) {
+ for (var row = 0; row < 3; row++) {
+ for (var col = 0; col < 3; col++) {
+ if (board[row][col] === null) {
+ board[row][col] = symbol;
+ if (checkWin(board, symbol)) {
+ board[row][col] = null;
+ return {
+ row: row,
+ col: col
+ };
+ }
+ board[row][col] = null;
+ }
+ }
+ }
+ return null;
+}
+function getBestMove(board, symbol) {
+ var bestScore = -Infinity;
+ var bestMove = null;
+ for (var row = 0; row < 3; row++) {
+ for (var col = 0; col < 3; col++) {
+ if (board[row][col] === null) {
+ board[row][col] = symbol;
+ var score = minimax(board, 0, false, symbol);
+ board[row][col] = null;
+ if (score > bestScore) {
+ bestScore = score;
+ bestMove = {
+ row: row,
+ col: col
+ };
+ }
+ }
+ }
+ }
+ return bestMove;
+}
+function minimax(board, depth, isMaximizing, aiSym) {
+ var playerSym = aiSym === 'X' ? 'O' : 'X';
+ if (checkWin(board, aiSym)) return 10 - depth;
+ if (checkWin(board, playerSym)) return depth - 10;
+ if (checkDraw(board)) return 0;
+ if (isMaximizing) {
+ var bestScore = -Infinity;
+ for (var row = 0; row < 3; row++) {
+ for (var col = 0; col < 3; col++) {
+ if (board[row][col] === null) {
+ board[row][col] = aiSym;
+ var score = minimax(board, depth + 1, false, aiSym);
+ board[row][col] = null;
+ bestScore = Math.max(score, bestScore);
+ }
+ }
+ }
+ return bestScore;
+ } else {
+ var bestScore = Infinity;
+ for (var row = 0; row < 3; row++) {
+ for (var col = 0; col < 3; col++) {
+ if (board[row][col] === null) {
+ board[row][col] = playerSym;
+ var score = minimax(board, depth + 1, true, aiSym);
+ board[row][col] = null;
+ bestScore = Math.min(score, bestScore);
+ }
+ }
+ }
+ return bestScore;
+ }
+}
+function checkWin(board, symbol) {
+ // Check rows
+ for (var row = 0; row < 3; row++) {
+ if (board[row][0] === symbol && board[row][1] === symbol && board[row][2] === symbol) {
+ return true;
+ }
+ }
+ // Check columns
+ for (var col = 0; col < 3; col++) {
+ if (board[0][col] === symbol && board[1][col] === symbol && board[2][col] === symbol) {
+ return true;
+ }
+ }
+ // Check diagonals
+ if (board[0][0] === symbol && board[1][1] === symbol && board[2][2] === symbol) {
+ return true;
+ }
+ if (board[0][2] === symbol && board[1][1] === symbol && board[2][0] === symbol) {
+ return true;
+ }
+ return false;
+}
+function checkDraw(board) {
+ for (var row = 0; row < 3; row++) {
+ for (var col = 0; col < 3; col++) {
+ if (board[row][col] === null) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+function showGameResult(message) {
+ resultText = new Text2(message, {
+ size: 100,
+ fill: 0xFFFFFF
+ });
+ resultText.anchor.set(0.5, 0.5);
+ resultText.x = 1024;
+ resultText.y = 800;
+ game.addChild(resultText);
+ // Play again button
+ playAgainButton = new MenuButton('Play Again', 'playAgain');
+ playAgainButton.x = 1024;
+ playAgainButton.y = 1000;
+ playAgainButton.down = function () {
+ initializeMenu();
+ };
+ game.addChild(playAgainButton);
+}
+// Initialize menu on start
+initializeMenu();
+game.update = function () {
+ // Main game loop - most logic handled in event handlers
+};
\ No newline at end of file