/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var MenuButton = Container.expand(function (text, callback) {
var self = Container.call(this);
self.buttonText = new Text2(text, {
size: 60,
fill: 0xFFFFFF
});
self.buttonText.anchor.set(0.5, 0.5);
// Calculate button size based on text dimensions
var textWidth = self.buttonText.width;
var textHeight = self.buttonText.height;
var buttonWidth = Math.max(400, textWidth + 60); // minimum 400px width, or text width + padding
var buttonHeight = Math.max(120, textHeight + 40); // minimum 120px height, or text height + padding
// Create background with calculated size
self.background = LK.getAsset('menuButton', {
width: buttonWidth,
height: buttonHeight
});
self.addChild(self.background);
// Position text at center of button
self.buttonText.x = buttonWidth / 2;
self.buttonText.y = buttonHeight / 2;
self.addChild(self.buttonText);
self.callback = callback;
self.down = function (x, y, obj) {
tween(self, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100
});
if (self.callback) {
self.callback();
}
LK.getSound('select').play();
};
self.up = function (x, y, obj) {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
};
return self;
});
var NumberButton = Container.expand(function (number) {
var self = Container.call(this);
self.number = number;
self.background = self.attachAsset('numberButton', {});
self.numberText = new Text2(number.toString(), {
size: 60,
fill: 0xFFFFFF
});
self.numberText.anchor.set(0.5, 0.5);
self.numberText.x = 90;
self.numberText.y = 60;
self.addChild(self.numberText);
self.down = function (x, y, obj) {
if (gameState.selectedCell) {
gameState.placeNumber(self.number);
LK.getSound('place').play();
}
};
return self;
});
var SudokuCell = Container.expand(function (row, col, isGiven) {
var self = Container.call(this);
self.row = row;
self.col = col;
self.value = 0;
self.isGiven = isGiven || false;
self.isSelected = false;
self.hasConflict = false;
self.background = self.attachAsset('cellBackground', {});
self.numberText = new Text2('', {
size: 80,
fill: self.isGiven ? "#666666" : "#000000"
});
self.numberText.anchor.set(0.5, 0.5);
self.numberText.x = 90;
self.numberText.y = 90;
self.addChild(self.numberText);
self.setValue = function (value) {
self.value = value;
self.numberText.setText(value > 0 ? value.toString() : '');
};
self.setSelected = function (selected) {
self.isSelected = selected;
self.updateVisual();
};
self.setConflict = function (conflict) {
self.hasConflict = conflict;
self.updateVisual();
};
self.updateVisual = function () {
if (self.hasConflict) {
self.background.tint = 0xffcdd2;
} else if (self.isSelected) {
self.background.tint = 0xbbdefb;
} else if (self.isGiven) {
self.background.tint = 0xe8e8e8;
} else {
self.background.tint = 0xf0f0f0;
}
};
self.down = function (x, y, obj) {
if (!self.isGiven) {
gameState.selectCell(self.row, self.col);
LK.getSound('select').play();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xf8f8f8
});
/****
* Game Code
****/
// Game state management
var gameState = {
currentScreen: 'menu',
// 'menu', 'game'
difficulty: 'easy',
grid: [],
selectedCell: null,
selectedRow: -1,
selectedCol: -1,
weeklyProgress: storage.weeklyProgress || 0,
hintsUsed: 0
};
// Initialize storage defaults
if (!storage.weeklyProgress) storage.weeklyProgress = 0;
if (!storage.easyCompleted) storage.easyCompleted = 0;
if (!storage.mediumCompleted) storage.mediumCompleted = 0;
if (!storage.hardCompleted) storage.hardCompleted = 0;
// Sudoku generation and validation
var sudokuGenerator = {
generatePuzzle: function generatePuzzle(difficulty) {
var grid = this.createFullGrid();
var clues = this.getClueCount(difficulty);
return this.removeNumbers(grid, 81 - clues);
},
createFullGrid: function createFullGrid() {
var grid = [];
for (var i = 0; i < 9; i++) {
grid[i] = [];
for (var j = 0; j < 9; j++) {
grid[i][j] = 0;
}
}
// Fill diagonal 3x3 boxes first
for (var box = 0; box < 9; box += 3) {
this.fillBox(grid, box, box);
}
// Fill remaining cells
this.solveSudoku(grid);
return grid;
},
fillBox: function fillBox(grid, row, col) {
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
this.shuffle(numbers);
var index = 0;
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
grid[row + i][col + j] = numbers[index++];
}
}
},
shuffle: function shuffle(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
},
solveSudoku: function solveSudoku(grid) {
for (var row = 0; row < 9; row++) {
for (var col = 0; col < 9; col++) {
if (grid[row][col] === 0) {
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
this.shuffle(numbers);
for (var i = 0; i < numbers.length; i++) {
var num = numbers[i];
if (this.isValid(grid, row, col, num)) {
grid[row][col] = num;
if (this.solveSudoku(grid)) {
return true;
}
grid[row][col] = 0;
}
}
return false;
}
}
}
return true;
},
isValid: function isValid(grid, row, col, num) {
// Check row
for (var x = 0; x < 9; x++) {
if (grid[row][x] === num) return false;
}
// Check column
for (var x = 0; x < 9; x++) {
if (grid[x][col] === num) return false;
}
// Check 3x3 box
var startRow = Math.floor(row / 3) * 3;
var startCol = Math.floor(col / 3) * 3;
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
if (grid[i + startRow][j + startCol] === num) return false;
}
}
return true;
},
removeNumbers: function removeNumbers(grid, count) {
var puzzle = [];
for (var i = 0; i < 9; i++) {
puzzle[i] = [];
for (var j = 0; j < 9; j++) {
puzzle[i][j] = grid[i][j];
}
}
var attempts = count;
while (attempts > 0) {
var row = Math.floor(Math.random() * 9);
var col = Math.floor(Math.random() * 9);
if (puzzle[row][col] !== 0) {
puzzle[row][col] = 0;
attempts--;
}
}
return puzzle;
},
getClueCount: function getClueCount(difficulty) {
switch (difficulty) {
case 'easy':
return Math.floor(Math.random() * 6) + 45;
// 45-50
case 'medium':
return Math.floor(Math.random() * 10) + 35;
// 35-44
case 'hard':
return Math.floor(Math.random() * 10) + 25;
// 25-34
default:
return 45;
}
}
};
// UI Elements
var menuContainer = new Container();
var gameContainer = new Container();
var sudokuCells = [];
var numberButtons = [];
// Create menu
function createMenu() {
var title = new Text2('Dr. Sudoku', {
size: 120,
fill: 0x2196F3
});
title.anchor.set(0.5, 0.5);
title.x = 1024;
title.y = 400;
menuContainer.addChild(title);
var subtitle = new Text2('Logic Master', {
size: 60,
fill: 0x666666
});
subtitle.anchor.set(0.5, 0.5);
subtitle.x = 1024;
subtitle.y = 500;
menuContainer.addChild(subtitle);
var easyButton = new MenuButton('Easy Play', function () {
startGame('easy');
});
easyButton.x = 1024 - easyButton.background.width / 2;
easyButton.y = 700;
menuContainer.addChild(easyButton);
var mediumButton = new MenuButton('Medium Play', function () {
startGame('medium');
});
mediumButton.x = 1024 - mediumButton.background.width / 2;
mediumButton.y = 850;
menuContainer.addChild(mediumButton);
var hardButton = new MenuButton('Hard Play', function () {
startGame('hard');
});
hardButton.x = 1024 - hardButton.background.width / 2;
hardButton.y = 1000;
menuContainer.addChild(hardButton);
var weeklyButton = new MenuButton('Weekly Challenge', function () {
startGame('weekly');
});
weeklyButton.x = 1024 - weeklyButton.background.width / 2;
weeklyButton.y = 1150;
menuContainer.addChild(weeklyButton);
}
// Create game UI
function createGameUI() {
// Create grid background
var gridBg = LK.getAsset('sudokuGrid', {});
gridBg.x = 124;
gridBg.y = 200;
gameContainer.addChild(gridBg);
// Create cells
sudokuCells = [];
for (var row = 0; row < 9; row++) {
sudokuCells[row] = [];
for (var col = 0; col < 9; col++) {
var cell = new SudokuCell(row, col);
cell.x = 124 + col * 200;
cell.y = 200 + row * 200;
sudokuCells[row][col] = cell;
gameContainer.addChild(cell);
}
}
// Create grid lines
// Horizontal lines
for (var i = 0; i <= 9; i++) {
var line = LK.getAsset(i % 3 === 0 ? 'thickGridLine' : 'gridLine', {});
line.x = 124;
line.y = 200 + i * 200 - (i % 3 === 0 ? 4 : 2);
gameContainer.addChild(line);
}
// Vertical lines
for (var i = 0; i <= 9; i++) {
var line = LK.getAsset(i % 3 === 0 ? 'thickGridLine' : 'gridLine', {});
line.x = 124 + i * 200 - (i % 3 === 0 ? 4 : 2);
line.y = 200;
line.rotation = Math.PI / 2;
gameContainer.addChild(line);
}
// Create number buttons
numberButtons = [];
for (var i = 1; i <= 9; i++) {
var button = new NumberButton(i);
button.x = 124 + (i - 1) * 200;
button.y = 2100;
numberButtons.push(button);
gameContainer.addChild(button);
}
// Create hint button
var hintButton = new Container();
var hintBg = hintButton.attachAsset('hintButton', {});
var hintText = new Text2('Hint', {
size: 40,
fill: 0xFFFFFF
});
hintText.anchor.set(0.5, 0.5);
hintText.x = 100;
hintText.y = 40;
hintButton.addChild(hintText);
hintButton.x = 924;
hintButton.y = 2250;
hintButton.down = function () {
provideHint();
};
gameContainer.addChild(hintButton);
// Create back button
var backButton = new Container();
var backBg = backButton.attachAsset('hintButton', {});
var backText = new Text2('Menu', {
size: 40,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.x = 100;
backText.y = 40;
backButton.addChild(backText);
backButton.x = 124;
backButton.y = 2250;
backButton.down = function () {
showMenu();
};
gameContainer.addChild(backButton);
}
// Game functions
function startGame(difficulty) {
gameState.currentScreen = 'game';
gameState.difficulty = difficulty;
gameState.hintsUsed = 0;
// Generate puzzle
var puzzle = sudokuGenerator.generatePuzzle(difficulty);
gameState.grid = puzzle;
// Update cells
for (var row = 0; row < 9; row++) {
for (var col = 0; col < 9; col++) {
var cell = sudokuCells[row][col];
var value = puzzle[row][col];
cell.isGiven = value > 0;
cell.setValue(value);
cell.updateVisual();
}
}
showGame();
}
function showMenu() {
gameState.currentScreen = 'menu';
menuContainer.visible = true;
gameContainer.visible = false;
}
function showGame() {
gameState.currentScreen = 'game';
menuContainer.visible = false;
gameContainer.visible = true;
}
gameState.selectCell = function (row, col) {
// Deselect previous cell
if (gameState.selectedCell) {
gameState.selectedCell.setSelected(false);
}
// Select new cell
gameState.selectedRow = row;
gameState.selectedCol = col;
gameState.selectedCell = sudokuCells[row][col];
gameState.selectedCell.setSelected(true);
};
gameState.placeNumber = function (number) {
if (!gameState.selectedCell || gameState.selectedCell.isGiven) {
return;
}
var row = gameState.selectedRow;
var col = gameState.selectedCol;
// Place number
gameState.grid[row][col] = number;
gameState.selectedCell.setValue(number);
// Check for conflicts
checkConflicts();
// Check if puzzle is complete
if (isPuzzleComplete()) {
setTimeout(function () {
LK.getSound('victory').play();
// Update statistics
switch (gameState.difficulty) {
case 'easy':
storage.easyCompleted = (storage.easyCompleted || 0) + 1;
break;
case 'medium':
storage.mediumCompleted = (storage.mediumCompleted || 0) + 1;
break;
case 'hard':
storage.hardCompleted = (storage.hardCompleted || 0) + 1;
break;
case 'weekly':
storage.weeklyProgress = Math.min(9, (storage.weeklyProgress || 0) + 1);
break;
}
// Generate new puzzle
startGame(gameState.difficulty);
}, 500);
}
};
function checkConflicts() {
// Clear all conflicts first
for (var row = 0; row < 9; row++) {
for (var col = 0; col < 9; col++) {
sudokuCells[row][col].setConflict(false);
}
}
// Check for conflicts
for (var row = 0; row < 9; row++) {
for (var col = 0; col < 9; col++) {
var value = gameState.grid[row][col];
if (value > 0) {
var hasConflict = !sudokuGenerator.isValid(gameState.grid, row, col, value);
if (hasConflict) {
sudokuCells[row][col].setConflict(true);
}
}
}
}
}
function isPuzzleComplete() {
// Check if all cells are filled
for (var row = 0; row < 9; row++) {
for (var col = 0; col < 9; col++) {
if (gameState.grid[row][col] === 0) {
return false;
}
}
}
// Check if there are any conflicts
for (var row = 0; row < 9; row++) {
for (var col = 0; col < 9; col++) {
if (sudokuCells[row][col].hasConflict) {
return false;
}
}
}
return true;
}
function provideHint() {
if (!gameState.selectedCell || gameState.selectedCell.isGiven || gameState.selectedCell.value > 0) {
return;
}
var row = gameState.selectedRow;
var col = gameState.selectedCol;
// Find valid number for this cell
for (var num = 1; num <= 9; num++) {
if (sudokuGenerator.isValid(gameState.grid, row, col, num)) {
gameState.placeNumber(num);
gameState.hintsUsed++;
break;
}
}
}
// Initialize UI
createMenu();
createGameUI();
// Add containers to game
game.addChild(menuContainer);
game.addChild(gameContainer);
// Show menu initially
showMenu();
// Create ads bar at bottom
var adsBar = new Container();
var adsBg = LK.getAsset('gameBackground', {
width: 2048,
height: 150,
color: 0x333333
});
adsBar.addChild(adsBg);
var adsText = new Text2('Advertisement Space', {
size: 32,
fill: 0xFFFFFF
});
adsText.anchor.set(0.5, 0.5);
adsText.x = 1024;
adsText.y = 75;
adsBar.addChild(adsText);
LK.gui.bottom.addChild(adsBar);
// Create score display
var scoreText = new Text2('', {
size: 40,
fill: 0x666666
});
scoreText.anchor.set(0.5, 0);
scoreText.x = 1024;
scoreText.y = 50;
function updateScoreDisplay() {
var text = '';
switch (gameState.difficulty) {
case 'easy':
text = 'Easy: ' + (storage.easyCompleted || 0) + ' completed';
break;
case 'medium':
text = 'Medium: ' + (storage.mediumCompleted || 0) + ' completed';
break;
case 'hard':
text = 'Hard: ' + (storage.hardCompleted || 0) + ' completed';
break;
case 'weekly':
text = 'Weekly: ' + (storage.weeklyProgress || 0) + '/9 completed';
break;
}
scoreText.setText(text);
}
LK.gui.top.addChild(scoreText);
game.update = function () {
updateScoreDisplay();
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var MenuButton = Container.expand(function (text, callback) {
var self = Container.call(this);
self.buttonText = new Text2(text, {
size: 60,
fill: 0xFFFFFF
});
self.buttonText.anchor.set(0.5, 0.5);
// Calculate button size based on text dimensions
var textWidth = self.buttonText.width;
var textHeight = self.buttonText.height;
var buttonWidth = Math.max(400, textWidth + 60); // minimum 400px width, or text width + padding
var buttonHeight = Math.max(120, textHeight + 40); // minimum 120px height, or text height + padding
// Create background with calculated size
self.background = LK.getAsset('menuButton', {
width: buttonWidth,
height: buttonHeight
});
self.addChild(self.background);
// Position text at center of button
self.buttonText.x = buttonWidth / 2;
self.buttonText.y = buttonHeight / 2;
self.addChild(self.buttonText);
self.callback = callback;
self.down = function (x, y, obj) {
tween(self, {
scaleX: 0.95,
scaleY: 0.95
}, {
duration: 100
});
if (self.callback) {
self.callback();
}
LK.getSound('select').play();
};
self.up = function (x, y, obj) {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 100
});
};
return self;
});
var NumberButton = Container.expand(function (number) {
var self = Container.call(this);
self.number = number;
self.background = self.attachAsset('numberButton', {});
self.numberText = new Text2(number.toString(), {
size: 60,
fill: 0xFFFFFF
});
self.numberText.anchor.set(0.5, 0.5);
self.numberText.x = 90;
self.numberText.y = 60;
self.addChild(self.numberText);
self.down = function (x, y, obj) {
if (gameState.selectedCell) {
gameState.placeNumber(self.number);
LK.getSound('place').play();
}
};
return self;
});
var SudokuCell = Container.expand(function (row, col, isGiven) {
var self = Container.call(this);
self.row = row;
self.col = col;
self.value = 0;
self.isGiven = isGiven || false;
self.isSelected = false;
self.hasConflict = false;
self.background = self.attachAsset('cellBackground', {});
self.numberText = new Text2('', {
size: 80,
fill: self.isGiven ? "#666666" : "#000000"
});
self.numberText.anchor.set(0.5, 0.5);
self.numberText.x = 90;
self.numberText.y = 90;
self.addChild(self.numberText);
self.setValue = function (value) {
self.value = value;
self.numberText.setText(value > 0 ? value.toString() : '');
};
self.setSelected = function (selected) {
self.isSelected = selected;
self.updateVisual();
};
self.setConflict = function (conflict) {
self.hasConflict = conflict;
self.updateVisual();
};
self.updateVisual = function () {
if (self.hasConflict) {
self.background.tint = 0xffcdd2;
} else if (self.isSelected) {
self.background.tint = 0xbbdefb;
} else if (self.isGiven) {
self.background.tint = 0xe8e8e8;
} else {
self.background.tint = 0xf0f0f0;
}
};
self.down = function (x, y, obj) {
if (!self.isGiven) {
gameState.selectCell(self.row, self.col);
LK.getSound('select').play();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0xf8f8f8
});
/****
* Game Code
****/
// Game state management
var gameState = {
currentScreen: 'menu',
// 'menu', 'game'
difficulty: 'easy',
grid: [],
selectedCell: null,
selectedRow: -1,
selectedCol: -1,
weeklyProgress: storage.weeklyProgress || 0,
hintsUsed: 0
};
// Initialize storage defaults
if (!storage.weeklyProgress) storage.weeklyProgress = 0;
if (!storage.easyCompleted) storage.easyCompleted = 0;
if (!storage.mediumCompleted) storage.mediumCompleted = 0;
if (!storage.hardCompleted) storage.hardCompleted = 0;
// Sudoku generation and validation
var sudokuGenerator = {
generatePuzzle: function generatePuzzle(difficulty) {
var grid = this.createFullGrid();
var clues = this.getClueCount(difficulty);
return this.removeNumbers(grid, 81 - clues);
},
createFullGrid: function createFullGrid() {
var grid = [];
for (var i = 0; i < 9; i++) {
grid[i] = [];
for (var j = 0; j < 9; j++) {
grid[i][j] = 0;
}
}
// Fill diagonal 3x3 boxes first
for (var box = 0; box < 9; box += 3) {
this.fillBox(grid, box, box);
}
// Fill remaining cells
this.solveSudoku(grid);
return grid;
},
fillBox: function fillBox(grid, row, col) {
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
this.shuffle(numbers);
var index = 0;
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
grid[row + i][col + j] = numbers[index++];
}
}
},
shuffle: function shuffle(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
},
solveSudoku: function solveSudoku(grid) {
for (var row = 0; row < 9; row++) {
for (var col = 0; col < 9; col++) {
if (grid[row][col] === 0) {
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
this.shuffle(numbers);
for (var i = 0; i < numbers.length; i++) {
var num = numbers[i];
if (this.isValid(grid, row, col, num)) {
grid[row][col] = num;
if (this.solveSudoku(grid)) {
return true;
}
grid[row][col] = 0;
}
}
return false;
}
}
}
return true;
},
isValid: function isValid(grid, row, col, num) {
// Check row
for (var x = 0; x < 9; x++) {
if (grid[row][x] === num) return false;
}
// Check column
for (var x = 0; x < 9; x++) {
if (grid[x][col] === num) return false;
}
// Check 3x3 box
var startRow = Math.floor(row / 3) * 3;
var startCol = Math.floor(col / 3) * 3;
for (var i = 0; i < 3; i++) {
for (var j = 0; j < 3; j++) {
if (grid[i + startRow][j + startCol] === num) return false;
}
}
return true;
},
removeNumbers: function removeNumbers(grid, count) {
var puzzle = [];
for (var i = 0; i < 9; i++) {
puzzle[i] = [];
for (var j = 0; j < 9; j++) {
puzzle[i][j] = grid[i][j];
}
}
var attempts = count;
while (attempts > 0) {
var row = Math.floor(Math.random() * 9);
var col = Math.floor(Math.random() * 9);
if (puzzle[row][col] !== 0) {
puzzle[row][col] = 0;
attempts--;
}
}
return puzzle;
},
getClueCount: function getClueCount(difficulty) {
switch (difficulty) {
case 'easy':
return Math.floor(Math.random() * 6) + 45;
// 45-50
case 'medium':
return Math.floor(Math.random() * 10) + 35;
// 35-44
case 'hard':
return Math.floor(Math.random() * 10) + 25;
// 25-34
default:
return 45;
}
}
};
// UI Elements
var menuContainer = new Container();
var gameContainer = new Container();
var sudokuCells = [];
var numberButtons = [];
// Create menu
function createMenu() {
var title = new Text2('Dr. Sudoku', {
size: 120,
fill: 0x2196F3
});
title.anchor.set(0.5, 0.5);
title.x = 1024;
title.y = 400;
menuContainer.addChild(title);
var subtitle = new Text2('Logic Master', {
size: 60,
fill: 0x666666
});
subtitle.anchor.set(0.5, 0.5);
subtitle.x = 1024;
subtitle.y = 500;
menuContainer.addChild(subtitle);
var easyButton = new MenuButton('Easy Play', function () {
startGame('easy');
});
easyButton.x = 1024 - easyButton.background.width / 2;
easyButton.y = 700;
menuContainer.addChild(easyButton);
var mediumButton = new MenuButton('Medium Play', function () {
startGame('medium');
});
mediumButton.x = 1024 - mediumButton.background.width / 2;
mediumButton.y = 850;
menuContainer.addChild(mediumButton);
var hardButton = new MenuButton('Hard Play', function () {
startGame('hard');
});
hardButton.x = 1024 - hardButton.background.width / 2;
hardButton.y = 1000;
menuContainer.addChild(hardButton);
var weeklyButton = new MenuButton('Weekly Challenge', function () {
startGame('weekly');
});
weeklyButton.x = 1024 - weeklyButton.background.width / 2;
weeklyButton.y = 1150;
menuContainer.addChild(weeklyButton);
}
// Create game UI
function createGameUI() {
// Create grid background
var gridBg = LK.getAsset('sudokuGrid', {});
gridBg.x = 124;
gridBg.y = 200;
gameContainer.addChild(gridBg);
// Create cells
sudokuCells = [];
for (var row = 0; row < 9; row++) {
sudokuCells[row] = [];
for (var col = 0; col < 9; col++) {
var cell = new SudokuCell(row, col);
cell.x = 124 + col * 200;
cell.y = 200 + row * 200;
sudokuCells[row][col] = cell;
gameContainer.addChild(cell);
}
}
// Create grid lines
// Horizontal lines
for (var i = 0; i <= 9; i++) {
var line = LK.getAsset(i % 3 === 0 ? 'thickGridLine' : 'gridLine', {});
line.x = 124;
line.y = 200 + i * 200 - (i % 3 === 0 ? 4 : 2);
gameContainer.addChild(line);
}
// Vertical lines
for (var i = 0; i <= 9; i++) {
var line = LK.getAsset(i % 3 === 0 ? 'thickGridLine' : 'gridLine', {});
line.x = 124 + i * 200 - (i % 3 === 0 ? 4 : 2);
line.y = 200;
line.rotation = Math.PI / 2;
gameContainer.addChild(line);
}
// Create number buttons
numberButtons = [];
for (var i = 1; i <= 9; i++) {
var button = new NumberButton(i);
button.x = 124 + (i - 1) * 200;
button.y = 2100;
numberButtons.push(button);
gameContainer.addChild(button);
}
// Create hint button
var hintButton = new Container();
var hintBg = hintButton.attachAsset('hintButton', {});
var hintText = new Text2('Hint', {
size: 40,
fill: 0xFFFFFF
});
hintText.anchor.set(0.5, 0.5);
hintText.x = 100;
hintText.y = 40;
hintButton.addChild(hintText);
hintButton.x = 924;
hintButton.y = 2250;
hintButton.down = function () {
provideHint();
};
gameContainer.addChild(hintButton);
// Create back button
var backButton = new Container();
var backBg = backButton.attachAsset('hintButton', {});
var backText = new Text2('Menu', {
size: 40,
fill: 0xFFFFFF
});
backText.anchor.set(0.5, 0.5);
backText.x = 100;
backText.y = 40;
backButton.addChild(backText);
backButton.x = 124;
backButton.y = 2250;
backButton.down = function () {
showMenu();
};
gameContainer.addChild(backButton);
}
// Game functions
function startGame(difficulty) {
gameState.currentScreen = 'game';
gameState.difficulty = difficulty;
gameState.hintsUsed = 0;
// Generate puzzle
var puzzle = sudokuGenerator.generatePuzzle(difficulty);
gameState.grid = puzzle;
// Update cells
for (var row = 0; row < 9; row++) {
for (var col = 0; col < 9; col++) {
var cell = sudokuCells[row][col];
var value = puzzle[row][col];
cell.isGiven = value > 0;
cell.setValue(value);
cell.updateVisual();
}
}
showGame();
}
function showMenu() {
gameState.currentScreen = 'menu';
menuContainer.visible = true;
gameContainer.visible = false;
}
function showGame() {
gameState.currentScreen = 'game';
menuContainer.visible = false;
gameContainer.visible = true;
}
gameState.selectCell = function (row, col) {
// Deselect previous cell
if (gameState.selectedCell) {
gameState.selectedCell.setSelected(false);
}
// Select new cell
gameState.selectedRow = row;
gameState.selectedCol = col;
gameState.selectedCell = sudokuCells[row][col];
gameState.selectedCell.setSelected(true);
};
gameState.placeNumber = function (number) {
if (!gameState.selectedCell || gameState.selectedCell.isGiven) {
return;
}
var row = gameState.selectedRow;
var col = gameState.selectedCol;
// Place number
gameState.grid[row][col] = number;
gameState.selectedCell.setValue(number);
// Check for conflicts
checkConflicts();
// Check if puzzle is complete
if (isPuzzleComplete()) {
setTimeout(function () {
LK.getSound('victory').play();
// Update statistics
switch (gameState.difficulty) {
case 'easy':
storage.easyCompleted = (storage.easyCompleted || 0) + 1;
break;
case 'medium':
storage.mediumCompleted = (storage.mediumCompleted || 0) + 1;
break;
case 'hard':
storage.hardCompleted = (storage.hardCompleted || 0) + 1;
break;
case 'weekly':
storage.weeklyProgress = Math.min(9, (storage.weeklyProgress || 0) + 1);
break;
}
// Generate new puzzle
startGame(gameState.difficulty);
}, 500);
}
};
function checkConflicts() {
// Clear all conflicts first
for (var row = 0; row < 9; row++) {
for (var col = 0; col < 9; col++) {
sudokuCells[row][col].setConflict(false);
}
}
// Check for conflicts
for (var row = 0; row < 9; row++) {
for (var col = 0; col < 9; col++) {
var value = gameState.grid[row][col];
if (value > 0) {
var hasConflict = !sudokuGenerator.isValid(gameState.grid, row, col, value);
if (hasConflict) {
sudokuCells[row][col].setConflict(true);
}
}
}
}
}
function isPuzzleComplete() {
// Check if all cells are filled
for (var row = 0; row < 9; row++) {
for (var col = 0; col < 9; col++) {
if (gameState.grid[row][col] === 0) {
return false;
}
}
}
// Check if there are any conflicts
for (var row = 0; row < 9; row++) {
for (var col = 0; col < 9; col++) {
if (sudokuCells[row][col].hasConflict) {
return false;
}
}
}
return true;
}
function provideHint() {
if (!gameState.selectedCell || gameState.selectedCell.isGiven || gameState.selectedCell.value > 0) {
return;
}
var row = gameState.selectedRow;
var col = gameState.selectedCol;
// Find valid number for this cell
for (var num = 1; num <= 9; num++) {
if (sudokuGenerator.isValid(gameState.grid, row, col, num)) {
gameState.placeNumber(num);
gameState.hintsUsed++;
break;
}
}
}
// Initialize UI
createMenu();
createGameUI();
// Add containers to game
game.addChild(menuContainer);
game.addChild(gameContainer);
// Show menu initially
showMenu();
// Create ads bar at bottom
var adsBar = new Container();
var adsBg = LK.getAsset('gameBackground', {
width: 2048,
height: 150,
color: 0x333333
});
adsBar.addChild(adsBg);
var adsText = new Text2('Advertisement Space', {
size: 32,
fill: 0xFFFFFF
});
adsText.anchor.set(0.5, 0.5);
adsText.x = 1024;
adsText.y = 75;
adsBar.addChild(adsText);
LK.gui.bottom.addChild(adsBar);
// Create score display
var scoreText = new Text2('', {
size: 40,
fill: 0x666666
});
scoreText.anchor.set(0.5, 0);
scoreText.x = 1024;
scoreText.y = 50;
function updateScoreDisplay() {
var text = '';
switch (gameState.difficulty) {
case 'easy':
text = 'Easy: ' + (storage.easyCompleted || 0) + ' completed';
break;
case 'medium':
text = 'Medium: ' + (storage.mediumCompleted || 0) + ' completed';
break;
case 'hard':
text = 'Hard: ' + (storage.hardCompleted || 0) + ' completed';
break;
case 'weekly':
text = 'Weekly: ' + (storage.weeklyProgress || 0) + '/9 completed';
break;
}
scoreText.setText(text);
}
LK.gui.top.addChild(scoreText);
game.update = function () {
updateScoreDisplay();
};