new nonogram.Editor( 4, 8, 'edit1', { theme: { threshold: 0.2, isMeshed: true, boldMeshGap: 2 }})
new nonogram.Editor( 2, 4, 'edit2', { grid: [[1, 0, 1, 0], [0, 1, 0, 1]] })
new nonogram.Game( [[1,1], [1,1]], [[1], [1], [1], [1]], 'play1', { theme: { filledColor: '#0c6', correctColor: '#0c6' }})
new nonogram.Game( [[1,1], [1,1]], [[2], [], [2], []], 'play2')
new nonogram.Solver( [[1,1], [1,1]], [[2], [], [2], []], 'solve1', { delay: 200, onError: (error) => console.error(error) } ).solve()
The following nonogram produces a valid QRCode that, once decoded, reveals the text: You are the BEST!
window._row = [ [7, 2, 2, 7], [1, 1, 1, 2, 1, 1], [1, 3, 1, 3, 1, 1, 3, 1], [1, 3, 1, 2, 1, 1, 3, 1], [1, 3, 1, 2, 1, 3, 1], [1, 1, 2, 2, 1, 1], [7, 1, 1, 1, 7], [2], [2, 3, 2, 1, 4], [1, 1, 3, 3, 2, 1], [3, 1, 3, 2, 2], [1, 1, 1, 3, 1, 1], [1, 5, 1, 1, 1, 1], [1, 1, 1, 1, 3, 1], [7, 1, 1], [1, 1, 1, 1, 1, 1, 1, 1], [1, 3, 1, 1, 1, 2, 2], [1, 3, 1, 2, 1, 2, 1, 1], [1, 3, 1, 1, 1, 2], [1, 1, 2, 1, 1], [7, 1, 3, 1], ]
window._column = [ [7, 1, 2, 7], [1, 1, 1, 1, 1, 1], [1, 3, 1, 1, 1, 3, 1], [1, 3, 1, 1, 1, 1, 3, 1], [1, 3, 1, 1, 1, 1, 3, 1], [1, 1, 2, 1, 1], [7, 1, 1, 1, 7], [4], [4, 2, 2, 2, 2, 2], [1, 2, 1, 1, 1, 2, 3], [1, 2, 2, 2], [2, 3, 1, 1, 1, 1, 1], [3, 3, 2, 3, 1, 1], [1, 1, 3, 2], [7, 1, 1], [1, 1, 1, 1, 1, 1, 1], [1, 3, 1, 3, 2, 3], [1, 3, 1, 2, 2, 1, 1], [1, 3, 1, 1, 1, 1, 1], [1, 1, 5, 3], [7, 1, 1, 2, 1], ]
new nonogram.Solver( window._row, window._column, 'solve2', { onError: (error) => console.error(error) } ).solve()
Here is an example showing how to use listeners to create nonogram.Game
and nonogram.Solver
instances automatically.
function f(grid) { var m = +document.getElementById('m').value, n = +document.getElementById('n').value; if ((grid && grid.length) || window.advEditor1) { if (grid && grid.length) { m = grid.length; n = grid[0].length; } else { grid = window.advEditor1.grid; } } window.advEditor1 = new nonogram.Editor( m, n, 'adv-edit1', { threshold: +document.getElementById('threshold').value, grid: grid, onHintChange(row, column) { new nonogram.Game(row, column, 'adv-play1', { theme: { boldMeshGap: 0 } }) new nonogram.Solver(row, column, 'adv-solve1', { onError: (error) => console.error(error) }).solve() } }) document.getElementById('pattern-download-link').onclick = function () { this.href = gridToBase64Img(window.advEditor1.grid) } document.getElementById('hints-grid-download-link').onclick = function () { this.href = document.getElementById('adv-play1').toDataURL() } document.getElementById('hints-as-json-link').onclick = function () { this.href = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(window.advEditor1.hints)) } } document.getElementById('m').addEventListener('change', f) document.getElementById('n').addEventListener('change', f) document.getElementById('threshold').addEventListener('change', f) document.getElementById('load-from-file').addEventListener('change', () => gridFromImgFile((grid) => { document.getElementById('m').value = grid.length; document.getElementById('n').value = grid[0].length; f(grid) })) f()
This example shows how to solve the nonogram by given hints, which are separated by newlines and commas.
Put your rows in the first textarea, columns in the second textarea.
One row (or column) a line, numbers separated by any non-numerical characters.
To represent an empty row (or column), you can use an empty line, or a line including the number 0
as well.
However, empty lines at two ends will be dropped, since they are really unnecessary.
If the process end with an error, please check your input carefully.
Delay: 0~500ms. Setting delay=0 disables step-by-step solution, with a much smaller time cost.
Parse JSON-like strings or anything.
function parseArray(text) {
return text
.replace(/[^\d\n]+/g, ' ')
.trim()
.split('\n')
.map(row => (row.match(/\d+/g) || [])
.map(parseFloat)
.filter(Math.sign))
}
document.getElementById('btn-solve2').addEventListener('click', () => {
new nonogram.Solver(
parseArray(document.getElementById('txt-row-hints2').value),
parseArray(document.getElementById('txt-col-hints2').value),
'adv-solve2',
{ theme: {
isMeshed: true,
isBoldMeshOnly: true,
isMeshOnTop: true },
delay: +document.getElementById('delay').value,
onError: (error) => console.error(error),
onSuccess(time) {
document.getElementById('timecost').innerHTML = 'Solved in ' + time + 'ms.'
} }).solve()
})
The qrcode lib is used in this example to try to build a solvable grid in the form of a valid QRCode that, once decoded, reveals some text:
function rebuildQRCodeSolver() { var text = document.getElementById('text').value; var qrcode = QRCode.create(text, { errorCorrectionLevel: 'L' }); // Getting the hints for this grid: var size = qrcode.modules.size; var data = [].slice.call(qrcode.modules.data); var grid = []; while(data.length) { grid.push(data.splice(0, size)); } var hints = nonogram.Editor.getHints(grid); // Displaying a Solver that will check if a unique solution exists: var downloadPatternLink = document.getElementById('qrcode-pattern-download-link'); var downloadJsonLink = document.getElementById('qrcode-hints-as-json-link'); var downloadGridLink = document.getElementById('qrcode-hints-grid-download-link'); var solver = new nonogram.Solver(hints.row, hints.column, 'edit-qrcode', { onSuccess(duration, iterations, solved) { downloadPatternLink.style.display = solved ? 'block' : 'none'; downloadJsonLink.style.display = solved ? 'block' : 'none'; downloadGridLink.style.display = solved ? 'block' : 'none'; if (solved) { // == the grid has a unique solution downloadPatternLink.onclick = function () { this.href = gridToBase64Img(grid) } downloadJsonLink.onclick = function () { this.href = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(hints)) } // Using a hidden Game/canvas in order to produce a downloable grid: class GameWithoutController extends nonogram.Game { printController() {} // We hide the "controller", i.e. the bottom-right switch button } new GameWithoutController(hints.row, hints.column, 'hidden-game', { theme: { boldMeshGap: 0 } }) downloadGridLink.onclick = function () { this.href = document.getElementById('hidden-game').toDataURL() } } }, }); solver.solve() } window.rebuildQRCodeSolver = rebuildQRCodeSolver rebuildQRCodeSolver()