创建数独时页面无响应

时间:2019-10-28 08:37:41

标签: javascript sudoku

我正在尝试创建正确的数独。

我创建了3种方法来检查数字,一种方法是生成数独。

createSudoku()尝试创建一个数独。

colContainsNumber():检查col是否包含我生成的随机数

rowContainsNumber():与colContainsNumber相同,仅用于行

squareContainsNumber():检查一个块是否包含随机数。

createSudoku()中,我生成一个随机数,并使用while循环不断生成一个新数,直到“ contain-Methods”均未返回true为止(对于“是,该行中已经存在该数字,则为true”等)

使用所有方法自己创建数独作品。 (例如,如果我仅使用rowContainsNumber,我将得到一个数独,其中没有任何行包含相同的数字,等等。)

但是如果同时使用这三种方法,页面将不会响应。

我试图更改在while循环中调用的方法的顺序,但并没有做太多改变,因为如果仅调用其中一个方法,这些方法就可以正常工作。

function createSudoku() {
    var sudoku = [
        [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]
    ];
    for (var i = 0; i < 9; i++) {
        for (var j = 0; j < 9; j++) {
            //generate a random number between 1 and 9
            var randomNumber = Math.floor((Math.random() * 9) + 1);

            /*Keep generate a random number, until the square doesn't contain 
            the number. This is the loop where I'm supposed to use all three 
            Methods (colContains-, rowContains- and squareContainsNumber) but 
            the page doesn't respond if I use all three of them. If I only use 
            one like you can see now, the generation works fine*/

            while (squareContainsNumber(sudoku, i, j, randomNumber)) {
                randomNumber = Math.floor((Math.random() * 9) + 1);

            }
            sudoku[i][j] = randomNumber;
            solvedSudoku[i][j] = randomNumber;
        }
    }
    return sudoku;
}

function rowContainsNumber(sudoku, col, number) {
    for (var i = 0; i < 9; i++) {
        if (sudoku[col][i] == number) {
            return true;
        }
    }
    return false;
}

function colContainsNumber(sudoku, row, number) {
    for (var i = 0; i < 9; i++) {
        if (sudoku[i][row] == number) {
            return true;
        }
    }
    return false;
}

function squareContainsNumber(sudoku, col, row, number)
{
    var minRow, maxRow, minCol, maxCol = 0;
    //Check which column the loop is in, then set the min and max column so I 
    //can get the range of the block
    switch (col) {
        case 0:
        case 1:
        case 2:
            minCol = 0;
            maxCol = 2;
            break;
        case 3:
        case 4:
        case 5:
            minCol = 3;
            maxCol = 5;
            break;
        case 6:
        case 7:
        case 8:
            minCol = 6;
            maxCol = 8;
            break;
        default:
            break;
    }
    //Check which row the loop is in, then set the min and max row so I 
    //can get the range of the block
    switch (row) {
        case 0:
        case 1:
        case 2:
            minRow = 0;
            maxRow = 2;
            break;
        case 3:
        case 4:
        case 5:
            minRow = 3;
            maxRow = 5;
            break;
        case 6:
        case 7:
        case 8:
            minRow = 6;
            maxRow = 8;
            break;
        default:
            break;
    }

   //loop through the square and check If the square contains the random number
    for (var i = minRow; i <= maxRow; i++) {
        for (var j = minCol; j <= maxCol; j++) {
            if (sudoku[i][j] == number)
                return true;
        }
    }

    return false;
}

预期结果将是正确的数独,其中没有行,没有列且没有正方形包含相同的数字。

但是就像我已经说过的那样,页面只是没有响应,可能是因为while循环花费的时间太长了。

1 个答案:

答案 0 :(得分:0)

基于不重复复制行,列或框中现有数字的约束条件,随机选择数独单元格值的算法不完整。人们可能会遵循这些约束条件,但仍然会发现一个空单元格之前已将所有1-9位数字分配为行,单元格或框中的邻居。

当发布的代码达到此条件时,它将尝试为拼图生成一个新的随机数字,而不检查是否可能。由于该页面无法继续尝试另一个无法正常工作的随机数字,因此该页面可能会挂起。

此代码段检查一个空单元格的房屋(行,列或盒子)是否确实有未使用的数字,如果没有,请重试该难题:

var attempts = 0;

function puzzle( sudoku) {
    ++attempts;

    function House() {
        this.index = Object.create(null);
    }
    House.prototype.add = function( n) {
            if( this.index[n]) {
                return 0;
            }
            this.index[n] = true;
            return n;
        };
    
    let houses = [];
    for( var i = 0; i < 27; ++i) {
        houses [i] = new House();
    }
    let rowOf = index =>  Math.floor(index/9);
    let colOf = index =>  index%9;
    let boxOf = index =>  3 * Math.floor( rowOf( index)/3) + Math.floor( colOf( index)/3);
    
    function randomDigit( index) {
        let rowHouse = houses[ rowOf( index)];
        let colHouse = houses[ 9 + colOf(index)];
        let boxHouse = houses[ 18 + boxOf(index)];
        let domain = [1,2,3,4,5,6,7,8,9].reduce( function( array, digit) {
            if( !(rowHouse.index[ digit] || colHouse.index[digit] || boxHouse.index[ digit])) {
                array.push( digit);
            }
            return array;
        }, []);
        let digit = domain.length ? domain[ Math.floor( domain.length * Math.random())] : 0;
        if( digit) {
            rowHouse.add(digit);
            colHouse.add(digit);
            boxHouse.add(digit);
        }
        return digit;
    }

    var sudoku = [];
    for( var index = 0 ; index < 81; ++index) {
        let digit = randomDigit( index);
        if( digit == 0) {
            break;
        }
        sudoku[ index] = digit;
    }

    if( sudoku.length == 81) {
        return sudoku;
    }
    return puzzle();
}

const sudoku = puzzle();

console.log( "Attempts = " + attempts);
if( sudoku.length < 81) {
    sudoku.push('x');
    console.log("invalid sudoku");
}
for( let i = 0; i < 81; i += 9) {
    console.log( sudoku.slice( i, i+9).toString());
}

运行该代码段表明,可能需要进行大量尝试才能获得结果。

在网上快速浏览表明,这可能是生成完整拼图的一种不寻常的方法,如果没有进一步的经验,我无法评论其用途。

相关问题