Sudoku
A Sudoku puzzle game built with Preact.
by remarkablemark
HTML
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/preact/8.2.6/preact.min.js"></script>
CSS
body {
font-family: 'Lucida Grande', Helvetica, sans-serif;
}
/* Sudoku */
table {
border: 1px solid #666;
border-collapse: collapse;
}
td {
padding: 0;
}
table input {
font-size: 14px;
height: 30px;
text-align: center;
width: 30px;
}
table input:not([readonly]) {
font-weight: bold;
}
tr:nth-child(3n):not(:last-child) > td {
border-bottom: 1px solid #666;
}
td:nth-child(3n):not(:last-child) {
border-right: 1px solid #666;
}
/* difficulty */
label input {
width: 50px;
}
Babel + JSX
const { h, render, Component } = preact; /** @jsx h */
// Sudoku uses numbers 1-9
const SIZE = 9;
/**
* Generates an array with values.
*
* @param {Number} len
* @param {Function} [callback]
* @return {Array}
*/
const generateArray = (len, callback = () => {}) =>
Array.apply(null, { length: len }).map(callback);
// [1, 2, 3, 4, 5, 6, 7, 8, 9]
const NUMBERS = generateArray(SIZE, (_, index) => index + 1);
/**
* Shuffles an array.
*
* @param {Array} array
* @param {Boolean} [shouldMutate=false]
* @return {Array}
*/
const shuffleArray = (array = [], shouldMutate = false) => {
const arr = shouldMutate ? array : array.slice();
for (let i = arr.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
const temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
return arr;
};
/**
* Generates row.
*
* @return {Array}
*/
const generateRow = () => shuffleArray(NUMBERS);
/**
* Given output, checks if row is usable.
*
* @param {Number} index
* @param {Array} row
* @param {Array} output
* @return {Boolean}
*/
const isRowUsable = (index, row = [], output = []) => {
let rowIndex = output.length - 1;
for (; rowIndex > -1; rowIndex--) {
let columnIndex = output[rowIndex].length - 1;
for (; columnIndex > -1; columnIndex--) {
// check if row value exists in output column
const rowValue = row[columnIndex];
if (rowValue === output[rowIndex][columnIndex]) return false;
let rowStart = 6;
if (index < 3) {
rowStart = 0;
} else if (index < 6) {
rowStart = 3;
}
let columnStart = 6;
if (columnIndex < 3) {
columnStart = 0;
} else if (columnIndex < 6) {
columnStart = 3;
}
let section = [];
for (i = 0; i < 3; i++) {
if (output[rowStart + i] instanceof Array) {
section = section.concat(
output[rowStart + i].slice(columnStart, columnStart + 3)
);
}
}
// check if row value exists in output 3x3 section
if (section.indexOf(rowValue) !==...