数独校验器Bug排查:无效返回False正确但有效不返回True
数独校验器有效时无法返回true的问题分析
我正在完成编程入门课程的期末项目,数独校验器存在问题:无效数独能正确返回false,但有效数独却无法返回true,已经花了一小时排查仍没头绪,求分析。
以下是相关代码:
//puzzle let puzzle = [[ 8,9,5, 7,4,2, 1,3,6 ], [ 2,7,1, 9,6,3, 4,8,5 ], [ 4,6,3, 5,8,1, 7,9,2 ], [ 9,3,4, 6,1,7, 2,5,8 ], [ 5,1,7, 2,3,8, 9,6,4 ], [ 6,8,2, 4,5,9, 3,7,1 ], [ 1,5,9, 8,7,4, 6,2,3 ], [ 7,4,6, 3,2,5, 8,1,9 ], [ 3,2,8, 1,9,6, 5,4,7 ]]; //puzzle 2 let puzzleTwo = [[ 8,9,5,7,4,2,1,3,6 ], [ 8,7,1,9,6,3,4,8,5 ], [ 4,6,3,5,8,1,7,9,2 ], [ 9,3,4,6,1,7,2,5,8 ], [ 5,1,7,2,3,8,9,6,4 ], [ 6,8,2,4,5,9,3,7,1 ], [ 1,5,9,8,7,4,6,2,3 ], [ 7,4,6,3,2,5,8,1,9 ], [ 3,2,8,1,9,6,5,4,7 ]]; //DO NOT EDIT ABOVE function getRow(puzzle, row) { // YOUR CODE return puzzle[row]; } function getColumn(puzzle, col) { // YOUR CODE let column = []; for (let i = 0; i < puzzle.length; i++) { column.push(puzzle[i][col]); } return column; } function getSection(puzzle, x, y) { // YOUR CODE let numSubgrid = []; x *= 3; y *= 3; for (let i = y; i < y + 3; i++) { for (let j = x; j < x + 3; j++) { numSubgrid.push(puzzle[i][j]) } } return numSubgrid; } function includes1To9(arr) { // YOUR CODE for (let i = 0; i < arr.length; i++) { for (let j = 0; j < arr.length; j++) { if (i !== j && arr[i] === arr[j]) { return false; } } } return true; } function sudokuIsValid(puzzle) { // YOUR CODE if (includes1To9(getRow) || includes1To9(getColumn) || includes1To9(getSection) !== true) { return false; } return true; }
问题根源分析
1. sudokuIsValid函数逻辑完全错误
- 代码直接将
getRow、getColumn、getSection函数本身传入includes1To9,而非调用这些函数获取数独的行、列、区块数据。函数作为参数传入时,includes1To9遍历的是函数对象的属性,完全不是预期的数独数字数组。 - 判断逻辑颠倒:数独要求所有行、所有列、所有区块都必须符合规则,只要有一个不符合则无效;当前代码的逻辑是只要其中一个函数(作为参数)满足
includes1To9就返回false,完全不符合校验要求。
2. includes1To9函数存在缺陷
- 该函数仅检查数组内是否有重复值,但未验证数组是否包含1-9的所有数字。例如数组
[1,2,3,4,5,6,7,8,0]没有重复值,但包含非法数字0,这个函数会错误返回true,不符合数独规则。
修正后的代码
修正includes1To9函数
function includes1To9(arr) { // 数独的行/列/区块必须是9个元素 if (arr.length !== 9) return false; // 用Set去重,同时检查是否包含1-9所有数字 const numSet = new Set(arr); for (let num = 1; num <= 9; num++) { if (!numSet.has(num)) { return false; } } return true; }
修正sudokuIsValid函数
function sudokuIsValid(puzzle) { // 校验所有行 for (let row = 0; row < 9; row++) { if (!includes1To9(getRow(puzzle, row))) { return false; } } // 校验所有列 for (let col = 0; col < 9; col++) { if (!includes1To9(getColumn(puzzle, col))) { return false; } } // 校验所有3x3区块(x和y取值0-2,对应3x3区块的索引) for (let x = 0; x < 3; x++) { for (let y = 0; y < 3; y++) { if (!includes1To9(getSection(puzzle, x, y))) { return false; } } } // 所有校验通过,返回true return true; }
验证说明
- 修正后的
includes1To9会同时检查数组长度、是否包含1-9所有数字(自动排除重复,因为Set会去重,若有重复则Set大小小于9,循环检查1-9时会发现缺失)。 sudokuIsValid会遍历每一行、每一列、每一个3x3区块,逐一校验,只要有一个不符合规则就返回false,全部通过则返回true。
内容的提问来源于stack exchange,提问作者Cluff3rs
相关产品推荐
相关产品推荐

