我已经成功将一个js数独生成器转换成了一个ts生成器进行练习,唯一的问题是如何让它只输出完整的数独盘面。现在,它无论盘面是否完整都会输出,我必须刷新直到出现一个正确的盘面。
我不确定如何编写以下函数,以便它只输出完整的盘面:
function fillBoard(puzzleArray: number[][]): number[][] { if (nextEmptyCell(puzzleArray).colIndex === -1) return puzzleArray; let emptyCell = nextEmptyCell(puzzleArray); for (var num in shuffle(numArray)) { if (safeToPlace(puzzleArray, emptyCell, numArray[num])) { puzzleArray[emptyCell.rowIndex][emptyCell.colIndex] = numArray[num]; fillBoard(puzzleArray); } } return puzzleArray; }
这是我的所有代码:
import { Box } from "./Box"; export function Board() { let BLANK_BOARD = [ [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], ]; let NEW_BOARD = [ [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], ]; let counter: number = 0; let check: number[]; const numArray: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9]; function rowSafe( puzzleArray: number[][], emptyCell: { rowIndex: number; colIndex: number }, num: number ): boolean { return puzzleArray[emptyCell.rowIndex].indexOf(num) == -1; } function colSafe( puzzleArray: number[][], emptyCell: { rowIndex: number; colIndex: number }, num: number ): boolean { let test = puzzleArray.flat(); for (let i = emptyCell.colIndex; i < test.length; i += 9) { if (test[i] === num) { return false; } } return true; } function regionSafe( puzzleArray: number[][], emptyCell: { rowIndex: number; colIndex: number }, num: number ): boolean { const rowStart: number = emptyCell.rowIndex - (emptyCell.rowIndex % 3); const colStart: number = emptyCell.colIndex - (emptyCell.colIndex % 3); for (let i = 0; i < 3; i++) { for (let j = 0; j < 3; j++) { if (puzzleArray[rowStart + i][colStart + j] === num) { return false; } } } return true; } console.log(rowSafe(BLANK_BOARD, { rowIndex: 4, colIndex: 6 }, 5)); console.log(colSafe(BLANK_BOARD, { rowIndex: 2, colIndex: 3 }, 4)); console.log(regionSafe(BLANK_BOARD, { rowIndex: 5, colIndex: 6 }, 5)); function safeToPlace( puzzleArray: number[][], emptyCell: { rowIndex: number; colIndex: number }, num: number ): boolean { return ( regionSafe(puzzleArray, emptyCell, num) && rowSafe(puzzleArray, emptyCell, num) && colSafe(puzzleArray, emptyCell, num) ); } console.log(safeToPlace(BLANK_BOARD, { rowIndex: 5, colIndex: 6 }, 5)); function nextEmptyCell(puzzleArray: number[][]): { colIndex: number; rowIndex: number; } { let emptyCell = { rowIndex: -1, colIndex: -1 }; for (let i = 0; i < 9; i++) { for (let j = 0; j < 9; j++) { if (puzzleArray[i][j] === 0) { return { rowIndex: i, colIndex: j }; } } } return emptyCell; } function shuffle(array: number[]): number[] { // using Array sort and Math.random let shuffledArr = array.sort(() => 0.5 - Math.random()); return shuffledArr; } function fillBoard(puzzleArray: number[][]): number[][] { if (nextEmptyCell(puzzleArray).colIndex === -1) return puzzleArray; let emptyCell = nextEmptyCell(puzzleArray); for (var num in shuffle(numArray)) { if (safeToPlace(puzzleArray, emptyCell, numArray[num])) { puzzleArray[emptyCell.rowIndex][emptyCell.colIndex] = numArray[num]; fillBoard(puzzleArray); } else { puzzleArray[emptyCell.rowIndex][emptyCell.colIndex] = 0; } } return puzzleArray; } console.log(nextEmptyCell(BLANK_BOARD)); NEW_BOARD = fillBoard(BLANK_BOARD); function fullBoard(puzzleArray: number[][]): boolean { return puzzleArray.every((row) => row.every((col) => col !== 0)); } return ( <div style={{ height: "450px", width: "450px", display: "inline-grid", gap: "10px", gridTemplateColumns: "repeat(9,50px)", gridTemplateRows: "repeat(9,50px)", position: "absolute", top: "30px", left: "0px", right: "0px", marginLeft: "auto", marginRight: "auto", }} > {NEW_BOARD.flat().map((item) => ( <Box i={item} /> ))} </div> ); }
当发现在一个空白单元格中无法添加有效数字时,该函数将返回一个不完整的数独板。
为了解决这个问题,你的函数应该:
puzzleArray
,因为该数组在原地进行了修改,所以调用者可以访问到这些变化。NEW_BOARD = fillBoard(BLANK_BOARD);
的副作用是NEW_BOARD
和BLANK_BOARD
引用了同一个数独板,而且它不再是空白的(所以名称有误导性)。下面是修改后的实现:
调用者应该检查返回值,但如果你从一个空白板开始,保证会得到
true
作为返回值。所以你可以这样做: