User prompt
add a shop so you can buy skins ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
When I'm winning in tic-tac-toe, it doesn't give me a point. So when you win in tic-tac-toe, it gives the player a point and makes the X disappear. Actually, no, restart the game.
User prompt
If it is 3 in a row, give the player a point. If it is any kind of line, like a diagonal line, or a line going up, give the X a point. But if it's 4-0, don't give X a point.
User prompt
If X wins, give them one win, and if O wins, don't give X a win, and make it so if O wins, you win.
User prompt
add a menu screen that you can play multiplayer or play with an AI
User prompt
Make tic-tac-toe
Code edit (1 edits merged)
Please save this source code
User prompt
Ultimate Tic-Tac-Toe Arena
Initial prompt
can you make tic-tac-toe like better so you could have like multiplayer custom modes
/****
* Plugins
****/
var storage = LK.import("@upit/storage.v1", {
coins: 0,
ownedSkins: ["default"],
currentSkin: "default"
});
/****
* Classes
****/
var ShopItem = Container.expand(function (skinData) {
var self = Container.call(this);
self.skinData = skinData;
// Create item background
var itemBg = self.attachAsset('skinItem', {
anchorX: 0.5,
anchorY: 0.5
});
// Create skin preview
var skinPreview = self.attachAsset(skinData.assetId, {
anchorX: 0.5,
anchorY: 0.5,
y: -40
});
// Create skin name text
var nameText = new Text2(skinData.name, {
size: 40,
fill: 0x333333
});
nameText.anchor.set(0.5, 0.5);
nameText.y = 40;
self.addChild(nameText);
// Create price/status text
var priceText = new Text2(skinData.price + ' pts', {
size: 30,
fill: 0x666666
});
priceText.anchor.set(0.5, 0.5);
priceText.y = 70;
self.addChild(priceText);
// Create button
var button = null;
var buttonText = null;
self.updateButton = function () {
if (button) {
button.destroy();
buttonText.destroy();
}
var isOwned = storage.ownedSkins.indexOf(skinData.id) !== -1;
var isCurrent = storage.currentSkin === skinData.id;
var canAfford = LK.getScore() >= skinData.price;
if (isCurrent) {
button = self.attachAsset('selectedButton', {
anchorX: 0.5,
anchorY: 0.5,
y: 95
});
buttonText = new Text2('SELECTED', {
size: 25,
fill: 0xffffff
});
} else if (isOwned) {
button = self.attachAsset('selectButton', {
anchorX: 0.5,
anchorY: 0.5,
y: 95
});
buttonText = new Text2('SELECT', {
size: 25,
fill: 0xffffff
});
} else if (canAfford) {
button = self.attachAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
y: 95
});
buttonText = new Text2('BUY', {
size: 25,
fill: 0xffffff
});
} else {
button = self.attachAsset('skinItem', {
anchorX: 0.5,
anchorY: 0.5,
y: 95,
scaleX: 0.7,
scaleY: 0.25
});
button.alpha = 0.5;
buttonText = new Text2('NOT ENOUGH', {
size: 20,
fill: 0x999999
});
}
buttonText.anchor.set(0.5, 0.5);
buttonText.y = 95;
self.addChild(buttonText);
};
self.down = function (x, y, obj) {
if (gameState !== 'shop') return;
var isOwned = storage.ownedSkins.indexOf(skinData.id) !== -1;
var isCurrent = storage.currentSkin === skinData.id;
var canAfford = LK.getScore() >= skinData.price;
if (isCurrent) {
// Already selected, do nothing
} else if (isOwned) {
// Select this skin
storage.currentSkin = skinData.id;
updateShopUI();
} else if (canAfford) {
// Buy this skin
LK.setScore(LK.getScore() - skinData.price);
storage.ownedSkins.push(skinData.id);
storage.currentSkin = skinData.id;
updateShopUI();
}
};
self.updateButton();
return self;
});
var TicTacToeCell = Container.expand(function (row, col) {
var self = Container.call(this);
self.row = row;
self.col = col;
self.state = 'empty'; // 'empty', 'X', 'O'
// Create border
var border = self.attachAsset('cellBorder', {
anchorX: 0.5,
anchorY: 0.5
});
// Create empty cell background
var cellBg = self.attachAsset('cellEmpty', {
anchorX: 0.5,
anchorY: 0.5
});
var symbol = null;
self.placeSymbol = function (symbolType) {
if (self.state !== 'empty') return false;
self.state = symbolType;
if (symbolType === 'X') {
var currentSkinData = null;
for (var i = 0; i < skinData.length; i++) {
if (skinData[i].id === storage.currentSkin) {
currentSkinData = skinData[i];
break;
}
}
var assetToUse = currentSkinData ? currentSkinData.assetId : 'symbolX';
symbol = self.attachAsset(assetToUse, {
anchorX: 0.5,
anchorY: 0.5
});
} else if (symbolType === 'O') {
symbol = self.attachAsset('symbolO', {
anchorX: 0.5,
anchorY: 0.5
});
}
LK.getSound('placeSymbol').play();
return true;
};
self.reset = function () {
self.state = 'empty';
if (symbol) {
symbol.destroy();
symbol = null;
}
};
self.down = function (x, y, obj) {
if (gameState === 'playing' && self.state === 'empty') {
if (self.placeSymbol(currentPlayer)) {
checkWin();
if (gameState === 'playing') {
if (gameMode === 'multiplayer') {
currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
} else if (gameMode === 'ai' && currentPlayer === 'X') {
currentPlayer = 'O';
// AI makes move after short delay
LK.setTimeout(makeAIMove, 500);
}
updateUI();
}
}
}
};
return self;
});
/****
* Initialize Game
****/
// Game variables
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game variables
var gridSize = 3;
var cells = [];
var currentPlayer = 'X';
var gameState = 'menu'; // 'menu', 'playing', 'won', 'draw', 'shop'
var gameMode = null; // 'multiplayer', 'ai'
var winner = null;
// UI elements
var titleText = new Text2('Tic-Tac-Toe', {
size: 120,
fill: 0x333333
});
titleText.anchor.set(0.5, 0);
titleText.y = 200;
LK.gui.top.addChild(titleText);
var statusText = new Text2('Player X\'s Turn', {
size: 80,
fill: 0x333333
});
statusText.anchor.set(0.5, 0);
statusText.y = 100;
statusText.visible = false;
LK.gui.top.addChild(statusText);
var multiplayerButton = new Text2('Multiplayer', {
size: 80,
fill: 0x4444ff
});
multiplayerButton.anchor.set(0.5, 0.5);
multiplayerButton.x = 2048 / 2;
multiplayerButton.y = 2732 / 2 - 100;
game.addChild(multiplayerButton);
var aiButton = new Text2('Play vs AI', {
size: 80,
fill: 0xff4444
});
aiButton.anchor.set(0.5, 0.5);
aiButton.x = 2048 / 2;
aiButton.y = 2732 / 2 + 100;
game.addChild(aiButton);
var resetButton = new Text2('Reset Game', {
size: 60,
fill: 0x666666
});
resetButton.anchor.set(0.5, 1);
resetButton.visible = false;
LK.gui.bottom.addChild(resetButton);
var backButton = new Text2('Back to Menu', {
size: 60,
fill: 0x666666
});
backButton.anchor.set(0.5, 1);
backButton.y = -100;
backButton.visible = false;
LK.gui.bottom.addChild(backButton);
var shopButton = new Text2('Shop', {
size: 80,
fill: 0x9b59b6
});
shopButton.anchor.set(0.5, 0.5);
shopButton.x = 2048 / 2;
shopButton.y = 2732 / 2 + 200;
game.addChild(shopButton);
var shopTitle = new Text2('Skin Shop', {
size: 100,
fill: 0x333333
});
shopTitle.anchor.set(0.5, 0);
shopTitle.y = 150;
shopTitle.visible = false;
LK.gui.top.addChild(shopTitle);
// Skin data
var skinData = [{
id: 'default',
name: 'Classic',
price: 0,
assetId: 'skinClassic'
}, {
id: 'gold',
name: 'Gold',
price: 5,
assetId: 'skinGold'
}, {
id: 'rainbow',
name: 'Rainbow',
price: 10,
assetId: 'skinRainbow'
}];
var shopItems = [];
var scoreText = new Text2('Score: 0', {
size: 60,
fill: 0x333333
});
scoreText.anchor.set(1, 0);
scoreText.x = -50;
scoreText.y = 50;
LK.gui.topRight.addChild(scoreText);
// Initialize grid
function initializeGrid() {
// Clear existing cells
for (var i = 0; i < cells.length; i++) {
for (var j = 0; j < cells[i].length; j++) {
if (cells[i][j]) {
cells[i][j].destroy();
}
}
}
cells = [];
var cellSize = 220;
var gridWidth = gridSize * cellSize;
var gridHeight = gridSize * cellSize;
var startX = (2048 - gridWidth) / 2 + cellSize / 2;
var startY = (2732 - gridHeight) / 2 + cellSize / 2;
for (var row = 0; row < gridSize; row++) {
cells[row] = [];
for (var col = 0; col < gridSize; col++) {
var cell = new TicTacToeCell(row, col);
cell.x = startX + col * cellSize;
cell.y = startY + row * cellSize;
cells[row][col] = cell;
game.addChild(cell);
}
}
}
function checkWin() {
// Check rows
for (var row = 0; row < gridSize; row++) {
var allSame = true;
var firstCell = cells[row][0].state;
if (firstCell === 'empty') continue;
var lineLength = 0;
for (var col = 0; col < gridSize; col++) {
if (cells[row][col].state === firstCell) {
lineLength++;
} else {
allSame = false;
break;
}
}
if (allSame && lineLength === 3) {
gameState = 'won';
winner = firstCell;
if (winner === 'X') {
LK.setScore(LK.getScore() + 1);
} else if (winner === 'O') {
LK.showYouWin();
}
LK.getSound('winSound').play();
// Restart game after 2 seconds
LK.setTimeout(function () {
resetGame();
}, 2000);
return;
}
}
// Check columns
for (var col = 0; col < gridSize; col++) {
var allSame = true;
var firstCell = cells[0][col].state;
if (firstCell === 'empty') continue;
var lineLength = 0;
for (var row = 0; row < gridSize; row++) {
if (cells[row][col].state === firstCell) {
lineLength++;
} else {
allSame = false;
break;
}
}
if (allSame && lineLength === 3) {
gameState = 'won';
winner = firstCell;
if (winner === 'X') {
LK.setScore(LK.getScore() + 1);
} else if (winner === 'O') {
LK.showYouWin();
}
LK.getSound('winSound').play();
// Restart game after 2 seconds
LK.setTimeout(function () {
resetGame();
}, 2000);
return;
}
}
// Check diagonal (top-left to bottom-right)
var allSame = true;
var firstCell = cells[0][0].state;
if (firstCell !== 'empty') {
var lineLength = 0;
for (var i = 0; i < gridSize; i++) {
if (cells[i][i].state === firstCell) {
lineLength++;
} else {
allSame = false;
break;
}
}
if (allSame && lineLength === 3) {
gameState = 'won';
winner = firstCell;
if (winner === 'X') {
LK.setScore(LK.getScore() + 1);
} else if (winner === 'O') {
LK.showYouWin();
}
LK.getSound('winSound').play();
// Restart game after 2 seconds
LK.setTimeout(function () {
resetGame();
}, 2000);
return;
}
}
// Check diagonal (top-right to bottom-left)
allSame = true;
firstCell = cells[0][gridSize - 1].state;
if (firstCell !== 'empty') {
var lineLength = 0;
for (var i = 0; i < gridSize; i++) {
if (cells[i][gridSize - 1 - i].state === firstCell) {
lineLength++;
} else {
allSame = false;
break;
}
}
if (allSame && lineLength === 3) {
gameState = 'won';
winner = firstCell;
if (winner === 'X') {
LK.setScore(LK.getScore() + 1);
} else if (winner === 'O') {
LK.showYouWin();
}
LK.getSound('winSound').play();
// Restart game after 2 seconds
LK.setTimeout(function () {
resetGame();
}, 2000);
return;
}
}
// Check for draw
var allFilled = true;
for (var row = 0; row < gridSize; row++) {
for (var col = 0; col < gridSize; col++) {
if (cells[row][col].state === 'empty') {
allFilled = false;
break;
}
}
if (!allFilled) break;
}
if (allFilled) {
gameState = 'draw';
}
}
function updateUI() {
if (gameState === 'won') {
statusText.setText('Player ' + winner + ' Wins!');
} else if (gameState === 'draw') {
statusText.setText('It\'s a Draw!');
} else {
statusText.setText('Player ' + currentPlayer + '\'s Turn');
}
scoreText.setText('Score: ' + LK.getScore());
}
function startGame(mode) {
gameMode = mode;
gameState = 'playing';
currentPlayer = 'X';
winner = null;
// Hide menu elements
titleText.visible = false;
multiplayerButton.visible = false;
aiButton.visible = false;
shopButton.visible = false;
// Show game elements
statusText.visible = true;
resetButton.visible = true;
backButton.visible = true;
initializeGrid();
updateUI();
}
function showMenu() {
gameState = 'menu';
gameMode = null;
// Hide game elements
statusText.visible = false;
resetButton.visible = false;
backButton.visible = false;
shopTitle.visible = false;
// Show menu elements
titleText.visible = true;
multiplayerButton.visible = true;
aiButton.visible = true;
shopButton.visible = true;
// Clear grid
for (var i = 0; i < cells.length; i++) {
for (var j = 0; j < cells[i].length; j++) {
if (cells[i][j]) {
cells[i][j].destroy();
}
}
}
cells = [];
// Clear shop items
for (var i = 0; i < shopItems.length; i++) {
shopItems[i].destroy();
}
shopItems = [];
}
function showShop() {
gameState = 'shop';
// Hide menu elements
titleText.visible = false;
multiplayerButton.visible = false;
aiButton.visible = false;
shopButton.visible = false;
// Show shop elements
shopTitle.visible = true;
backButton.visible = true;
// Create shop items
var itemsPerRow = 3;
var itemSpacing = 300;
var startX = 2048 / 2 - (itemsPerRow - 1) * itemSpacing / 2;
var startY = 2732 / 2 - 100;
for (var i = 0; i < skinData.length; i++) {
var shopItem = new ShopItem(skinData[i]);
var row = Math.floor(i / itemsPerRow);
var col = i % itemsPerRow;
shopItem.x = startX + col * itemSpacing;
shopItem.y = startY + row * 250;
shopItems.push(shopItem);
game.addChild(shopItem);
}
}
function updateShopUI() {
for (var i = 0; i < shopItems.length; i++) {
shopItems[i].updateButton();
}
scoreText.setText('Score: ' + LK.getScore());
}
function resetGame() {
gameState = 'playing';
currentPlayer = 'X';
winner = null;
for (var row = 0; row < gridSize; row++) {
for (var col = 0; col < gridSize; col++) {
cells[row][col].reset();
}
}
updateUI();
}
// Menu button functionality
multiplayerButton.down = function (x, y, obj) {
if (gameState === 'menu') {
startGame('multiplayer');
}
};
aiButton.down = function (x, y, obj) {
if (gameState === 'menu') {
startGame('ai');
}
};
shopButton.down = function (x, y, obj) {
if (gameState === 'menu') {
showShop();
}
};
// Reset button functionality
resetButton.down = function (x, y, obj) {
if (gameState === 'playing') {
resetGame();
}
};
// Back button functionality
backButton.down = function (x, y, obj) {
if (gameState === 'shop') {
showMenu();
} else {
showMenu();
}
};
function makeAIMove() {
if (gameState !== 'playing' || currentPlayer !== 'O') return;
// Simple AI: find first empty cell
var emptyCells = [];
for (var row = 0; row < gridSize; row++) {
for (var col = 0; col < gridSize; col++) {
if (cells[row][col].state === 'empty') {
emptyCells.push({
row: row,
col: col
});
}
}
}
if (emptyCells.length > 0) {
var randomIndex = Math.floor(Math.random() * emptyCells.length);
var move = emptyCells[randomIndex];
cells[move.row][move.col].placeSymbol('O');
checkWin();
if (gameState === 'playing') {
currentPlayer = 'X';
updateUI();
}
}
}
// Initialize the game - start with menu
showMenu(); /****
* Plugins
****/
var storage = LK.import("@upit/storage.v1", {
coins: 0,
ownedSkins: ["default"],
currentSkin: "default"
});
/****
* Classes
****/
var ShopItem = Container.expand(function (skinData) {
var self = Container.call(this);
self.skinData = skinData;
// Create item background
var itemBg = self.attachAsset('skinItem', {
anchorX: 0.5,
anchorY: 0.5
});
// Create skin preview
var skinPreview = self.attachAsset(skinData.assetId, {
anchorX: 0.5,
anchorY: 0.5,
y: -40
});
// Create skin name text
var nameText = new Text2(skinData.name, {
size: 40,
fill: 0x333333
});
nameText.anchor.set(0.5, 0.5);
nameText.y = 40;
self.addChild(nameText);
// Create price/status text
var priceText = new Text2(skinData.price + ' pts', {
size: 30,
fill: 0x666666
});
priceText.anchor.set(0.5, 0.5);
priceText.y = 70;
self.addChild(priceText);
// Create button
var button = null;
var buttonText = null;
self.updateButton = function () {
if (button) {
button.destroy();
buttonText.destroy();
}
var isOwned = storage.ownedSkins.indexOf(skinData.id) !== -1;
var isCurrent = storage.currentSkin === skinData.id;
var canAfford = LK.getScore() >= skinData.price;
if (isCurrent) {
button = self.attachAsset('selectedButton', {
anchorX: 0.5,
anchorY: 0.5,
y: 95
});
buttonText = new Text2('SELECTED', {
size: 25,
fill: 0xffffff
});
} else if (isOwned) {
button = self.attachAsset('selectButton', {
anchorX: 0.5,
anchorY: 0.5,
y: 95
});
buttonText = new Text2('SELECT', {
size: 25,
fill: 0xffffff
});
} else if (canAfford) {
button = self.attachAsset('buyButton', {
anchorX: 0.5,
anchorY: 0.5,
y: 95
});
buttonText = new Text2('BUY', {
size: 25,
fill: 0xffffff
});
} else {
button = self.attachAsset('skinItem', {
anchorX: 0.5,
anchorY: 0.5,
y: 95,
scaleX: 0.7,
scaleY: 0.25
});
button.alpha = 0.5;
buttonText = new Text2('NOT ENOUGH', {
size: 20,
fill: 0x999999
});
}
buttonText.anchor.set(0.5, 0.5);
buttonText.y = 95;
self.addChild(buttonText);
};
self.down = function (x, y, obj) {
if (gameState !== 'shop') return;
var isOwned = storage.ownedSkins.indexOf(skinData.id) !== -1;
var isCurrent = storage.currentSkin === skinData.id;
var canAfford = LK.getScore() >= skinData.price;
if (isCurrent) {
// Already selected, do nothing
} else if (isOwned) {
// Select this skin
storage.currentSkin = skinData.id;
updateShopUI();
} else if (canAfford) {
// Buy this skin
LK.setScore(LK.getScore() - skinData.price);
storage.ownedSkins.push(skinData.id);
storage.currentSkin = skinData.id;
updateShopUI();
}
};
self.updateButton();
return self;
});
var TicTacToeCell = Container.expand(function (row, col) {
var self = Container.call(this);
self.row = row;
self.col = col;
self.state = 'empty'; // 'empty', 'X', 'O'
// Create border
var border = self.attachAsset('cellBorder', {
anchorX: 0.5,
anchorY: 0.5
});
// Create empty cell background
var cellBg = self.attachAsset('cellEmpty', {
anchorX: 0.5,
anchorY: 0.5
});
var symbol = null;
self.placeSymbol = function (symbolType) {
if (self.state !== 'empty') return false;
self.state = symbolType;
if (symbolType === 'X') {
var currentSkinData = null;
for (var i = 0; i < skinData.length; i++) {
if (skinData[i].id === storage.currentSkin) {
currentSkinData = skinData[i];
break;
}
}
var assetToUse = currentSkinData ? currentSkinData.assetId : 'symbolX';
symbol = self.attachAsset(assetToUse, {
anchorX: 0.5,
anchorY: 0.5
});
} else if (symbolType === 'O') {
symbol = self.attachAsset('symbolO', {
anchorX: 0.5,
anchorY: 0.5
});
}
LK.getSound('placeSymbol').play();
return true;
};
self.reset = function () {
self.state = 'empty';
if (symbol) {
symbol.destroy();
symbol = null;
}
};
self.down = function (x, y, obj) {
if (gameState === 'playing' && self.state === 'empty') {
if (self.placeSymbol(currentPlayer)) {
checkWin();
if (gameState === 'playing') {
if (gameMode === 'multiplayer') {
currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
} else if (gameMode === 'ai' && currentPlayer === 'X') {
currentPlayer = 'O';
// AI makes move after short delay
LK.setTimeout(makeAIMove, 500);
}
updateUI();
}
}
}
};
return self;
});
/****
* Initialize Game
****/
// Game variables
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
// Game variables
var gridSize = 3;
var cells = [];
var currentPlayer = 'X';
var gameState = 'menu'; // 'menu', 'playing', 'won', 'draw', 'shop'
var gameMode = null; // 'multiplayer', 'ai'
var winner = null;
// UI elements
var titleText = new Text2('Tic-Tac-Toe', {
size: 120,
fill: 0x333333
});
titleText.anchor.set(0.5, 0);
titleText.y = 200;
LK.gui.top.addChild(titleText);
var statusText = new Text2('Player X\'s Turn', {
size: 80,
fill: 0x333333
});
statusText.anchor.set(0.5, 0);
statusText.y = 100;
statusText.visible = false;
LK.gui.top.addChild(statusText);
var multiplayerButton = new Text2('Multiplayer', {
size: 80,
fill: 0x4444ff
});
multiplayerButton.anchor.set(0.5, 0.5);
multiplayerButton.x = 2048 / 2;
multiplayerButton.y = 2732 / 2 - 100;
game.addChild(multiplayerButton);
var aiButton = new Text2('Play vs AI', {
size: 80,
fill: 0xff4444
});
aiButton.anchor.set(0.5, 0.5);
aiButton.x = 2048 / 2;
aiButton.y = 2732 / 2 + 100;
game.addChild(aiButton);
var resetButton = new Text2('Reset Game', {
size: 60,
fill: 0x666666
});
resetButton.anchor.set(0.5, 1);
resetButton.visible = false;
LK.gui.bottom.addChild(resetButton);
var backButton = new Text2('Back to Menu', {
size: 60,
fill: 0x666666
});
backButton.anchor.set(0.5, 1);
backButton.y = -100;
backButton.visible = false;
LK.gui.bottom.addChild(backButton);
var shopButton = new Text2('Shop', {
size: 80,
fill: 0x9b59b6
});
shopButton.anchor.set(0.5, 0.5);
shopButton.x = 2048 / 2;
shopButton.y = 2732 / 2 + 200;
game.addChild(shopButton);
var shopTitle = new Text2('Skin Shop', {
size: 100,
fill: 0x333333
});
shopTitle.anchor.set(0.5, 0);
shopTitle.y = 150;
shopTitle.visible = false;
LK.gui.top.addChild(shopTitle);
// Skin data
var skinData = [{
id: 'default',
name: 'Classic',
price: 0,
assetId: 'skinClassic'
}, {
id: 'gold',
name: 'Gold',
price: 5,
assetId: 'skinGold'
}, {
id: 'rainbow',
name: 'Rainbow',
price: 10,
assetId: 'skinRainbow'
}];
var shopItems = [];
var scoreText = new Text2('Score: 0', {
size: 60,
fill: 0x333333
});
scoreText.anchor.set(1, 0);
scoreText.x = -50;
scoreText.y = 50;
LK.gui.topRight.addChild(scoreText);
// Initialize grid
function initializeGrid() {
// Clear existing cells
for (var i = 0; i < cells.length; i++) {
for (var j = 0; j < cells[i].length; j++) {
if (cells[i][j]) {
cells[i][j].destroy();
}
}
}
cells = [];
var cellSize = 220;
var gridWidth = gridSize * cellSize;
var gridHeight = gridSize * cellSize;
var startX = (2048 - gridWidth) / 2 + cellSize / 2;
var startY = (2732 - gridHeight) / 2 + cellSize / 2;
for (var row = 0; row < gridSize; row++) {
cells[row] = [];
for (var col = 0; col < gridSize; col++) {
var cell = new TicTacToeCell(row, col);
cell.x = startX + col * cellSize;
cell.y = startY + row * cellSize;
cells[row][col] = cell;
game.addChild(cell);
}
}
}
function checkWin() {
// Check rows
for (var row = 0; row < gridSize; row++) {
var allSame = true;
var firstCell = cells[row][0].state;
if (firstCell === 'empty') continue;
var lineLength = 0;
for (var col = 0; col < gridSize; col++) {
if (cells[row][col].state === firstCell) {
lineLength++;
} else {
allSame = false;
break;
}
}
if (allSame && lineLength === 3) {
gameState = 'won';
winner = firstCell;
if (winner === 'X') {
LK.setScore(LK.getScore() + 1);
} else if (winner === 'O') {
LK.showYouWin();
}
LK.getSound('winSound').play();
// Restart game after 2 seconds
LK.setTimeout(function () {
resetGame();
}, 2000);
return;
}
}
// Check columns
for (var col = 0; col < gridSize; col++) {
var allSame = true;
var firstCell = cells[0][col].state;
if (firstCell === 'empty') continue;
var lineLength = 0;
for (var row = 0; row < gridSize; row++) {
if (cells[row][col].state === firstCell) {
lineLength++;
} else {
allSame = false;
break;
}
}
if (allSame && lineLength === 3) {
gameState = 'won';
winner = firstCell;
if (winner === 'X') {
LK.setScore(LK.getScore() + 1);
} else if (winner === 'O') {
LK.showYouWin();
}
LK.getSound('winSound').play();
// Restart game after 2 seconds
LK.setTimeout(function () {
resetGame();
}, 2000);
return;
}
}
// Check diagonal (top-left to bottom-right)
var allSame = true;
var firstCell = cells[0][0].state;
if (firstCell !== 'empty') {
var lineLength = 0;
for (var i = 0; i < gridSize; i++) {
if (cells[i][i].state === firstCell) {
lineLength++;
} else {
allSame = false;
break;
}
}
if (allSame && lineLength === 3) {
gameState = 'won';
winner = firstCell;
if (winner === 'X') {
LK.setScore(LK.getScore() + 1);
} else if (winner === 'O') {
LK.showYouWin();
}
LK.getSound('winSound').play();
// Restart game after 2 seconds
LK.setTimeout(function () {
resetGame();
}, 2000);
return;
}
}
// Check diagonal (top-right to bottom-left)
allSame = true;
firstCell = cells[0][gridSize - 1].state;
if (firstCell !== 'empty') {
var lineLength = 0;
for (var i = 0; i < gridSize; i++) {
if (cells[i][gridSize - 1 - i].state === firstCell) {
lineLength++;
} else {
allSame = false;
break;
}
}
if (allSame && lineLength === 3) {
gameState = 'won';
winner = firstCell;
if (winner === 'X') {
LK.setScore(LK.getScore() + 1);
} else if (winner === 'O') {
LK.showYouWin();
}
LK.getSound('winSound').play();
// Restart game after 2 seconds
LK.setTimeout(function () {
resetGame();
}, 2000);
return;
}
}
// Check for draw
var allFilled = true;
for (var row = 0; row < gridSize; row++) {
for (var col = 0; col < gridSize; col++) {
if (cells[row][col].state === 'empty') {
allFilled = false;
break;
}
}
if (!allFilled) break;
}
if (allFilled) {
gameState = 'draw';
}
}
function updateUI() {
if (gameState === 'won') {
statusText.setText('Player ' + winner + ' Wins!');
} else if (gameState === 'draw') {
statusText.setText('It\'s a Draw!');
} else {
statusText.setText('Player ' + currentPlayer + '\'s Turn');
}
scoreText.setText('Score: ' + LK.getScore());
}
function startGame(mode) {
gameMode = mode;
gameState = 'playing';
currentPlayer = 'X';
winner = null;
// Hide menu elements
titleText.visible = false;
multiplayerButton.visible = false;
aiButton.visible = false;
shopButton.visible = false;
// Show game elements
statusText.visible = true;
resetButton.visible = true;
backButton.visible = true;
initializeGrid();
updateUI();
}
function showMenu() {
gameState = 'menu';
gameMode = null;
// Hide game elements
statusText.visible = false;
resetButton.visible = false;
backButton.visible = false;
shopTitle.visible = false;
// Show menu elements
titleText.visible = true;
multiplayerButton.visible = true;
aiButton.visible = true;
shopButton.visible = true;
// Clear grid
for (var i = 0; i < cells.length; i++) {
for (var j = 0; j < cells[i].length; j++) {
if (cells[i][j]) {
cells[i][j].destroy();
}
}
}
cells = [];
// Clear shop items
for (var i = 0; i < shopItems.length; i++) {
shopItems[i].destroy();
}
shopItems = [];
}
function showShop() {
gameState = 'shop';
// Hide menu elements
titleText.visible = false;
multiplayerButton.visible = false;
aiButton.visible = false;
shopButton.visible = false;
// Show shop elements
shopTitle.visible = true;
backButton.visible = true;
// Create shop items
var itemsPerRow = 3;
var itemSpacing = 300;
var startX = 2048 / 2 - (itemsPerRow - 1) * itemSpacing / 2;
var startY = 2732 / 2 - 100;
for (var i = 0; i < skinData.length; i++) {
var shopItem = new ShopItem(skinData[i]);
var row = Math.floor(i / itemsPerRow);
var col = i % itemsPerRow;
shopItem.x = startX + col * itemSpacing;
shopItem.y = startY + row * 250;
shopItems.push(shopItem);
game.addChild(shopItem);
}
}
function updateShopUI() {
for (var i = 0; i < shopItems.length; i++) {
shopItems[i].updateButton();
}
scoreText.setText('Score: ' + LK.getScore());
}
function resetGame() {
gameState = 'playing';
currentPlayer = 'X';
winner = null;
for (var row = 0; row < gridSize; row++) {
for (var col = 0; col < gridSize; col++) {
cells[row][col].reset();
}
}
updateUI();
}
// Menu button functionality
multiplayerButton.down = function (x, y, obj) {
if (gameState === 'menu') {
startGame('multiplayer');
}
};
aiButton.down = function (x, y, obj) {
if (gameState === 'menu') {
startGame('ai');
}
};
shopButton.down = function (x, y, obj) {
if (gameState === 'menu') {
showShop();
}
};
// Reset button functionality
resetButton.down = function (x, y, obj) {
if (gameState === 'playing') {
resetGame();
}
};
// Back button functionality
backButton.down = function (x, y, obj) {
if (gameState === 'shop') {
showMenu();
} else {
showMenu();
}
};
function makeAIMove() {
if (gameState !== 'playing' || currentPlayer !== 'O') return;
// Simple AI: find first empty cell
var emptyCells = [];
for (var row = 0; row < gridSize; row++) {
for (var col = 0; col < gridSize; col++) {
if (cells[row][col].state === 'empty') {
emptyCells.push({
row: row,
col: col
});
}
}
}
if (emptyCells.length > 0) {
var randomIndex = Math.floor(Math.random() * emptyCells.length);
var move = emptyCells[randomIndex];
cells[move.row][move.col].placeSymbol('O');
checkWin();
if (gameState === 'playing') {
currentPlayer = 'X';
updateUI();
}
}
}
// Initialize the game - start with menu
showMenu();