【JavaScript】数独解析器 ver 1.0

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>数独解析器 ver 1.0</TITLE>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="莲兮奈若何-杜子兮(lotusiki)">
<META NAME="Keywords" CONTENT="数独 深度优先搜索 排除法">
<META NAME="Description" CONTENT="以九宫格、行、列为单位,优先选择空格少的进行1~9的数字排列。用数组存储解空间,总体上以深度优先算法求解。">
<META NAME="CreateDate" CONTENT="2013.1.18">
</HEAD>
<script language="javascript">
var time=0;                 //解析次数
var arr=[];                 //当前数字填充状态(9 X 9)
var type;                   //空格数最少的单位类型:格、行、列
var emptyNum=[];            //每个单位的空格数
var emptySum;               //空格数之和
var solve=[];               //解空间
var stepNo=0;               //搜索深度
var way=1;                  //当前状态下第n种可能性
var notFound=false;         //是否找到解

function solveProblem(){
	time++;
	getProblem();
	if(emptySum==0){
		alert("结果已算出!");
		return;
	}
	findStep();
	if(notFound){
		goBack();
	}else{
		way=1;
	}
	inputValue();
	showSolve();
}

function getProblem(){
	emptySum=0;
	for(var i=1;i<=9;i++){
		arr[i]=[];
		for (var j=1;j<=9;j++){
			arr[i][j]=document.getElementById("txt"+i+""+j).value;
		}
	}
	for (var i=1;i<28 ;i++ ){
		emptyNum[i]=0;
	}
	for (var i=1;i<=9 ;i++ ){
		for (var j=1;j<=9 ;j++ ){
			var gridNo=getGrid(i,j);
			if (arr[i][j]==""){
				emptyNum[gridNo]++;
				emptyNum[9+i]++;
				emptyNum[18+i]++;
				emptySum++;
			}
		}
	}
}

function findStep(){
	var min=9;
	var iMin=1;
	var num=0;
	var ll=[1,1,1,1,1,1,1,1,1];
	var I=[];
	var J=[];
	var L=[];
	var aL=[];
	var x0,y0;

	stepNo++;
	for (var i=1;i<28 ;i++ ){
		if ((emptyNum[i]<min)&&(emptyNum[i]!=0)){
			min=emptyNum[i];
			iMin=i;
		}
	}

	if (iMin<=9){
		type="grid";
		x0=getX0(iMin);
		y0=getY0(iMin);
		for (var i=x0;i<x0+3 ;i++ ){
			for (var j=y0;j<y0+3 ;j++ ){
				if (arr[i][j]==""){
					I[I.length]=i;
					J[J.length]=j;
				}else{
					ll[arr[i][j]-1]=0;
				}
			}
		}
	}else if (iMin<=18){
		type="line";
		x0=iMin-9;
		for (var j=1;j<=9 ;j++ ){
			if (arr[x0][j]==""){
				I[I.length]=x0;
				J[J.length]=j;
			}else{
				ll[arr[x0][j]-1]=0;
			}
		}
	}else{
		type="list";
		y0=iMin-18;
		for (var i=1;i<=9 ;i++ ){
			if (arr[i][y0]==""){
				I[I.length]=i;
				J[J.length]=y0;
			}else{
				ll[arr[i][y0]-1]=0;
			}
		}
	}
	for (var i=0;i<9 ;i++ ){
		if (ll[i]){
			L[L.length]=i+1;
		}
	}
	if (min==1){
		if (checkOk(iMin,I,J,L)){
			num++;
			memoWay(stepNo,num,I,J,L);
		}
	}
	if (min==2){
		for (var a=0;a<min ;a++ ){
			for (var b=0;b<min ;b++ ){
				if (L[a]!=L[b]){
					aL=[L[a],L[b]];
					if (!checkOk(iMin,I,J,aL)){
						break;
					}
					num++;
					memoWay(stepNo,num,I,J,aL);
				}
			}
		}
	}
	if (min==3){
		for (var a=0;a<min ;a++ ){
			for (var b=0;b<min ;b++ ){
				for (var c=0;c<min ;c++ ){
					if ((L[a]!=L[b])&&(L[a]!=L[c])&&(L[b]!=L[c])){
						aL=[L[a],L[b],L[c]];
						if (!checkOk(iMin,I,J,aL)){
							break;
						}
						num++;
						memoWay(stepNo,num,I,J,aL);
					}
				}
			}
		}
	}
	if (min==4){
		for (var a=0;a<min ;a++ ){
			for (var b=0;b<min ;b++ ){
				for (var c=0;c<min ;c++ ){
					for (var d=0;d<min ;d++ ){
						if ((L[a]!=L[b])&&(L[a]!=L[c])&&(L[a]!=L[d])&&(L[b]!=L[c])&&(L[b]!=L[d])&&(L[c]!=L[d])){
							aL=[L[a],L[b],L[c],L[d]];
							if (!checkOk(iMin,I,J,aL)){
								break;
							}
							num++;
							memoWay(stepNo,num,I,J,aL);
						}
					}
				}
			}
		}
	}
	if (min==5){
		for (var a=0;a<min ;a++ ){
			for (var b=0;b<min ;b++ ){
				for (var c=0;c<min ;c++ ){
					for (var d=0;d<min ;d++ ){
						for (var e=0;e<min ;e++ ){
							if ((L[a]!=L[b])&&(L[a]!=L[c])&&(L[a]!=L[d])&&(L[a]!=L[e])&&(L[b]!=L[c])&&(L[b]!=L[d])&&(L[b]!=L[e])&&(L[c]!=L[d])&&(L[c]!=L[e])&&(L[d]!=L[e])){
								aL=[L[a],L[b],L[c],L[d],L[e]];
								if (!checkOk(iMin,I,J,aL)){
									break;
								}
								num++;
								memoWay(stepNo,num,I,J,aL);
							}						
						}
					}
				}
			}
		}
	}

	if (num==0){
		notFound=true;
		for (var i=0;i<solve.length ;i++ ){
			if ((solve[i][0]==stepNo)&&(solve[i][1]==way-1)){
				arr[solve[i][2]][solve[i][3]]="";
			}
			if ((solve[i][5]!="XX")&&(solve[i][0]==stepNo-1)&&(solve[i][1]==way)){
				solve[i][5]="XX";
				arr[solve[i][2]][solve[i][3]]="";
				try	{
					if (solve[i+1][1]!=way){
						break;
					}
				}catch(e){
				}
			}
		}
	}else{
		notFound=false;
	}
}

