源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

Javascript 实现的数独解题算法网页实例

  • 时间:2022-09-01 06:27 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:Javascript 实现的数独解题算法网页实例
1)当我们拿到一个题目时,首先会根据已经知道的条件,进行数据的初步整理和分析。 相当于填写出9宫格里,所有的“确定项”,以及标记“可能选项”。 function refreshStat() 2)此后,思考会进入 猜测/验证 的循环阶段。 在9宫格中,可以对于“可能选项”进行尝试,验证是否违背现有条件。 每一个新的分支,最后的结果无非是两种,答案/出错。
[u]复制代码[/u] 代码如下:
                while(true){                     var a=setOne();                     var b=refreshStat();                     if(!a||b){ //如果 a==false 或者 b==ture,则可以跳出循环                         break;                     }                 }
实际人脑思考的过程,也是要先遍历选项较少的分支。 所以,程序实现上也是 确定点/2叉分支/3叉分支/.... 3)当所有的路径搜索下来,答案不是唯一的情况,是和数独游戏的宗旨相悖的。 以下部分是全部代码,为方便阅读,调试信息未删除。
[u]复制代码[/u] 代码如下:
<html>  <head>   <title>数独解题程序</title> <meta http-equiv="Content-Type" content="text/html; charset=GBK" />   <script>    function keygo(evt,obj){        key = window .event?evt.keyCode:evt.which;        var next=obj.tabIndex ;        var inputs=document.getElementsByTagName("input");        if (key==38){//↑            if (next -9>=0 ) {                inputs[next-9].select()            }        }        if (key==40){//↓            if (next +9<81 ) {                inputs[next+9].select()            }        }        if (key==37){//←            if (next -1>=0 ) {                inputs[next-1].select()            }        }        if (key==39){//→            if(next+1<81)inputs[next+1].select();        }    }   </script>  </head> <body onload="init();"> <div id="sodukuTable"></div><input type=button name="cal" onclick="calculate()" value="计算"> <input type=button name="clear" onclick="clearGrid()" value="清空"> <br><span><textarea id="gtxt" cols="19" rows="10">004502006 000000005 002014007 008000012 070080050 930020700 600190200 020000000 300208500</textarea></span> <input type=button name="cal" onclick="paste()" value="粘贴" >可以文本拷贝到下框中后点粘贴,从左到右从上往下的81个数字序列,未填为0,中间非数字字符将忽略<br> <span></span><br><span id="statusDiv"></span><span id="log"></span>   <script>    var maxRow =9;    var maxCol = 9;    var strTbody = ["<table id='sodukuTable' border='0'><tbody>"];    for(var i = 0; i < maxRow; i++){     strTbody.push("<tr>");      for(var j = 0; j < maxCol; j++){       strTbody.push("<td style='border-left:"+(j%3==0?1:0)             +"px solid black ;border-right:"+(j%3==2?1:0)             +"px solid black;border-top:"+(i%3==0?1:0)             +"px solid black;border-bottom:"+(i%3==2?1:0)+"px solid black;' ><input style='width:20px;' tabindex='"+(i*9+j)         +"'onclick='check(this);' onKeyUp='return keygo(event,this)'type='text' id='input"+(i*9+j)+"'name='n"+(i*9+j)+"'value='"+i+j+"' ></td>");      }     strTbody.push("</tr>");    }    strTbody.push("</tbody></table>");    var sTbody = ["<table border='1'><tbody>"];    for(var i = 0; i < maxRow; i++){     sTbody.push("<tr>");      for(var j = 0; j < maxCol; j++){       sTbody.push("<td style='border-left:"+(j%3==0?1:0)             +"px solid black ;border-right:"+(j%3==2?1:0)             +"px solid black;border-top:"+(i%3==0?1:0)             +"px solid black;border-bottom:"+(i%3==2?1:0)+"px solid black;'><div style='width:25px;height:25px'  id='status"+(i*9+j)+"'name='div"+i+j+"'  ></div></td>");      }     sTbody.push("</tr>");    }    sTbody.push("</tbody></table>");    var obj = document.getElementById("sodukuTable");    obj.innerHTML = strTbody.join("");    var obj2 = document.getElementById("statusDiv");    var grid=[        [5, 7, 0, 1, 2, 0, 0, 0, 0],     [0, 0, 0, 0, 0, 0, 0, 0, 0],     [0, 0, 6, 7, 0, 0, 0, 8, 0],     [3, 0, 4, 0, 0, 9, 0, 7, 0],     [0, 2, 0, 0, 7, 0, 0, 5, 0],     [0, 1, 0, 3, 0, 0, 9, 0, 2],     [0, 8, 0, 0, 0, 2, 1, 0, 0],     [0, 0, 0, 0, 0, 0, 0, 0, 0],     [0, 0, 0, 0, 5, 4, 0, 6, 3]];    var candidatNum=[];    var columns=[];    var rows=[];    var blook=[];    var papers=0;    var discards=0;    var success=false;    var steps = new Array();    var log1 = document.getElementById("statusDiv"); function Step(current1,arrys){         this.temp1=new Array();         this.step=[arrys[0],arrys[1],arrys[2]];         for (var i = 0; i < 9; i++)             {                 this.temp1[i]=new Array();                 for (var j = 0; j < 9; j++)                     {                     this.temp1[i][j]=current1[i][j];                     }                 } } out(grid); init(); function push( current1,  i,  j,  n) {         var s = new Step(current1, [ i, j, n ]);         steps.push(s); } function pop(){         var step = steps.pop();         discards ++;         grid=step.temp1;         grid[step.step[0]][step.step[1]] = step.step[2];                 var timeline = document.getElementById('PaperList');                 timeline.value += ('discard: ['+discards+']:['+papers+']n');                 timeline.scrollTop = timeline.scrollHeight;         return step; } function check(obj){     if(obj.value==0)return;     for(var i=0;i<9;i++){         for(var j=0;j<9;j++){             var text = document.getElementById("input"+(i*9+j));             if(text.value==obj.value){                 text.style.background="green";             }else{                 text.style.background="";             }         }     } } function CheckNumInput(array,num,  x,  y)  {     //  目标:     //      冲突检查  参数 array:矩阵 num:检测值 x/y:检测位置     //      行列宫均无冲突,return true;     //            发现冲突,return false;     if (((rows[x] & (1 << num)) == 0) && (columns[y] & (1 << num)) == 0         && (blook[parseInt(x / 3) * 3 + parseInt(y / 3)] & (1 << num)) == 0) {         return true;         }     return false; } function out(array){     var result=true;     for (var i = 0; i < 9; i++)         {             for (var j = 0; j < 9; j++)             {         document.getElementById("input"+(i*9+j)).value=array[i][j];                 if(array[i][j]==0)result=false;             }         }         return result; } function setOne(){     var result = false;     //目标:     //    遍历矩阵,当前是否可以简单刷新,或者已经可以发现出错.     for (var i = 0; i < 9; i++) {         for (var j = 0; j < 9; j++) {             //目标:             // (grid[i][j] == 0 && candidatNum[i][j][0] == 0)  >> 没有候选数字,出错了             // (candidatNum[i][j][0] == 1)                     >> 候选数字唯一             // CheckNumInput(grid,candidatNum[i][j][10],i,j)   >> 检查此数字是否符合逻辑             // 判断 没有候选数字||最后一个候选数字不符合逻辑的条件,  从这里回退或者返回出错             if (grid[i][j] == 0 && candidatNum[i][j][0] == 0||                (candidatNum[i][j][0] == 1&&!CheckNumInput(grid,candidatNum[i][j][10],i,j))) {                     if (grid[i][j] == 0) {                        result = false;                     }                     if (steps.length>0) {// 回退                         pop();           // 当前标签已经被证明逻辑错误,废弃                         return true;                     } else {                         if (!success) {                             alert("栈为空 结束!");    //题目出错,结束                             }                         return false;                     }             }             if (candidatNum[i][j][0] == 1) {              //唯一选择                 grid[i][j] = candidatNum[i][j][10];       //  更新矩阵                 refreshStat3(candidatNum[i][j][10],i,j);  //  更新行列宫                 candidatNum[i][j][0] = 0;                 //  标记已选                 result = true;                 continue;             }         }     }     if (result == false) { //对于(candidatNum[i][j][0] != 1)的情况,进行筛选         return choose();     }     return result; } function refreshStat3( num, x, y) {   //  更新行列宫         rows[x] |= 1<<num;         columns[y] |= 1<<num;         blook[parseInt(x / 3) * 3 + parseInt(y / 3)] |= 1 << num ; } /*********************  * 矩阵 数据分析  * 统计 剩余可选项  *********************/ function refreshStat(){     var over = true;     //  目标:     //      分解行/列/宫     for (var i = 0; i < 9; i++) {         rows[i] = 0;    //行         columns[i] = 0; //列         blook[i] = 0;   //宫         for (var j = 0; j < 9; j++) {             if (grid[i][j] != 0) {                 rows[i] |= 1 << grid[i][j];             } else {                 rows[i] &= ~(1 << grid[i][j]);             }             if (grid[j][i] != 0) {                 columns[i] |= 1 << grid[j][i];             } else {                 columns[i] &= ~(1 << grid[j][i]);             }             if (grid[parseInt(i / 3) * 3 + parseInt(j / 3)][i % 3 * 3 + j % 3] != 0) {                 blook[i] |= 1 << grid[parseInt(i / 3 )* 3 + parseInt(j / 3)][i % 3 * 3 + j % 3];             }         }     }     //  目标:     //      遍历矩阵,进行候选标记candidatNum[i][j][0]     //      candidatNum[i][j][0] = 0;    >>>>    已有确定值     //      candidatNum[i][j][0] = k;    >>>>    可能值数目     //      candidatNum[i][j][1] = 987654321x    2进制数位表示的可选数字     for (var i = 0; i < 9; i++) {         for (var j = 0; j < 9; j++) {         if (grid[i][j] != 0) {             candidatNum[i][j][0] = 0;             continue;         }         var size = 0;         over = false;         for (var k = 1; k < 10; k++) {             if (CheckNumInput(grid, k, i, j)) {                 candidatNum[i][j][1] |= 1 << k;                 candidatNum[i][j][10] = k;                 over = false;                 size++;             } else {                 candidatNum[i][j][1] &= ~(1 << k);             }         }         candidatNum[i][j][0] = size;  //标记剩余选项数目     }     }     return over; } function calculate(){  //功能入口     //读取数据     var start=new Date();     for (var i = 0; i < 9; i++)         {                for (var j = 0; j < 9; j++)             {                 var text = document.getElementById("input"+(i*9+j));                 grid[i][j]=parseInt(text.value);         }     }     //刷新网格        refreshStat();     out(grid);     //计算矩阵     while(true){         var a=setOne();         var b=refreshStat();         if(!a||b){ //如果 a==false 或者 b==ture,则可以跳出循环             break;         }     }     out(grid);    //答案     alert("用时:"+(new Date()-start)+"ms");     success = true;     //计算结束     //验证答案是否唯一     if (papers != discards){             if (steps.length>0) {// 回退                 pop();           // 当前标签废弃                 //计算矩阵                 while(true){                     var a=setOne();                     var b=refreshStat();                     if(!a||b){ //如果 a==false 或者 b==ture,则可以跳出循环                         break;                     }                 }                 if (b) {                     alert("答案不唯一!记录!");                     out(grid);    //答案                     }                 else {                     alert("答案唯一!!");    //答案唯一                 }             } else {                 alert("出错 结束!");                 return false;             }     } } function clearGrid(){     for (var i = 0; i < 9; i++){         for (var j = 0; j < 9; j++){             grid[i][j]=0;             document.getElementById("input"+(i*9+j)).value=grid[i][j];         }     }     out(grid); } function init(){      for (var i = 0; i < 9; i++)         {    candidatNum[i]=new Array();             for (var j = 0; j < 9; j++)             {    candidatNum[i][j]=new Array();         for (var k = 0; k < 11; k++)                 {    candidatNum[i][j][k]=0;         }         }     } } function choose() {     //目标:     //    遍历矩阵,从当前位置建立搜索分支.     var binarynode = false;     for (var i = 0; i < 9; i++) {         for (var j = 0; j < 9; j++) {     //      2叉树分支:     //      如果在某位置有两种可能,选项1/选项2     //      则假设是选项1,并进行验算,同时按选项2生成一个新的标签             if (candidatNum[i][j][0] == 2) {// 有2种选择                 binarynode = true;                 var found = -1;                 for (var k = 1; k < 10; k++) {                     if  ((candidatNum[i][j][1] & (1 << k)) > 0) {                         if (found > 0) {                             papers ++;                             var timeline = document.getElementById('PaperList');                             timeline.value += ('add papers:'+papers+':'+i+' '+j+' '+k+'n');                             timeline.scrollTop = timeline.scrollHeight;                             push(grid, i, j, k);                         }else{                             found = k;                         }                     }                 }                 grid[i][j] = found;                 candidatNum[i][j][0] = 0; // 在当前标签上标记已选                             var timeline = document.getElementById('PaperList');                             timeline.value += ('TRY CURRENT:'+i+' '+j+' '+found+'n');                             timeline.scrollTop = timeline.scrollHeight;                 return true;             }         }     }     if (!binarynode) {     var timeline = document.getElementById('PaperList');     timeline.value += ('2叉分支未找到!n');     timeline.scrollTop = timeline.scrollHeight;         for (var i = 0; i < 9; i++) {             for (var j = 0; j < 9; j++) {         // 2叉树查找失败时,启动3叉树分支,作为扩充,还可以启动3叉树分支:         //      如果在某位置有三种可能,选项1/选项2/选项3         //      则假设是选项1,并进行验算,同时按选项2生成一个新的标签                 if (candidatNum[i][j][0] == 3) {// 有3种选择                             var timeline = document.getElementById('PaperList');                             timeline.value += ('发现3叉分支!n');                             timeline.scrollTop = timeline.scrollHeight;                     binarynode = true;                     var found = -1;                     for (var k = 1; k < 10; k++) {                         if  ((candidatNum[i][j][1] & (1 << k)) > 0) {                             if (found > 0) {                                 papers ++;                             var timeline = document.getElementById('PaperList');                             timeline.value += ('add papers:'+papers+':'+i+' '+j+' '+k+'n');                             timeline.scrollTop = timeline.scrollHeight;                                 push(grid, i, j, k);                             }else{                                 found = k;                             }                         }                     }                     grid[i][j] = found;                     candidatNum[i][j][0] = 0; // 在当前标签上标记已选                             var timeline = document.getElementById('PaperList');                             timeline.value += ('TRY CURRENT:'+i+' '+j+' '+found+'n');                             timeline.scrollTop = timeline.scrollHeight;                     return true;                 }             }         }     }     return false; } function paste(){     var gridstr= document.getElementById("gtxt").value;     var a = gridstr.replace(/[^0-9]/g,'');     if(a.length!=81){        alert("数据格式不正确:n"+gridstr);        return;     }     for (var i = 0; i < 9; i++)         {             for (var j = 0; j < 9; j++){                 grid[i][j]=a.charAt(i*9+j);                 document.getElementById("input"+(i*9+j)).value=grid[i][j];         }     }     out(grid);     papers = 0;     discards = 0;     success = false;     steps = new Array(); }   </script>   建议使用IE浏览器,F12开启调试模式<br> <br><span> <textarea id="PaperList" cols="30" rows="20" style="position:absolute;left:550px;"></textarea></span>  </body> </html>
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部