最近打算用小程序开发个数独游戏,所以研究了下数独可行性数据的算法。具体代码如下:
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();
来源:oschina
链接:https://my.oschina.net/u/4343669/blog/4229946