javascript的數獨自動填滿演算法代碼

來源:互聯網
上載者:User

  數獨遊戲的一段代碼,忘記了用的是深度優先還是廣度優先的搜尋演算法,使用了些機率上的演算法改進,share下,怕過幾年不小心刪除了, g.js 貌似另外一篇博文中有,這裡就不貼了。
  
  當初這段代碼頗有些緣由,古人有曰:山不在高有仙則名,水不在深有龍則靈。程式設計語言本無類,不要抱怨某些語言如何如何,關鍵的問題還是在人。這段代碼比很多native code要快,不信各位可自行驗證

  本來不想繼續寫了,回想下還是做些筆記吧,以免時間長了自己都忘記了,備忘下這段代碼使用的技巧:


1.js代碼使用CloneNode(true)複製DOM節點(包含子節點)建立多個九宮格,並用CSS將其渲染成不同的效果;

  

2.物件導向的設計結構;mvc分層設計


3.推斷的時候使用可能值排除法,當無法明確推斷的時候,尋找可能值個數最少的節點開始(這個是重點),先壓棧儲存狀態,然後嘗試填充,繼續推斷或猜測,直到得到答案,或者出錯復原排除錯誤值後向另一個方向繼續


<!-- copy all right , barenx@163.com -->


<html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"><meta http-equiv="Description" content="there is one shoudu online demo"><meta http-equiv="Keywords" content="shoudu;javascript;css;web design;dom"><meta http-equiv="Auther" content="barenx"><title>sodu demo--PowerBy Barenx</title><script language="javascript" type="text/javascript" src="g.js"></script><style type="text/css">body{text-align:center;margin:5px;}/*big display number block*/#tb td, #hx td{width:47px;height:47px;font-size:17px; font-family:Verdana, Arial, Helvetica, sans-serif; vertical-align:middle; text-align:center; work-break:break-all;border:1px #FFFFFF solid;}#tb td{border:#ffffff dotted 1px;font-weight:bold;}#hx td{cursor:pointer;background:#99FFFF;}/*main div block*/#lp1{width:auto;height:auto;float:left;border:1px #00CC33 solid;}#lp1 table{margin:2px auto}#lp1 hr{width:480px;}/*information div block*/#rp1{display:block;width:510px;height:auto;float:left;border:none;margin:auto 5px;padding:3px;}#rp1 td {width:14px;height:14px;font-size:11px; font-family:Verdana, Arial, Helvetica, sans-serif; vertical-align:middle; text-align:center; work-break:break-all;float:none;}#rp1 table{table-layout:fixed;border:1px #CC0033 solid;margin:2px;float:left;}/*debug div block*/#debugWin{width:100%;height:60px;margin:3px;display:block;padding-bottom:15px;text-align:left;}#debugWin div{width:100%;margin:0 40px 1px 1px;padding:0 20px 0 12px;border:1px solid #000099;height:50px;overflow-y:scroll;text-align:left;word-break:break-all;font-size:10px;}#debugWin input{width:85px;height:auto;font:Verdana, Arial, Helvetica, sans-serif;font-size:1.75ex;}</style></head><body><div id=debugWin></div><div id=lp1></div><div id=rp1></div></body><script language="javascript" type="text/javascript">//Copyright(C) 2008 BAREN Productions. All rights reserved.var ihx={//choiced numberval:0,//nine pane, td block object [1-9] O:[],//td block onclick callback function click:function(id){if(id==this.val)return;if(this.O[this.val]){with(this.O[this.val].style){background="#99ffff";color="#000";fontWeight="";}}var y=this.O[id];if(!y)return false;with(y.style){background="#ffff99";color="#a11";fontWeight="bold";}this.val=id;},//initialization function ---create events' function to change css styleCreate:function(id){var tbcs=_F.$('hx').rows[0].cells,o;this.O[0]=0;for(var i=0;i<tbcs[_L];i++){o=tbcs[i];o.v=i+1;o.onclick=function(){ihx.click(this.v)}o.onmouseenter=function(){this.style.border="#000000 dotted 1px"}o.onmouseleave=function(){this.style.border="#ffffff dotted 1px"}this.O.push(o);}//set default valuethis.click(1);}},matrixs={//O td :--y rowNum[1-9] , --x cellIndex[1-9] :--matrix [1-9]*[1-9]O:[],//dump info table tr td :--matrix [1-9]*[1-9]*[1-9]DumpDev:[],//mark if true dump information Ready:true,//set one paneset:function(y,x,v,iw){var i,o=this.O,c=o[y][x];if(c.isFix)return true;//debug.printTitle(p.P[v],v);if(c.P[v]!=v)return false;for(i=0;i<20;i++) c.Na[i].P[v]='';//debug.print(c.Na[_L]);for(i=1;i<=9;i++) c.P[i]='';c.P[v]=v;c.innerHTML=v;if(iw)c.style.color='green';this.dump();return c.isFix=true;},//save data to stringsave:function(){var o=matrixs.O,v=[],y,x;for(y=1;y<=9;y++){for(x=1;x<=9;x++)v.push(o[y][x].isFix?o[y][x].innerHTML:0);}return v.join('');//debug.stop();},//Load data from stringload:function(s,m){s=(s||'').replace(/\D+/g,'');if(s[_L]!=81)return debug.print('error data input,9*9 panes numbers needed!\n');m=m||s;this.Ready=false;this.reset();var i,x,y,a;for(i=0;i<81;i++){y=Math.floor(i/9)+1;x=i%9+1;a=s.charAt(i);if(a>0&&a<=9)this.set(y,x,a,(a!=m.charAt(i)));}this.Ready=true;this.dump();},//get point valuegetPointVal:function(y,x){return this.O[y][x].P.join('')},// rational value checkisError:function(){var i,j,o=this.O;for(i=1;i<=9;i++){for(j=1;j<=9;j++){if(this.O[i][j].P.join('')[_L]<=0) return {y:i,x:j};}}return false;},//check wheather the table is full filled isFull:function(){var i,j,o=this.O;for(i=1;i<=9;i++){for(j=1;j<=9;j++){if(!o[i][j].isFix) return false;}}return true;},//reset user data & display reset:function(){var y,x,o=this.O,oy,oyx;for(y=1;y<=9;y++){oy=o[y];for(x=1;x<=9;x++){oyx=oy[x];oyx.isFix=false;oyx.innerHTML=" ";oyx.style.color="#000";oyx.P=['',1,2,3,4,5,6,7,8,9];}}this.dump();},//dump funciton to show matrix statusdump:function(){if(!this.Ready)return;var d=this.DumpDev,o=this.O,oy,dv,dvy;var v,y,x,a,b;for(v=1;v<=9;v++){ dv=d[v];for(y=1;y<=9;y++){ dvy=dv[y];oy=o[y];for(x=1;x<=9;x++){a=oy[x].P[v];b=dvy[x];if(a!=b.innerHTML)b.innerHTML=a;}}}},setNerb:function(y,x,o){var i,j,c=o[y][x];for(j=1;j<=9;j++) if(j!=y)c.Ny.push(o[j][x]);for(i=1;i<=9;i++) if(i!=x)c.Nx.push(o[y][i]); var bx=Math.floor((x-1)/3)*3+1;var by=Math.floor((y-1)/3)*3+1;c.Na=c.Na.concat(c.Ny,c.Nx);//if (x==1 && y==1)debug.stop();for(j=by;j<by+3;j++){for(i=bx;i<bx+3;i++){if(i!=x || j!=y) c.Nb.push(o[j][i]);if(i!=x && j!=y) c.Na.push(o[j][i]);}}},//initialization function set variants' value,fomate matrix arrayCreate:function(id,de){var tbrs=_F.$(id).rows,tbcs,cell;var i,j,k,o=[0];for(i=1;i<=9;i++){o[i]=[0];tbcs=tbrs[i-1].cells;for(j=0;j<tbcs[_L];j++){cell=tbcs[j];cell.y=i;cell.x=j+1;cell.Ny=[];cell.Nx=[];cell.Nb=[];cell.Na=[];cell.P=['',1,2,3,4,5,6,7,8,9];cell.onclick=function(){matrixs.set(this.y,this.x,ihx.val)}cell.onmouseenter=function(){this.style.border="#000000 dotted 1px";debug.printTitle(matrixs.getPointVal(this.y,this.x))}cell.onmouseleave=function(){this.style.border="#ffffff dotted 1px"}o[i].push(cell);}}for(i=1;i<=9;i++){for(j=1;j<=9;j++) this.setNerb(i,j,o);}delete this.setNerb;this.O=o;o=0;var d=[0],dv,dvy;for(i=1;i<=9;i++){tbrs=_F.$(de+i).rows;dv=[0];for(j=0;j<9;j++){tbcs=tbrs[j].cells;dvy=[0];for(k=0;k<9;k++)dvy.push(tbcs[k]);dv.push(dvy);}d.push(dv);}//debug.stop();this.DumpDev=d;d=0;dv=0;dvy=0;tbcs=0;tbrs=0;cell=0;debug.f.push({n:"save",f:function(){debug.println(matrixs.save());}},{n:"load",f:function(){matrixs.load(debug.get("input your data",""));}},{n:"reset",f:function(){matrixs.reset();intelligence.reset();}},{n:"intelligence",f:function(){intelligence.start();}},{n:"check",f:function(){var rlt=matrixs.isError();debug.println(rlt?['point(',rlt.y,",",rlt.x,') has no choice!']:'check ok!');}});}},//intelligence functions can guess the right number in the cell be filledintelligence={org:'',buf:[],lastMin:1,timer:0,//reset program clear bufreset:function(){this.buf=[];this.org='';this.lastMin=1;},//get point is the only possibility, return the value or zerocheckPoint:function(y,x,c){var i,j,v,s,vs=matrixs.getPointVal(y,x);if (vs[_L]==1)return vs;for(i=0;i<vs[_L];i++){v=vs.charAt(i);for(s=0,j=0;j<8;j++){if(c.Ny[j].P[v])s++;if(s>0)break;}if(0==s)return v;for(s=0,j=0;j<8;j++){if(c.Nx[j].P[v])s++;if(s>1)break;}if(0==s)return v;for(s=0,j=0;j<8;j++){if(c.Nb[j].P[v])s++;if(s>0)break;}if(0==s)return v;}return 0},//infer valuesinfer:function(){var y,x,v,c,o=matrixs.O;for(y=1;y<=9;y++){for(x=1;x<=9;x++){c=o[y][x];if(c.isFix)continue;v=this.checkPoint(y,x,c);if(0!=v){debug.print(["point(",y,",",x,")=",v,"\t"].join(''));return matrixs.set(y,x,v,1);}}}return 0;},doGuessFirst:function(){//guess value struct {(y,x),v}var y,x,v,l,minX,minY,minL=10,Lm=this.lastMin,o=matrixs.O,c;for(y=1;y<=9;y++){for(x=1;x<=9;x++){//if isFix continuec=o[y][x];if(c.isFix)continue;//get point valuev=c.P.join(''); l=v[_L];//find min value length Pointif(l<minL){minX=x; minY=y; minL=l}if(Lm==l)break;}if(Lm==l)break;}this.lastMin=l;c=o[minY][minX];var k,s,i,vn=[];minVs=c.P.join(''),minVn=99,Pointer=-1;//calculate each value's probability--- vn, & find the min value pointfor(k=0;k<minVs[_L];k++){//get a valuev=minVs.charAt(k);//calculat its nerb countfor(s=0,i=0;i<20;i++) if(c.Na[i].P[v])s++;//save itvn[k]=s;//find the min valueif(s<minVn){minVn=s; Pointer=k}}//return a guess point objectreturn {x:minX,//point xy:minY,//point yv:minVs.charAt(Pointer),//i guess value//this is the max probabilityi:Pointer,//i guess value pointervn:vn,//all point values nerb countav:minVs,//all point valuesr:matrixs.save() // save matrixs status}},doGuessNext:function(gP){//disable last guess point valuegP.vn[gP.i]=99;//init valuevar s,gv={i:-1,vn:99},minVn=99,Pointer=-1;//find next valuefor(var k=0;k<gP.av[_L];k++){s=gP.vn[k];if(s<minVn){minVn=s; Pointer=k}}//no found return nullif(-1==Pointer) return null;//update guess point valuegP.v=gP.av.charAt(Pointer);gP.i=Pointer;return gP;},//try to guess point valueguess:function(gP){//debug.printTitle('guess tree deep ==>',this.buf[_L]);//if exist guess point try next valueif(gP){//change guess point clean the error valuegP=this.doGuessNext(gP);//if no value left null retrun ,do roll back if(null==gP){//when error guess ,roll data backif(this.buf[_L]>0){return this.guess(this.buf.pop());}//no data to go back ,print errorelse{debug.println("the input value is corrupted!");return false;}}matrixs.load(gP.r,this.org);}//create a guess pointelse gP=this.doGuessFirst();this.buf.push(gP);debug.print(["Guess(",gP.y,",",gP.x,")=",gP.v,"\t"].join(''));matrixs.set(gP.y,gP.x,gP.v,1);setTimeout(function(){intelligence.run()},10);//debug.stop();},//start functionrun:function(){//check if the table is full filled if(matrixs.isFull()){return debug.println("well done! ="+(new Date()-this.timer));}//still some panes' value is unknown//hide the fellow logic stuct , the 'else' case is not necessary //else{//check if any pane value is errorif(matrixs.isError()){//when error guess ,roll data backif(this.buf[_L]>0) return this.guess(this.buf.pop());//no data to go back ,print errorelse return debug.println("the input value is corrupted!");}//save curent status ,try to give one simple guesselse{//if infer valu is legal try to infer the next point valueif(this.infer()) return setTimeout(function(){intelligence.run()},10);//can not infer any point valueelse return this.guess();}},start:function(){this.timer=new Date();this.reset();this.org=matrixs.save();this.run();}},//debug functionsdebug={//screen output devicedev:null,//debug functions define here , init function will create button for these functionsf:[],//initialization function , id - output device container idinit:function(id){this.dev=_F.$c('div');_F.$a(_F.$(id),this.dev);for(var i=0;i<this.f[_L];i++)_F.$a(_F.$(id),_F.$c('input',{type:'button',value:this.f[i].n,onclick:this.f[i].f}));_F.$a(_F.$(id),_F.$c('input',{type:'button',value:'clear',onclick:function(){debug.clear()}}));},//print information to debuger device print:function(){_F.$a(this.dev,_F.$t(1==arguments[_L]?arguments[0]:Array.apply([],arguments)));this.dev.scrollTop+=200;},//print information to debuger device end with crlfprintln:function(){_F.$a(this.dev,_F.$t(1==arguments[_L]?arguments[0]:Array.apply([],arguments)));_F.$a(this.dev,_F.$c('br'));this.dev.scrollTop+=200;},//print information to top document titleprintTitle:function(){top.document.title=(Array.apply([],arguments)).join(',').replace(/\s+/g,' ');},//get input from userget:function(){return prompt(arguments[0],arguments[1])},//clear debuge device ouputclear:function(){this.dev.innerHTML='';},//stop running script by calling the native debuger if available, else do nothingstop:function(){debugger}}/*************************************************************//*this function draw all panes in the special id/*con1container 1 id--left panes layer/*con2container 2id--right panes layer/*id1 choice table id --in left layer/*id2 main table id   --contain ninety-nine panes /*id3 information table id string mark/*************************************************************/function DrawTables(con1,con2,id1,id2,id3){var cont,tb,row,i,j,cell;cont=_F.$(con1);tb=_F.$c('table',{id:id1});row=tb.insertRow(0);for(i=0;i<9;i++){row.insertCell(i).innerHTML=i+1}_F.$a(cont,tb);_F.$a(cont,_F.$c('hr'));tb=_F.$c('table',{id:id2});for(i=0;i<9;i++){row=tb.insertRow(i);for(j=0;j<9;j++){cell=row.insertCell(j);cell.innerHTML=" ";cell.bgColor =((i>2&&i<6)^(j>2&&j<6))?"#ffffcc":"#ccffff";}}_F.$a(cont,tb);cont.onselectstart=_F.f;cont=_F.$(con2);for(i=1;i<=9;i++){tb=tb.cloneNode(true);tb.id=id3+i;_F.$a(cont,tb);}cont.onselectstart=_F.f;_F.$a(cont,_F.$c('div',{innerHTML:'<b>Copyright(C) 2008 BAREN Productions. <br />All rights reserved.</b>'}));}// global initialization funtion, create each object on document's Ready (function init(){DrawTables('lp1','rp1','hx','tb',"de");delete DarwTables;ihx.Create('hx');delete ihx.Create;matrixs.Create('tb',"de");delete matrixs.Create;debug.init('debugWin');delete debug.init;_F.$l(document,function(){var k=event.keyCode-48;if(k>0&&k<=9)ihx.click(k);//if(event.ctrlKey)debug.printTitle(matrixs.getCurPointInfo());//debug.print(k);},"keydown");setTimeout(function(){_F.$h(_F.$('rp1'));matrixs.dump();_F.$s(_F.$('rp1'));},10);})();//forbiden user select opration//document.onselectstart=_F.f;</script></html>

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.