function checkOk(iMin,I,J,L){
	for (var l=0;l<I.length ;l++ ){
		var gridNo=getGrid(I[l],J[l]);
		var x0=getX0(gridNo);
		var y0=getY0(gridNo);
		//1st: check the grid
		for (var i=x0;i<x0+3 ;i++ ){
			for (var j=y0;j<y0+3 ;j++ ){
				if (!(i==I[l])&&(j==J[l])){
					if (arr[i][j]==L[l].toString()){
						return false;
					}
				}
			}
		}
        //2nd: check the line
		for (var j=1; j<=9; j++){
		    if ((j!=J[l])&&(arr[I[l]][j]==L[l].toString())){
			    return false;
            }
		}
		//3rd: check the list
        for (var i=1; i<=9; i++){
		    if ((i!=I[l])&&(arr[i][J[l]]==L[l].toString())){
			    return false;
            }
		} 
	}
	return true;
}

function memoWay(stepNo,num,I,J,aL){
	for (var i=0;i<I.length ;i++ ){
		solve[solve.length]=[];
		solve[solve.length-1][0]=stepNo;
		solve[solve.length-1][1]=num;
		solve[solve.length-1][2]=I[i];
		solve[solve.length-1][3]=J[i];
		solve[solve.length-1][4]=aL[i];
		solve[solve.length-1][5]="ok";
	}
}

function goBack(){
	for (var i=0;i<solve.length ;i++ ){
		if ((solve[i][0]==stepNo)&&(solve[i][1]==way)){
			arr[solve[i][2]][solve[i][3]]="";
		}
	}
	stepNo--;
	if (stepNo<0){
		alert("未能求得可行解");
		return;
	}
	way++;
	var exist=false;
	for (var i=0;i<solve.length ;i++ ){
		if ((solve[i][0]==stepNo)&&(solve[i][1]==way)&&(solve[i][5]!="XX")){
			exist=true;
			break;
		}
	}
	if (!exist){
		for (var i=0;i<solve.length ;i++ ){
			if ((solve[i][0]==stepNo-1)&&(solve[i][5]=="ok")){
				way=solve[i][1];
				break;
			}
		}
		for (var i=0;i<solve.length ;i++ ){
			if ((solve[i][0]==stepNo-1)&&(solve[i][1]==way)&&(solve[i][5]=="ok")){
				solve[i][5]="XX";
				arr[solve[i][2]][solve[i][3]]="";
				try{
					if (solve[i+1][1]!=way){
						break;
					}
				}catch(e){}
			}
		}
		goBack();
	}
}

