Skip to content

Instantly share code, notes, and snippets.

@primaryobjects
Created October 8, 2023 20:12
Show Gist options
  • Select an option

  • Save primaryobjects/3a4dc5b66552447563b368286a810986 to your computer and use it in GitHub Desktop.

Select an option

Save primaryobjects/3a4dc5b66552447563b368286a810986 to your computer and use it in GitHub Desktop.
Sudoku in javascript, created using Bing ChatGPT GPT4 https://jsbin.com/bivoficadi/edit?js,output
import Sudoku from './Sudoku.js';
import SudokuUI from './SudokuUI.js';
// Create a new Sudoku game
let game = new Sudoku(20);
let ui = new SudokuUI(game);
// Use the UI class to create and update the Sudoku grid
ui.createGrid();
ui.updateGrid();
ui.handleUserInput();
class Sudoku {
constructor(emptyCellCount = 20) {
this.solvedBoard = this.generateSudoku();
this.board = JSON.parse(JSON.stringify(this.solvedBoard));
this.clearCells(emptyCellCount);
}
clearCells(K) {
// Remove K elements randomly to create an 'easy' puzzle
for (let i = 0; i < K; i++) {
let row, col;
do {
row = Math.floor(Math.random() * 9);
col = Math.floor(Math.random() * 9);
} while (this.board[row][col] === 0);
this.board[row][col] = 0;
}
}
generateSudoku() {
const N = 9;
let mat = [...Array(N)].map(e => Array(N).fill(0));
// Fill the diagonal boxes
this.fillDiagonal(mat);
// Fill the rest of the board
this.fillRemaining(mat, 0, 3);
return mat;
}
fillDiagonal(mat) {
const SRN = Math.sqrt(9);
for (let i = 0; i<9; i=i+SRN)
this.fillBox(mat, i, i);
}
unUsedInBox(mat, rowStart, colStart, num) {
const SRN = Math.sqrt(9);
for (let i = 0; i<SRN; i++)
for (let j = 0; j<SRN; j++)
if (mat[rowStart+i][colStart+j]===num)
return false;
return true;
}
fillBox(mat, row, col) {
const SRN = Math.sqrt(9);
let num;
for (let i=0; i<SRN; i++) {
for (let j=0; j<SRN; j++) {
do {
num = this.randomGenerator(9);
} while (!this.unUsedInBox(mat, row, col, num));
mat[row+i][col+j] = num;
}
}
}
randomGenerator(num) {
return Math.floor(Math.random()*num+1);
}
fillRemaining(mat, i, j) {
if (j >= 9 && i < 8) {
i = i + 1;
j = 0;
}
if (i >= 9 && j >= 9)
return true;
if (i < 3) {
if (j < 3)
j = 3;
} else if (i < 6) {
if (j === Math.floor(i / 3)*3)
j = j + 3;
} else {
if (j === 6) {
i = i + 1;
j = 0;
if (i >= 9)
return true;
}
}
for (let num = 1; num <= 9; num++) {
if (this.isValid(mat, i, j, num)) {
mat[i][j] = num;
if (this.fillRemaining(mat, i, j+1))
return true;
mat[i][j] = 0;
}
}
return false;
}
isValid(board, row, col, num) {
// Check if the number already exists in the same row or column
for (let i = 0; i < 9; i++) {
if (board[i][col] == num || board[row][i] == num) {
return false;
}
}
// Check if the number already exists in the same 3x3 box
let boxRow = Math.floor(row / 3) * 3;
let boxCol = Math.floor(col / 3) * 3;
for (let i = boxRow; i < boxRow + 3; i++) {
for (let j = boxCol; j < boxCol + 3; j++) {
if (board[i][j] == num) {
return false;
}
}
}
return true;
}
getEmptyPositions(board) {
let emptyPositions = [];
for (let i = 0; i < board.length; i++) {
for (let j = 0; j < board[i].length; j++) {
if (board[i][j] === 0) { // if the position is empty (contains 0)
emptyPositions.push([i, j]);
}
}
}
return emptyPositions;
}
}
export default Sudoku;
class SudokuUI {
constructor(sudoku) {
this.sudoku = sudoku;
this.sudokuGrid = document.getElementById('sudoku-grid');
this.enableHints = document.getElementById('enable-hints');
this.cells = [];
}
createGrid() {
// Create the Sudoku grid
for (let i = 0; i < 81; i++) {
const cell = document.createElement('div');
cell.classList.add('cell');
cell.contentEditable = 'true'; // Make the cell editable
cell.addEventListener('click', () => {
if (!cell.classList.contains('initial')) {
cell.textContent = ''; // Clear the cell when clicked
cell.classList.remove('incorrect');
}
});
cell.addEventListener('input', () => {
// Clear the cell if the input is not a number from 1-9
if (!/^[1-9]$/.test(cell.textContent)) {
cell.textContent = '';
}
if (this.enableHints.checked && cell.textContent && cell.textContent != this.sudoku.solvedBoard[Math.floor(i / 9)][i % 9]) {
cell.classList.add('incorrect');
} else {
cell.classList.remove('incorrect');
}
});
this.sudokuGrid.appendChild(cell);
this.cells.push(cell);
}
}
updateGrid() {
for (let i = 0; i < this.cells.length; i++) {
const value = this.sudoku.board[Math.floor(i / 9)][i % 9];
if (value !== 0) {
this.cells[i].textContent = value;
this.cells[i].classList.add('initial');
this.cells[i].contentEditable = 'false'; // Make the cell non-editable
} else {
this.cells[i].classList.add('empty');
this.cells[i].contentEditable = 'true'; // Make the cell editable
}
}
}
handleUserInput() {
// Add an event listener to the "Enable hints" checkbox
this.enableHints.addEventListener('change', () => {
for (let i = 0; i < this.cells.length; i++) {
if (this.cells[i].classList.contains('empty') && this.cells[i].textContent) {
if (this.enableHints.checked && this.cells[i].textContent != this.sudoku.solvedBoard[Math.floor(i / 9)][i % 9]) {
this.cells[i].classList.add('incorrect');
} else {
this.cells[i].classList.remove('incorrect');
}
}
}
});
}
}
export default SudokuUI;
@primaryobjects

Copy link
Copy Markdown
Author

sudoku

@primaryobjects

Copy link
Copy Markdown
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment