js实现数独算法(优化版本)

a 夏天 提交于 2020-11-03 07:21:35

 

最近打算用小程序开发个数独游戏,所以研究了下数独可行性数据的算法。具体代码如下:

 

var chess;//棋盘所有棋子的状态
var chessStack = [];//缓存点
//创建棋盘
function creatChess()
{
    chess = [];
    for (var i = 0; i < 9; i++)
    {
        chess[i] = [];
        for (var j = 0; j < 9; j++)
        {
            chess[i][j] = {num:0,fixed:false,temp:[1,2,3,4,5,6,7,8,9]};
        }
    }
}

//打印棋盘
function printChess()
{
    var say = "";
    for (var i = 0; i < 9; i++)
    {
        for (var j = 0; j < 9; j++)
        {
            say += chess[i][j].num;
        }
        say += '\n';
    }
    console.log(say);
}

//预先设置互不影响的九宫格位置数字
function setArea(a,b)
{
    var temp = [1,2,3,4,5,6,7,8,9];//每个小九宫格包含的九个数字
    for (var i = a; i < b; i++)
    {
        for (var j = a; j < b; j++)
        {
            var len = temp.length;//temp剩下的长度
            var index = getRandom(len);//随机抽取一个
            chess[i][j].num = temp[index];//赋值
            chess[i][j].fixed = true;//赋值
            temp.splice(index,1);//删除已赋值的
        }
    }
}

//设定数字 可以求解
function setPre(r,c,v)
{
    chess[r][c] = {num:v,fixed:true,temp:[]};
}

//获取一个随机数字下标
function getRandom(a)
{
    return Math.floor(Math.random()*a);
}

//初始化棋盘
function chessInit()
{
    for (var i = 0; i < 9; i++)
    {
        for (var j = 0; j < 9; )
        {
            //当数字确定了 则下一个 不然随机取一个
            if (!chess[i][j].fixed)
            {
                var len = chess[i][j].temp.length;//temp剩下的长度
                //当还有可选数字
                if (len > 0)
                {
                    var index = getRandom(len);//随机抽取一个
                    chess[i][j].num = chess[i][j].temp[index];//赋值
                    chess[i][j].temp.splice(index,1);//删除已赋值的
                    chessStack.push([i,j,JSON.parse(JSON.stringify(chess))]);//存储
                    chess[i][j].fixed = true;//变为确定
                    if(!checkTempNum(i,j))
                    {
                        var cs = chessStack.pop();//退格
                        i = cs[0];
                        j = cs[1];
                        chess = cs[2];//取出棋盘存储点
                    }
                }
                else
                {
                    // 当没有可选数字了
                    var cs = chessStack.pop();//退格
                    i = cs[0];
                    j = cs[1];
                    chess = cs[2];//取出棋盘存储点
                }
            }
            else
            {
                j++;//进一个
            }
        }
    }
}


//删除特定元素
function removeByValue(r,c,v)
{
    if (chess[r][c].num == v)
    {
        return false;//冲突了
    }
    if (chess[r][c].fixed)
    {
        return true;//已经确定了 则无需删除了
    }
    var len = chess[r][c].temp.length;
    for (var i = 0; i < len; i++)
    {
        if (chess[r][c].temp[i] == v)
        {
            chess[r][c].temp.splice(i,1);//删除备选数字
            break;//退出
        }
    }
    return chess[r][c].temp.length==0?false:true;//没有确定而且没有备选元素了 那么返回错误
}

//移除相关20格备选列表某数字
function checkTempNum(r,c)
{
    var i,j;
    var num = chess[r][c].num;//要移除的数字
    //检查列
    for (i = 0; i < 9 ; i++)
    {
        if (i != r && !removeByValue(i,c,num)) return false;//移除备选数字和判定数字合法性
    }
    //检查行
    for (j = 0; j < 9 ; j++)
    {
        if(j != c && !removeByValue(r,j,num)) return false;//移除备选数字和判定数字合法性
    }
    //检查小九宫
    var left = Math.floor(r/3)*3;//得出小九宫的左上角坐标
    var top = Math.floor(c/3)*3;//得出小九宫的左上角坐标
    for (i = left; i < left+3; i++)
    {
        for (j = top; j < top+3; j++)
        {
            if (i == r && j == c)
            {
                continue;//同一个格子跳过
            }
            if(!removeByValue(i,j,num)) return false;//移除备选数字和判定数字合法性
        }
    }
    return true;
}


//初始化
function chess()
{
    creatChess();//创建棋盘
    // setArea(0,3);//随机设置左上角九宫格数字
    // setArea(3,6);//随机设置中间九宫格数字
    // setArea(6,9);//随机设置右下角九宫格数字
    setPre(0,2,5);
    setPre(0,3,3);
    setPre(1,0,8);
    setPre(1,7,2);
    setPre(2,1,7);
    setPre(2,4,1);
    setPre(2,6,5);
    setPre(3,0,4);
    setPre(3,5,5);
    setPre(3,6,3);
    setPre(4,1,1);
    setPre(4,4,7);
    setPre(4,8,6);
    setPre(5,2,3);
    setPre(5,3,2);
    setPre(5,7,8);
    setPre(6,1,6);
    setPre(6,3,5);
    setPre(6,8,9);
    setPre(7,2,4);
    setPre(7,7,3);
    setPre(8,5,9);
    setPre(8,6,7);
    chessInit();//初始化棋盘
    printChess();//打印棋盘
}

chess();

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!