function inputValue(){
	for (var i=0;i<solve.length ;i++ ){
		if ((solve[i][0]==stepNo)&&(solve[i][1]==way)&&(solve[i][5]=="ok")){
			arr[solve[i][2]][solve[i][3]]=solve[i][4];
			document.getElementById("txt"+solve[i][2]+solve[i][3]).style.color="blue";
		}
	}
}

function showSolve(){
	for (var i=1;i<=9 ;i++ ){
		for (var j=1;j<=9 ;j++ ){
			document.getElementById("txt"+i+""+j).value=arr[i][j];
		}
	}
	var strHTML="Time:"+time+"  Step:"+stepNo+"  way:"+way+"<br/>";
	for (var i=0;i<solve.length ;i++ ){
		strHTML+=solve[i]+"<br/>";
	}
	document.getElementById("result").innerHTML=strHTML;
}

function getGrid(x,y){
	if ((x<4)&&(y<4)){
		return 1;
	}else if((x>=4)&&(x<7)&&(y<4)){
		return 2;
	}else if((x>=7)&&(y<4)){
		return 3;
	}else if((x<4)&&(y>=4)&&(y<7)){
		return 4;
	}else if((x>=4)&&(x<7)&&(y>=4)&&(y<7)){
		return 5;
	}else if((x>=7)&&(y>=4)&&(y<7)){
		return 6;
	}else if((x<4)&&(y>=7)){
		return 7;
	}else if((x>=4)&&(x<7)&&(y>=7)){
		return 8;
	}else{
		return 9;
	}
}

function getX0(iMin){
	if(iMin%3==1){
		return 1;
	}else if (iMin%3==2){
		return 4;
	}else{
		return 7;
	}
}

function getY0(iMin){
	if(iMin<=3){
		return 1;
	}else if (iMin<=6){
		return 4;
	}else{
		return 7;
	}
}
</script>
<BODY>

<input id="txt11" type="text" style="width:22;text-align:center" value="5"/>
<input id="txt12" type="text" style="width:22;text-align:center" value=""/>
<input id="txt13" type="text" style="width:22;text-align:center" value=""/>
<input id="txt14" type="text" style="width:22;text-align:center" value="3"/>
<input id="txt15" type="text" style="width:22;text-align:center" value=""/>
<input id="txt16" type="text" style="width:22;text-align:center" value="2"/>
<input id="txt17" type="text" style="width:22;text-align:center" value=""/>
<input id="txt18" type="text" style="width:22;text-align:center" value=""/>
<input id="txt19" type="text" style="width:22;text-align:center" value="6"/><br/>
<input id="txt21" type="text" style="width:22;text-align:center" value=""/>
<input id="txt22" type="text" style="width:22;text-align:center" value=""/>
<input id="txt23" type="text" style="width:22;text-align:center" value="1"/>
<input id="txt24" type="text" style="width:22;text-align:center" value=""/>
<input id="txt25" type="text" style="width:22;text-align:center" value="6"/>
<input id="txt26" type="text" style="width:22;text-align:center" value=""/>
<input id="txt27" type="text" style="width:22;text-align:center" value="8"/>
<input id="txt28" type="text" style="width:22;text-align:center" value=""/>
<input id="txt29" type="text" style="width:22;text-align:center" value=""/><br/>
<input id="txt31" type="text" style="width:22;text-align:center" value=""/>
<input id="txt32" type="text" style="width:22;text-align:center" value="2"/>
<input id="txt33" type="text" style="width:22;text-align:center" value=""/>
<input id="txt34" type="text" style="width:22;text-align:center" value=""/>
<input id="txt35" type="text" style="width:22;text-align:center" value="1"/>
<input id="txt36" type="text" style="width:22;text-align:center" value=""/>
<input id="txt37" type="text" style="width:22;text-align:center" value=""/>
<input id="txt38" type="text" style="width:22;text-align:center" value="3"/>
<input id="txt39" type="text" style="width:22;text-align:center" value=""/><br/>
<input id="txt41" type="text" style="width:22;text-align:center" value="3"/>
<input id="txt42" type="text" style="width:22;text-align:center" value=""/>
<input id="txt43" type="text" style="width:22;text-align:center" value=""/>
<input id="txt44" type="text" style="width:22;text-align:center" value="2"/>
<input id="txt45" type="text" style="width:22;text-align:center" value=""/>
<input id="txt46" type="text" style="width:22;text-align:center" value="4"/>
<input id="txt47" type="text" style="width:22;text-align:center" value=""/>
<input id="txt48" type="text" style="width:22;text-align:center" value=""/>
<input id="txt49" type="text" style="width:22;text-align:center" value="7"/><br/>
<input id="txt51" type="text" style="width:22;text-align:center" value=""/>
<input id="txt52" type="text" style="width:22;text-align:center" value="7"/>
<input id="txt53" type="text" style="width:22;text-align:center" value="2"/>
<input id="txt54" type="text" style="width:22;text-align:center" value=""/>
<input id="txt55" type="text" style="width:22;text-align:center" value=""/>
<input id="txt56" type="text" style="width:22;text-align:center" value=""/>
<input id="txt57" type="text" style="width:22;text-align:center" value="4"/>
<input id="txt58" type="text" style="width:22;text-align:center" value="5"/>
<input id="txt59" type="text" style="width:22;text-align:center" value=""/><br/>
<input id="txt61" type="text" style="width:22;text-align:center" value="9"/>
<input id="txt62" type="text" style="width:22;text-align:center" value=""/>
<input id="txt63" type="text" style="width:22;text-align:center" value=""/>
<input id="txt64" type="text" style="width:22;text-align:center" value="6"/>
<input id="txt65" type="text" style="width:22;text-align:center" value=""/>
<input id="txt66" type="text" style="width:22;text-align:center" value=""/>
<input id="txt67" type="text" style="width:22;text-align:center" value="3"/>
<input id="txt68" type="text" style="width:22;text-align:center" value=""/>
<input id="txt69" type="text" style="width:22;text-align:center" value=""/><br/>
<input id="txt71" type="text" style="width:22;text-align:center" value=""/>
<input id="txt72" type="text" style="width:22;text-align:center" value="8"/>
<input id="txt73" type="text" style="width:22;text-align:center" value=""/>
<input id="txt74" type="text" style="width:22;text-align:center" value=""/>
<input id="txt75" type="text" style="width:22;text-align:center" value="3"/>
<input id="txt76" type="text" style="width:22;text-align:center" value=""/>
<input id="txt77" type="text" style="width:22;text-align:center" value=""/>
<input id="txt78" type="text" style="width:22;text-align:center" value="9"/>
<input id="txt79" type="text" style="width:22;text-align:center" value=""/><br/>
<input id="txt81" type="text" style="width:22;text-align:center" value=""/>
<input id="txt82" type="text" style="width:22;text-align:center" value=""/>
<input id="txt83" type="text" style="width:22;text-align:center" value="5"/>
<input id="txt84" type="text" style="width:22;text-align:center" value=""/>
<input id="txt85" type="text" style="width:22;text-align:center" value="4"/>
<input id="txt86" type="text" style="width:22;text-align:center" value=""/>
<input id="txt87" type="text" style="width:22;text-align:center" value="2"/>
<input id="txt88" type="text" style="width:22;text-align:center" value=""/>
<input id="txt89" type="text" style="width:22;text-align:center" value=""/><br/>
<input id="txt91" type="text" style="width:22;text-align:center" value="4"/>
<input id="txt92" type="text" style="width:22;text-align:center" value=""/>
<input id="txt93" type="text" style="width:22;text-align:center" value=""/>
<input id="txt94" type="text" style="width:22;text-align:center" value="7"/>
<input id="txt95" type="text" style="width:22;text-align:center" value=""/>
<input id="txt96" type="text" style="width:22;text-align:center" value="6"/>
<input id="txt97" type="text" style="width:22;text-align:center" value=""/>
<input id="txt98" type="text" style="width:22;text-align:center" value=""/>
<input id="txt99" type="text" style="width:22;text-align:center" value="5"/><br/>
<input type="button" οnclick="solveProblem()" value="Solve problem step by step"/><br/>
<div id="result" style="font-size:12px"></div>
</BODY>
</HTML>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值