数独游戏(只完成几个普通的自动计算功能)

 驱动器 F 中的卷是 bak
 卷的序列号是 CC6D-A3EE

 F:/iis/game/sudoku 的目录

2010-04-09  10:38    <DIR>          .
2010-04-09  10:38    <DIR>          ..
2010-04-09  10:38                13 dir.bat
2010-04-09  10:38                 0 dir.txt
2008-10-17  18:57    <DIR>          pic
2008-11-08  14:13            48,761 sudoku2.hta
2008-10-27  17:34    <DIR>          sudokulogs
               3 个文件         48,774 字节
               4 个目录    228,220,928 可用字节

 

 

 驱动器 F 中的卷是 bak
 卷的序列号是 CC6D-A3EE

 F:/iis/game/sudoku/pic 的目录

2010-04-09  10:40    <DIR>          .
2010-04-09  10:40    <DIR>          ..
2008-10-16  11:37           533,603 bg.jpg
2010-04-09  10:38                13 dir.bat
2010-04-09  10:40                 0 dir.txt
               3 个文件        533,616 字节
               2 个目录    228,220,928 可用字节

 

 驱动器 F 中的卷是 bak
 卷的序列号是 CC6D-A3EE

 F:/iis/game/sudoku/sudokulogs 的目录

2010-04-09  10:41    <DIR>          .
2010-04-09  10:41    <DIR>          ..
2010-04-09  10:38                13 dir.bat
2010-04-09  10:41                 0 dir.txt
2008-10-27  17:58               434 test
2008-10-23  09:04               648 全盘局
               4 个文件          1,095 字节
               2 个目录    228,220,928 可用字节

全盘局

文件内容

001,012,023,034,045,056,067,078,089,104,115,126,137,148,159,161,172,183,207,218,229,231,242,253,264,275,286,302,313,324,335,346,357,368,379,381,405,416,427,438,449,451,462,473,484,508,519,521,532,543,554,565,576,587,609,611,622,633,644,655,666,677,688,706,717,728,739,741,752,763,774,785,803,814,825,836,847,858,869,871,882

 

hta文件内容

 

 

<html>
<head>
<title>数独游戏</title>

<style>
body

  margin:1px;
  background:transparent url("pic/bg.jpg") no-repeat  fixed 0% 0%;
}

#table
{
 border-collapse:collapse;
}

#tds0, #tds2, #tds4, #tds6, #tds8
{
  background-color:#BDB730;
}

#tds1, #tds3, #tds5, #tds7
{
  background-color:darkkhaki;
}

td
{
  border:1px solid #CCCCCC;
 text-align:center;
 vertical-align: bottom;
}

.topInput
{
  heigth:12px;
  font-size:9px;
}

.bottomInput
{
  color:black;
  margin-top:-10px;
  height:35px;
  font-size:33px;
  font-weight:800;
}

.bottomInput,.topInput

  cursor:default;
  display:block;
  background-color:transparent;
  width:45px; 
  padding:0px;
  text-align:center;
  border:0px;
}

.f1 {
 background-color: #CCCCCC;
}

#setTd
{
  color:green;
}
</style>
</head>
<body>
<center>
<table>
<tr>
 <td style="border:0px;">
  <table onKeydown="return keyDown();" onKeyup="keyUp();" id=table onselectStart="return false;"> </table>
 </td>
 <td style="border:0px; border:0px; background-color:#CCCCCC;">
   <b><span id=nameShow >&nbsp;</span></b><br><br>
   <b><span id=timeShow style="color:red;">&nbsp;</span></b><br><br>
  
  <input title="删除右边表格中所有内容,包括大小格里数字和颜色"
   type="button" value="清空盘面" style="width:60px;" onClick="clearTable();">
  <input title="全部大格都填写完数字后,检查是否完成此局"
   type="button" value="检查结果" style="width:60px;" onClick="checkRusilt();">
   <input title="计算并显示已花费时间" style="width:60px;"
    type="button" value="开始计时" id=timeButton onClick="setTime(this)"><br>
  
   <input type="button" value="重算上格" onClick="showMaybe();" style="width:60px;">
   <input type="button" value="随机初盘" onClick="randomDefault();" style="width:60px;"><br> <br>
   <select id=fun style="width:170px;">
    <option value="isOnly();">唯一候选数法</option>
    <option value="isOnlyHide();">隐性唯一候选数法</option>
    <option value="AreaDel();">候选数区块删减法</option>
   </select><input type=button value=应用 οnclick="doDel();" style="width:31px;">
  
  
  <a href="#" onClick="this.firstChild.click();" style="color:green; font-size:12px; display:block;" hidefocus=true><input type="checkbox" id=myDefault onClick="ifEdit(this.checked);"
   title="自己输入初盘数字,输入完成后,再次点击此处,关闭设置状态。然后关闭前输入的数字都是绿色在玩时不可更改.设置不对时,可再次点击此处更改初盘数."
   >开(手工输入初盘数字)/关初盘设置状态</a>
  
   <div style="color:green;font-size:12px;"><input type="checkbox" id=ifStart firstNumber=""
   title="打勾后新输入的数字会以蓝色显示,以区别绝对正确答案和假设作案."
   οnclick="if (this.checked)this.firstNumber = '';">假设并
   <select id="markColor" style="background-color:darkkhaki; width:60px;">
    <option style="color:white;">white</option>
    <option style="color:red;">red</option>
    <option style="color:blue;">blue</option>
    <option style="color:brown;">brown</option>
    <option style="color:darkmagenta;">darkmagenta</option>
    <option style="color:blueviolet;">blueviolet</option>
    <option style="color:darkblue;">darkblue</option>
    <option style="color:sienna;">sienna</option>
    <option style="color:teal;">teal</option>
    <option style="color:purple;">purple</option>
   </select>
    色标记输入数字</div>
    <br><br>
   
  <input type="button" value="保存盘局" onClick="getLog()" style="width:60px;" >
  <input type="button" value="载入盘局" onClick="file2Default()" style="width:60px;">
  <input type="button" value="更新列表" οnclick="fsoSearchFile()" style="width:60px;">
  <select id=fileList style="width:180px; display:block;" onChange="resetGameNumber(this);">
  <option value="man">手动输入</option>
  <option value="easy" child="1">系统初盘:初级</option>
  <option value="middle" child="1">系统初盘:中级</option>
  <option value="hard" child="1">系统初盘:高级</option>
  <option value="hardHard" child="1">系统初盘:难级</option>
  </select>

<div style="height:25px;">
<select id=easy style="width:180px;display:none;">
<option value="001,015,032,054,076,083,102,141,184,207,224,249,255,262,308,323,386,412,425,463,474,509,561,585,626,634,642,668,704,745,782,805,819,838,856,871,887">1
</option>
<option value="015,034,052,063,118,123,155,186,214,248,271,289,313,324,336,342,381,406,444,483,501,547,568,576,605,611,649,673,704,731,769,778,829,832,858,874">
23</option>
<option value="009,016,042,063,075,111,157,179,208,246,255,277,328,359,374,402,426,431,469,487,514,533,556,565,619,637,641,682,717,735,776,818,822,849,871,885">
72</option>
<option value="003,017,042,051,074,102,139,175,186,224,235,281,322,341,359,365,418,429,453,467,476,523,538,561,605,652,669,708,714,755,783,812,833,846,878,885">
83</option>
<option value="019,028,043,081,101,152,178,186,223,241,255,289,303,346,379,387,404,439,458,483,508,512,547,585,609,635,644,666,705,714,731,782,807,842,869,875">2900
</option>
</select>

<select id=middle style="width:180px;display:none;">
<option value="005,072,088,124,141,165,186,239,302,318,323,389,506,567,574,583,652,704,721,747,763,809,816,885">1
</option>
<option value="005,018,031,089,126,149,171,236,275,332,388,414,437,459,476,501,556,617,654,711,743,769,808,851,873,884">
1057</option>
<option value="001,035,068,072,116,152,163,207,241,286,309,346,354,377,417,443,471,512,548,584,605,642,689,723,736,778,818,829,853,882">
1061</option>
<option value="028,054,077,136,171,227,259,264,323,335,349,366,411,432,474,529,537,565,624,631,668,716,753,817,839,861">
1080</option>
<option value="018,026,049,074,085,105,183,229,236,302,321,335,413,477,554,565,582,653,669,706,788,804,819,847,862,875">
1095</option>
</select>

<select id=hard style="width:180px;display:none;">
<option value="008,052,065,084,129,178,187,207,255,282,317,339,386,428,435,451,464,509,556,573,603,631,685,704,716,762,801,825,836">
1</option>
<option value="007,015,049,074,086,109,121,163,182,302,336,351,387,418,472,501,533,558,585,703,729,762,784,808,814,843,877,889">
1033</option>
<option value="038,057,083,114,123,139,176,209,328,347,353,389,413,477,502,535,544,561,684,711,756,763,778,803,837,855">
1051</option>
<option value="021,067,115,133,206,255,262,319,365,416,454,472,527,556,571,622,631,683,758,779,824,861">
1056</option>
<option value="018,122,136,184,223,251,272,307,352,369,421,465,526,547,582,619,632,668,708,755,767,871">
1075</option>
<option value="026,044,068,108,157,214,243,287,311,339,377,382,422,464,509,513,547,576,604,646,671,734,789,825,841,867">
1081</option>
</select>

<select id=hardHard style="width:180px;display:none;">
<option value="016,071,133,159,184,304,345,389,411,448,476,502,547,583,703,732,754,787,815,878">
1
</option>
<option value="025,039,077,102,206,234,289,313,359,371,421,435,462,515,576,609,657,684,787,818,856,865">
852</option>
<option value="008,046,081,123,165,219,221,237,325,353,374,403,449,488,512,563,658,664,677,729,762,806,844,889">
1135</option>
<option value="009,014,071,087,226,234,242,259,263,303,338,351,389,436,454,504,535,552,583,623,639,648,655,664,808,817,879,885">
1148</option>
<option value="004,029,057,078,112,205,233,269,311,338,382,422,463,507,544,571,621,656,689,774,818,839,866,883">
1174</option>
<option value="027,102,113,147,168,221,249,274,318,332,381,423,466,505,544,572,615,648,669,728,746,773,782,865">
1189</option>
<option value="026,039,087,108,163,219,244,321,336,373,422,466,517,533,565,647,674,723,781,805,854,862">
1363</option>
<option value="014,048,062,127,135,229,266,323,342,375,407,483,516,534,569,625,664,757,768,822,841,877">
5283
</option>
<option value="005,071,111,142,173,202,236,318,363,409,453,481,524,555,578,659,685,714,745,776,816,887">
5326
</option>
<option value="019,064,108,137,161,201,242,321,362,413,457,479,526,559,568,646,688,722,754,785,824,877">
5408
</option>
<option value="025,031,123,138,186,226,279,319,344,371,427,439,463,512,578,613,661,701,754,762,856,868">
5422
</option>
<option value="009,085,114,133,172,228,261,317,336,353,448,537,559,576,621,669,713,756,774,805,888">me</option>
</select>

</div>
 </td>
</tr>
</table>
</center>
  <div class="f1">
<ul>
    <li>数独游戏规则:<br>
      <br>
      在9阶方阵中,包含了81个小格(九列九行),其中又再分成九个小正方形(称为宫),每宫有九小格。<br>
      游戏刚开始时,盘面上有些小格已经填了数字(称为初盘,一般初盘中数字最少要17个,因为还没有例子证明少于17个数字的初盘可以得到唯一解),游戏者要在空白的小格中填入1到9的数字,使得最后每行、每列、每宫都不出现重复的数字,而且每一个游戏都只有一个唯一的解答(称为终盘)。<br>
      <br>
    </li>
    <li>本游戏盘面使用方法:<br>
      <br>
    每个小格中包含一个上小格,和一个下大格;上小格是供填写大格可能值参考用,最多只能填写1-9的9个不重复数字,下大格才是81格中的"小格",只能填写一个数字,且必要符合上面的游戏规则;注意输入数字1-9只能使用键盘中右边小键盘;
      <br>
      <br>清空盘面按钮:把盘面数据清空.包括上下格数字,颜色,标记.
      <br>
      <br>检查结果按钮:当你全部填写完81个下格后,可以检查一下是否符合了规则,既是是否过关了,只不过不必检查,因为你在输入数字时程序自动检查是否符合规则,不符合就不允许输入.所以,只要你完全填写完就可以保证通关了.
      <br>
      <br>开始计时按钮:开/关记录你通关的耗时是多少.
      <br>
      <br>重算上格按钮:只是按行,列,九小宫是否未包含1-9中某个数字就放入上小格的功能.注意它不包含其它筛选规则,所以,建议你只在开始时使用一下,再人工使用其它筛选规则去掉上小格数字.千万不能在使用其它规则筛选后再使用此按钮,否则,它又会把某些已人工筛选出去的数字放上去.再说,太多的智能化,游戏也就失去它的意义了.
      <br>
      <br>随机初盘按钮:即时随机智能计算出一个初盘.可能此初盘因为智能化程度影响,将导致难度分级不是很准确.
      <br>
      <br>智能求解按钮:自动智能求出终盘.
      <br>
      <br>开(手工输入初盘数字)/关初盘设置状态选项:打勾时你可以修改初盘数字,去掉后它将把盘中所有数字下格当成初盘数字,变成游戏时不可以更改状态.所以你可以通过此功能来自已设置自己的初盘.
      <br>
      <br>假设并以*色标记输入数字选项:当你进行到无法通过某些规则一步确定某个数字是否可以去掉,或是可填时,你就可以打勾此选项,它就可以从你打勾开始的第一个数字用不同色记录你在此后输入的数字,并且第一个输入的数字是有下划线,以让你在最后推断矛盾时回头确定第一个数字可以去掉.
      <br>
      <br>保存盘局按钮:把当前盘面保存以供下次使用.可以保存的信息有上格数字,下格数字,初盘数字(就是下次载入时就属于不可以更改状态).至于假设数字(既是下格中非黑色数字)在保存前会被自动删除不保存.保存成文件时它会在下面的下拉框中添加入,然后你就可以选择它载入.自动保存的文件存放在程序文件夹下的sudokulogs文件夹中.你可以进入手动删除它,或在保存新文件时选择替换同名文件就可以了.注意手工删除这些文件不会自动删除下拉框中列表,你必须点击下拉框上面更新列表按钮来跟文件夹中文件同步.在这个按钮上有一个功能就是在保存盘局时,它会把数据同时保存到剪贴板中,无论你是否选择了弹出的输入文件名的窗口那个按钮,这样你就可以把这些盘局信息粘贴到记事本上手工保存,或是供载入时粘贴用.
      <br>
      <br>载入盘局按钮:下面还有一个选项,就是下拉框,和载入一起组成载入功能.
      <br>当你选择手动输入时,你必须在弹出窗口中输入上次保存的盘局信息,注意输入的信息是保存时给出信息一致的,否则可能会导致多出某些数字或是丢失一些数字或是弹出信息不合法提醒窗口.此时你也可以直接把刚才保存在剪贴板中的信息粘贴上去.在此网址的网页中有很多比较多人玩的初盘:<a href="http://www.sudoku.name/index-cn.php" target="blank">http://www.sudoku.name/index-cn.php</a>
      <br>当你选择系统初盘是,它分成初,中,高,难级,而每下面又有很多初盘,所以你可以选择.
      <br>或者你可以选择你上次保存在文件中的盘局,继续上次进度.
      最后你选择好后,请点击载入盘局按钮载入.</li>
     
      <li>
      人工解题技巧<br><br>
      直观法
       <br>  数独直观法指的是不需要任何辅助工具,刚刚看到数独题的时候就可以立即开始解题。数独直观法解题技巧主要有:唯一解法、基础摒除法、唯余解法、区块摒除法、组合摒除法、矩形摒弃法。
       <br><br>
       唯一解法:如果某行已填数字的单元格达到8个,那么该行剩余单元格能填的数字就只剩下那个还没出现过的数字;同理,如果某列已填数字的单元格达到8个,那么该列剩余单元格能填的数字就只剩下那个还没出现过的数字;如果某九宫格已填数字的单元格达到8个,那么该九宫格剩余单元格能填的数字就只剩下那个还没出现过的数字。
    这应该算是直观法中最简单的方法了。基本上只需要看谜题,推理分析一概都用不上,这是因为要使用它所需满足的条件十分明显。同样,也正是因为它简单,所以只能处理很简单的谜题,或是在处理较复杂谜题的后期才用得上。
    <br><br>
   
    基础摒除法:
    基础摒除法是直观法中最常用的方法,也是在平常解决数独谜题时使用最频繁的方法。单元排除法使用得当的话,甚至可以单独处理中等难度的谜题。
    使用单元排除法的目的就是要在某一单元(即行,列或区块)中找到能填入某一数字的唯一位置,换句话说,就是把单元中其他的空白位置都排除掉。
    那么要如何排除其余的空格呢?当然还是不能忘了游戏规则,由于1-9的数字在每一行、每一列、每一个九宫格都要出现且只能出现一次,所以:
    如果某行中已经有了某一数字,则该行中的其他位置不可能再出现这一数字;
    如果某列中已经有了某一数字,则该列中的其他位置不可能再出现这一数字;
    如果某区块中已经有了某一数字,则该区块中的其他位置不可能再出现这一数字。。基础摒除法可以分为行摒除、列摒除和九宫格摒除。<br><br>
    唯余解法唯余解法是直观法中较不常用的方法。虽然它很容易被理解,然而在实践中,却不易看出能够使用这个方法的条件是否得以满足,从而使这个方法的应用受到限制。
    与唯一解法相比,唯余解法是确定某个单元格能填什么数的方法,而唯一解法是确定某个数能填在哪个单元格的方法。另外,应用唯一解法的条件十分简单,几乎一目了然。
    <br><br>
    区块摒除法:区块摒除法是直观法中进阶的技法。虽然它的应用范围不如基础摒除法那样广泛,但用它可能找到用基础摒除法无法找到的解。有时在遇到困难无法继续时,只要用一次区块摒除法,接下去解题就会势如破竹了。
    当某数字在某个九宫格中可填入的位置正好都在同一行上,因为该九宫格中必须要有该数字,所以这一行中不在该九宫格内的单元格上将不能再出现该数字。
    当某数字在某个九宫格中可填入的位置正好都在同一列上,因为该九宫格中必须要有该数字,所以这一列中不在该九宫格内的单元格上将不能再出现该数字。
    当某数字在某行中可填入的位置正好都在同一九宫格上,因为该行中必须要有该数字,所以该九宫格中不在该行内的单元格上将不能再出现该数字。
    当某数字在某列中可填入的位置正好都在同一九宫格上,因为该列中必须要有该数字,所以该九宫格中不在该列内的单元格上将不能再出现该数字。
    区块摒除法实际上是利用区块与行或列之间的关系来实现的,这一点与基础摒除法颇为相似。然而,它实际上是一种模糊排除法,也就是说,它并不象基础摒除法那样利用谜题中现有的确定数字对行,列或九宫格进行排除,而是在不确定数字的具体位置的情况下进行排除的。<br><br>
    组合摒除法:组合摒除法和区块摒除法一样,都是直观法中进阶的技法。组合摒除法,顾名思义,要考虑到某种组合。这里的组合既包括区块与区块的组合,也包括单元格与单元格的组合,利用组合的关联与排斥的关系而进行某种排除。它也是一种模糊摒除法,同样是在不确定数字的具体位置的情况下进行排除的。
    如果在横向并行的两个九宫格中,某个数字可能填入的位置正好都分别占据相同的两行,则这两行可以被用来对横向并行的另一九宫格做行摒除。
    如果在纵向并行的两个九宫格中,某个数字可能填入的位置正好都分别占据相同的两列,则这两列可以被用来对纵向并行的另一九宫格做列摒除。
    <br><br>
    矩形摒弃法:矩形摒除法的原理类似于组合摒除法,是专门针对某个数字可能填入的位置刚好构成一个矩形的四个顶点时使用的摒除法。
    如果一个数字在某两行中能填入的位置正好在同样的两列中,则这两列的其他的单元格中将不可能再出现这个数字;
    如果一个数字在某两列中能填入的位置正好在同样的两行中,则这两行的其他的单元格中将不可能再出现这个数字。
   
    <br><br><br>
    候选数法
<br><br><br>唯一候选数法:唯一候选数法是候选数删减法中最简单的一种方法,就是通览所有单元格的候选数列表,如果哪个单元格中只剩下一个候选数,就可应用唯一候选数法,在该单元格中填入这个数字,并在相应行,列和九宫格的其它单元格候选数列表中删除该数字。
<br><br>
隐性唯一候选数法:顾名思义,隐式唯一候选数法也是唯一候选数法的一种,但它不如显式唯一候选数法那样显而易见。
    由于1-9这9个数字要在每行、每列和每个九宫格内至少出现一次,所以如果某个数字在某行、某列或是某个九宫格内所有单元格的候选数列表中只出现一次,那么这个数字就应该填入它出现的那个单元格内,并且从该格所在行、所在列和所在九宫格内其它单元格的候选数列表中删除该数字。
    <br><br>
    候选数区块删减法:候选数区块删减法也是比较常用的方法,它的目的是尽量删减候选数,而不一定要生成某一单元格的唯一解(当然,产生唯一解更好)。候选数区块删减法是利用九宫格中的候选数和行或列上的候选数之间的交互影响而实现的一种删减方法。
    在某一九宫格中,当所有可能出现某个数字的单元格都位于同一行时,就可以把这个数字从该行的其他单元格的候选数中删除;
    在某一九宫格中,当所有可能出现某个数字的单元格都位于同一列时,就可以把这个数字从该列的其他单元格的候选数中删除;
    在某一行(列)中,当所有可能出现某个数字的单元格都位于同一九宫格中时,就可以把这个数字从该九宫格的其他单元格的候选数中删除。
    <br><br>
    候选数对删减法:候选数对删减法依据的原理是数字1-9在同一行、同一列和同一九宫格内不能出现2次或2次以上。这样,如果在同一行、同一列和同一九宫格内两个单元格的候选数列表都是{a,b},那么如果其中一个单元格填入的数字为a,另一个单元格填入的数字就应该是b;反之,如果其中一个单元格填入的数字为b,另一个单元格填入的数字就应该是a。也就是说,a,b两个数字就应该分别填入这两个单元格,所以该行、该列或是该九宫格内其它单元格就不应该再填入数字a和b。
    所以候选数对删减法就是:在一个行、列或九宫格中,如果有两个单元格都包含且只包含相同的两个候选数,则这两个候选数字应该从该行、该列列或该九宫格的其他单元格的候选数列表中删去。
    <br><br>
    隐性候选数对删减法依据的原理是数字1-9在同一行、同一列和同一九宫格内至少要出现一次。这样,如果某两个数字a和b在同一行、同一列和同一九宫格内只在两个单元格的候选数列表中出现,那么该行、该列或是该九宫格内其它单元格就不应该再填入数字a和b,所以a和b只能在这两个单元格中出现,所以这两个单元格的候选数列表就都应该是{a,b},可以将其他的数字从这两个单元格的候选数列表中删去。
    所以隐性候选数对删减法就是:在同一行,列或区块中,如果一个数对(两个数字)正好只出现且都出现在两个单元格中,则这两个单元格的候选数中的其他数字可以被删除。
    <br><br>
    三数集删减法的原理类似于候选数对删减法。候选数对删减法要求同样的2个数字都出现在某行、列或九宫格的2个单元格中,且这2个单元格的候选数不能包含其他的数字。同样,三数集删减法要求的是3个数字要出现在3个位于同一行、列或九宫格的单元格中,且这3个单元格的候选数中不能包含其他数字。但不同的是,三数集删减法不要求每个单元格中都要包含这3个数字。例如,对于数字集{2,4,5},如果在某行,列或区块中有3个单元格的候选数分别为下面几种情况时,都可应用三数集删减法:
    {2, 4, 5}、{2, 4, 5}、{2, 4, 5};
    {2, 4}、{4, 5}、{2, 5};
    {2, 4, 5}、{2, 5}、{4, 5};
    {2, 4, 5}、{4, 5}、{2, 4, 5};
    ……
    也就是说,要形成三数集,则必须要有3个在同一行、列或九宫格中的单元格,每个单元格中至少要有2个候选数,且它们的所有候选数字也正好都是一个三数集的子集。这个三数集中的3个数字只能填入这3个单元格中,所以该行、列或九宫格中其他的单元格中不可能再填入这3个数字。
    但要注意的是,{2, 4, 5}、{2, 4}、{2, 4}这种情况不是三数集。其中{2, 4}和{2, 4}可应用候选数对删减法,所以第一个候选数列表{2, 4, 5}将只能剩下候选数5,这时就可应用唯一候选数法了。
    <br><br>
    隐性三数集删减法相对于三数集删减法就类似于隐形候选数对删减法相对于候选数对删减法。当某个3个数字只出现在某行、列或九宫格的3个单元格中,且每个单元格中至少包含有其中的2个数字时,则可以把其他数字从这3个单元格的候选数中删除。
    <br><br>
    候选数矩形删减法类似于直观法中的矩形摒除法。
    如果一个数字正好出现且只出现在某两行的相同的两列上,则这个数字就可以从这两列上其他的单元格的候选数中删除;
     如果一个数字正好出现且只出现在某两列的相同的两行上,则这个数字就可以从这两行上的其他单元格的候选数中删除。
     <br><br>
     三链数删减法类似于矩形删减法,是矩形删减法的推广。三链数删减法指的是如果某个数字在某三列中只出现在相同的三行中,则这个数字将从这三行上其他的候选数中删除;或者如果某个数字在某三行中只出现在相同的三列中,则这个数字也将从这三列上其他的候选数中删除。
     <br><br>XY形态匹配删减法是一个高级的数独技巧,但是应用的机会也比较多。<br />
<div style="height:210px;">
<div style="float:left; width:210px; ">
<table border="0" cellspacing="0" cellpadding="6" id="sudokutable">
  <tr>
    <td class="lt">&nbsp;</td>
    <td class="tt">&nbsp;</td>
    <td class="tt">&nbsp;</td>
    <td class="lt">&nbsp;</td>
    <td class="tt">&nbsp;</td>
    <td class="rt">&nbsp;</td>
  </tr>
  <tr>
    <td class="ll">&nbsp;</td>
    <td>XY</td>
    <td>&nbsp;</td>
    <td class="ll">&nbsp;</td>
    <td>XZ</td>
    <td class="rr">&nbsp;</td>
  </tr>
  <tr>
    <td class="ll">&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td class="ll">&nbsp;</td>
    <td>&nbsp;</td>
    <td class="rr">&nbsp;</td>
  </tr>
  <tr>
    <td class="lt">&nbsp;</td>
    <td class="tt">&nbsp;</td>
    <td class="tt">&nbsp;</td>
    <td class="lt">&nbsp;</td>
    <td class="tt">&nbsp;</td>
    <td class="rt">&nbsp;</td>
  </tr>
  <tr>
    <td class="ll">&nbsp;</td>
    <td>YZ</td>
    <td>&nbsp;</td>
    <td class="ll">&nbsp;</td>
    <td>*</td>
    <td class="rr">&nbsp;</td>
  </tr>
  <tr>
    <td class="lb">&nbsp;</td>
    <td class="bb">&nbsp;</td>
    <td class="bb">&nbsp;</td>
    <td class="lb">&nbsp;</td>
    <td class="bb">&nbsp;</td>
    <td class="rb">&nbsp;</td>
  </tr>
</table>
</div>
如左图,四个相邻的(也可不相邻)九宫格。XY, XZ和YZ分别表示只有两个候选数的单元格,但它们的候选数部分重叠。可见,不管XY取何值,星号所示的位置不可能是Z值。因为: <br />
如果XY取X值,则与其同行的XZ只能取Z值,这样星号所示单元格就不能为Z值;<br />
如果XY取Y值,则与其同列的YZ只能取Z值,而星号所示的单元格同样不能是Z值。 <br />
于是,就可以把Z值从星号所示的单元格中去除。
</div>
<div style="height:150px;">
<div style="float:left; width:210px;">
<table border="0" cellspacing="0" cellpadding="6" id="sudokutable">
  <tr>
    <td class="lt">*</td>
    <td class="tt">XY</td>
    <td class="tt">*</td>
    <td class="lt">&nbsp;</td>
    <td class="tt">XZ</td>
    <td class="rt">&nbsp;</td>
  </tr>
  <tr>
    <td class="ll">&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td class="ll">&nbsp;</td>
    <td>&nbsp;</td>
    <td class="rr">&nbsp;</td>
  </tr>
  <tr>
    <td class="lb">YZ</td>
    <td class="bb">&nbsp;</td>
    <td class="bb">&nbsp;</td>
    <td class="lb">*</td>
    <td class="bb">*</td>
    <td class="rb">*</td>
  </tr>
</table>
</div>
<div style="width:270px; float:right;">
如左图,XY和YZ同在一个九宫格但不同行中,而XZ和XY在同一行,但在不同九宫格中。这样,所有打星号的单元格中不能是Z值。因为:<br />
如果XY=X,则XZ=Z。那么XZ所在的行和九宫格中就不能再出现Z; <br />
如果XY=Y,则YZ=Z。那么YZ所在的行和九宫格中就不能再出现Z。
</div>
</div>
<div style="height:210px;">
<div style="float:left; width:110px; ">
<table border="0" cellspacing="0" cellpadding="6" id="sudokutable">
  <tr>
    <td class="lt">&nbsp;</td>
    <td class="tt">&nbsp;</td>
    <td class="rt">*</td>
  </tr>
  <tr>
    <td class="ll">YZ</td>
    <td>&nbsp;</td>
    <td class="rr">*</td>
  </tr>
  <tr>
    <td class="ll">&nbsp;</td>
    <td>&nbsp;</td>
    <td class="rr">XY</td>
  </tr>
  <tr>
    <td class="lt">*</td>
    <td class="tt">&nbsp;</td>
    <td class="rt">&nbsp;</td>
  </tr>
  <tr>
    <td class="ll">*</td>
    <td>&nbsp;</td>
    <td class="rr">XZ</td>
  </tr>
  <tr>
    <td class="lb">*</td>
    <td class="bb">&nbsp;</td>
    <td class="rb">&nbsp;</td>
  </tr>
</table>
</div>
如左图,XY和YZ在同一九宫格但不同列中,而XY和XZ在同一列的不同九宫格中。这样,所有打星号的单元格中不能是Z值。因为:<br />
如果XY=X,则XZ=Z。那么XZ所在的列和九宫格中就不能再出现Z; <br />
如果XY=Y,则YZ=Z。那么YZ所在的列和九宫格中就不能再出现Z。
</div>
<br><br>
XYZ形态匹配删减法类似于XY形态匹配删减法,不同的是这次有一个单元格的候选数列表含有三个数字。<br />
<div style="height:170px;">
<div style="float:left; width:210px;">
<table border="0" cellspacing="0" cellpadding="6" id="sudokutable">
  <tr>
    <td class="lt">*</td>
    <td class="tt">XYZ</td>
    <td class="tt">*</td>
    <td class="lt">&nbsp;</td>
    <td class="tt">XZ</td>
    <td class="rt">&nbsp;</td>
  </tr>
  <tr>
    <td class="ll">&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td class="ll">&nbsp;</td>
    <td>&nbsp;</td>
    <td class="rr">&nbsp;</td>
  </tr>
  <tr>
    <td class="lb">YZ</td>
    <td class="bb">&nbsp;</td>
    <td class="bb">&nbsp;</td>
    <td class="lb">&nbsp;</td>
    <td class="bb">&nbsp;</td>
    <td class="rb">&nbsp;</td>
  </tr>
</table>
</div>
如左图,XYZ和YZ同在一个九宫格但不同行中,而XZ和XYZ在同一行,但在不同九宫格中。这样,所有打星号的单元格中不能是Z值。因为:<br />
如果XYZ=X,则XZ=Z。那么XZ所在行就不能再出现Z; <br />
如果XYZ=Y,则YZ=Z。那么YZ所在的九宫格中就不能再出现Z;<br />
如果XYZ=Z。那么XYZ所在的九宫格中就不能再出现Z;
</div>
<div style="height:210px;">
<div style="float:left; width:110px; ">
<table border="0" cellspacing="0" cellpadding="6" id="sudokutable">
  <tr>
    <td class="lt">&nbsp;</td>
    <td class="tt">*</td>
    <td class="rt">YZ</td>
  </tr>
  <tr>
    <td class="ll">&nbsp;</td>
    <td>XYZ</td>
    <td class="rr">&nbsp;</td>
  </tr>
  <tr>
    <td class="ll">&nbsp;</td>
    <td>*</td>
    <td class="rr">&nbsp;</td>
  </tr>
  <tr>
    <td class="lt">&nbsp;</td>
    <td class="tt">&nbsp;</td>
    <td class="rt">&nbsp;</td>
  </tr>
  <tr>
    <td class="ll">&nbsp;</td>
    <td>XZ</td>
    <td class="rr">&nbsp;</td>
  </tr>
  <tr>
    <td class="lb">&nbsp;</td>
    <td class="bb">&nbsp;</td>
    <td class="rb">&nbsp;</td>
  </tr>
</table>
</div>
如左图,XYZ和YZ在同一九宫格但不同列中,而XYZ和XZ在同一列的不同九宫格中。这样,所有打星号的单元格中不能是Z值。因为:<br />
如果XYZ=X,则XZ=Z。那么XZ所在列就不能再出现Z; <br />
如果XYZ=Y,则YZ=Z。那么YZ所在的九宫格中就不能再出现Z;<br />
如果XYZ=Z。那么XYZ所在的九宫格中就不能再出现Z。</div>
<br><br>
WXYZ形态匹配删减法类似于XYZ形态匹配删减法,不同的是这次有一个单元格的候选数列表含有四个数字。<br />
<div style="height:190px;">
<div style="float:left; width:230px;">
<table border="0" cellspacing="0" cellpadding="6" id="sudokutable">
  <tr>
    <td class="lt">*</td>
    <td class="tt">WXYZ</td>
    <td class="tt">*</td>
    <td class="lt">&nbsp;</td>
    <td class="tt">XZ</td>
    <td class="rt">YZ</td>
  </tr>
  <tr>
    <td class="ll">&nbsp;</td>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    <td class="ll">&nbsp;</td>
    <td>&nbsp;</td>
    <td class="rr">&nbsp;</td>
  </tr>
  <tr>
    <td class="lb">WZ</td>
    <td class="bb">&nbsp;</td>
    <td class="bb">&nbsp;</td>
    <td class="lb">&nbsp;</td>
    <td class="bb">&nbsp;</td>
    <td class="rb">&nbsp;</td>
  </tr>
</table>
</div>
如左图,WXYZ和WZ同在一个九宫格但不同行中,而XZ、YZ和WXYZ在同一行,但在不同九宫格中。这样,所有打星号的单元格中不能是Z值。因为:<br />
如果WXYZ=X,则XZ=Z。那么XZ所在行就不能再出现Z; <br />
如果WXYZ=Y,则YZ=Z。那么YZ所在行就不能再出现Z; <br />
如果WXYZ=W,则WZ=Z。那么WZ所在的九宫格中就不能再出现Z;<br />
如果WXYZ=Z。那么WXYZ所在的九宫格中就不能再出现Z。
</div>
<div style="height:210px;">
<div style="float:left; width:130px; ">
<table border="0" cellspacing="0" cellpadding="6" id="sudokutable">
  <tr>
    <td class="lt">&nbsp;</td>
    <td class="tt">*</td>
    <td class="rt">WZ</td>
  </tr>
  <tr>
    <td class="ll">&nbsp;</td>
    <td>WXYZ</td>
    <td class="rr">&nbsp;</td>
  </tr>
  <tr>
    <td class="ll">&nbsp;</td>
    <td>*</td>
    <td class="rr">&nbsp;</td>
  </tr>
  <tr>
    <td class="lt">&nbsp;</td>
    <td class="tt">&nbsp;</td>
    <td class="rt">&nbsp;</td>
  </tr>
  <tr>
    <td class="ll">&nbsp;</td>
    <td>XZ</td>
    <td class="rr">&nbsp;</td>
  </tr>
  <tr>
    <td class="lb">&nbsp;</td>
    <td class="bb">YZ</td>
    <td class="rb">&nbsp;</td>
  </tr>
</table>
</div>
如左图,WXYZ和WZ在同一九宫格但不同列中,而WXYZ和XZ、YZ在同一列的不同九宫格中。这样,所有打星号的单元格中不能是Z值。因为:<br />
如果WXYZ=X,则XZ=Z。那么XZ所在列就不能再出现Z; <br />
如果WXYZ=Y,则YZ=Z。那么YZ所在列就不能再出现Z; <br />
如果WXYZ=W,则WZ=Z。那么WZ所在的九宫格中就不能再出现Z;<br />
如果WXYZ=Z。那么WXYZ所在的九宫格中就不能再出现Z。</div>
    
      </li>
</ul>
  </div>
</body>
</html>   

<script>

var timer = null, TGH = TGM = TGS = 0;
var logReg = new RegExp("^ *(?:[0-8]{2}//d(?:(?:[01][1-9]{1,9})|[01])?,?)+ *$", "m");//记录格式
var logText = "记录格式如下/n/n"
            + "单个单元格信息组成格式/n"
            + "所属行号(0-8中某个数字,不能省)"
            + "所属列号(0-8中某个数字,不能省)"
            + "大格的数字(0-9的某个数字,不能省)"
            + "初盘单元格(0或1,0并无小上格值时可省)"
            + "小上格值(1-9最多9个无重复数序,可无)/n/n"
            + "单元格信息跟单元格信息间用英文状态的逗号(,注意不是中文输入法下的)隔开/n"
            + "如下例意思是:第一行第一个单元格大格中无数字、非初盘单元格、小上格数字是123456789,"
            + "第一行第二个单元格大格数字是1、是初盘单元格数字绿色"
            + "第三行第一个单元格大格数字是1、非初盘单元格/n/n"
            + "0000123456789,0111,201";
           
var logFolder = "sudokulogs";
var hasClick = 0; //防止计算时再次点击        


try
{
   var fso = new ActiveXObject("Scripting.FileSystemObject");
   var htaFolder = unescape(location.pathname).match(//w/:[^/:]{5,}/gi); 
  
   if (htaFolder == null)
   {
      alert("获取程序路文件夹路径失败/n"
          + "此问题将导致不能使用fso控件保存、读取进度!"
           );
      htaFolder = "";
   }else
    {
       htaFolder = fso.GetParentFolderName(htaFolder);
    }
}catch(e)
 {
        alert("创建[Scripting.FileSystemObject]文件读写对象失败!/n"
            + "程序保存、载入进度功能将不可用。/n"
            + "可能是此控件被安全程序禁用或卸载了。/n"
            + "你只能手动保存、载入进度。"
               );
              
        fso = null;
 }


function window.onload()
{
  drawTd();
  fsoSearchFile();
}

function getLog()
{  
   var get = new Array();
   var bottomInputValue;
  
for (var forI = forII = 0; forI < 9; forI++)
{
   for (forII = 0; forII < 9; forII++)
    { 
          bottomInputValue = table.rows[forI].cells[forII].lastChild.style.color;
          bottomInputValue =  (bottomInputValue == "") || (bottomInputValue == "green") ?
                    table.rows[forI].cells[forII].lastChild.value * 1 : 0;
      
          if (bottomInputValue || //d/.test(table.rows[forI].cells[forII].firstChild.value))
          {
                get[get.length] = forI + "" + forII + "" + bottomInputValue
                                + (table.rows[forI].cells[forII].lastChild.style.color == "green" ?
                                    ("1" + table.rows[forI].cells[forII].firstChild.value)
                                  : (table.rows[forI].cells[forII].firstChild.value * 1 > 0 ?
                                     ("0" + table.rows[forI].cells[forII].firstChild.value) : "")
                                  );
         }
     }
}

howSave(get.join(","));
}

function howSave(text)
{
    window.clipboardData.setData("Text",text);
   
    if (fso != null)
    {//fso save
       fsoSave(text);
    }else
     {
        prompt("自动保存失败.余局相关信息已保存在剪贴板中和下框中(供粘贴无效手动复制用),"
             + "请把此信息保存好,以供下次继续玩此局时载入用.",text);
             
     }
}

function fsoSearchFile()
{
    if (fso == null)
    {
       return false;
    }
              
    if (!fso.FolderExists( htaFolder + "//" +  logFolder))
    {
        return false;
    }
   
    do
    {
        if ( (fileList.options[fileList.options.length - 1].child != "1")
          && (fileList.options[fileList.options.length - 1].value != "man") )
        {
          fileList.remove(fileList.options.length - 1);
        }else
         {
            break;
         }
    }while (fileList.options.length > 0)
   
    var fp = new Enumerator(fso.getfolder(htaFolder + "//" +  logFolder).files);
    var option;
   
    while(!fp.atEnd())
    {
       option = document.createElement("OPTION");
       fileList.options.add(option);
       option.innerText = "文件:" + fp.item().Name;
       option.value = fp.item().path;
       fp.moveNext();
    }
   
    fp = null;
}

function fsoSave(text)
{   
    var fileName = "";
   
    do
    {
      fileName = prompt("输入进度文件名(点击确定保存,点击取消不保存)","");
     
      if ( (null == fileName)
         )
      {
         return false;
      }  
     
    }while(
              /^ *$/.test(fileName)
           || ( fso.FileExists( htaFolder + "//" +  logFolder + "//" + fileName)
              && (confirm("[" + fileName + "]文件已存在!"
                      + "/n/n点击确定替换存在文件继续保存/n/n"
                      + "点击取消重新输入文件名") == false))
          )
           
    if (!fso.FolderExists( htaFolder + "//" +  logFolder))
    {
        fso.CreateFolder(htaFolder + "//" +  logFolder );
    }
   
    var fn = fso.CreateTextFile(htaFolder + "//" +  logFolder + "//" + fileName, 1, 1);
    fn.write(text);
    fn.close();
    fn = null;
   
    var option = document.createElement("OPTION");
    fileList.options.add(option);
    option.innerText = "文件:" + fileName;
    option.value = htaFolder + "//" +  logFolder + "//" + fileName;
}

function file2Default()
{
   var text;
  
   if (fileList.options[fileList.selectedIndex].child == "1")
   {
     option2Default(eval(fileList.options[fileList.selectedIndex].value));
   }else if ( (fileList.options[fileList.selectedIndex].value == "man")
      && logReg.test(text = prompt("请在下框中输入上次保存的余局信息全部内容.",""))
      )
   {     
      setDefault(text, 0, "上次手工保存余局");
   }else if ((fso != null) && fso.FileExists(fileList.options[fileList.selectedIndex].value))
    {
       var fn = fso.OpenTextFile(fileList.options[fileList.selectedIndex].value, 1, 0, true);
       try
       {
         text = fn.readAll();
           fn.close();
           fn = null;
       }catch(e)
        {
           fn.close();
           fn = null;
           return alert("读取余局信息文件出错,可能是里面没有内容!");
        }
            
       setDefault(text, 0, "上次余局" + fileList.options[fileList.selectedIndex].text);
    }
}

function setDefault(text, allGreen, showText)
{
   if (logReg.test(text))
   {       
      clearTable(); 
      var splits = text.split(",");
      var td;
     
     for (var forI = 0; forI < splits.length; forI++)
     {
        td = table.rows[splits[forI].charAt(0)].cells[splits[forI].charAt(1)];
       
        if (splits[forI].charAt(2) != "0")
        {//大格
           td.lastChild.value = splits[forI].charAt(2);
        }      
       
        if (allGreen || (splits[forI].charAt(3) == "1") )
        {//色
          
           td.lastChild.contentEditable = false;
           td.lastChild.style.color = "green";
        }
       
        if (splits[forI].slice(4) != "")
        {//上小格
            td.firstChild.value = splits[forI].slice(4);
        }
     }
    
     nameShow.innerText = "使用中的初盘是:/n" + showText;
   }else
    {
       alert("你提供要载入的初盘记录/n/n" + text
           + "/n/n未按照以下格式来记录,所以不能识别!/n记录格式如下:/n/n" + logText);
    }
}

function setTime(obj)
{
        if (obj.value == "开始计时")
        { 
         TGH = TGM = TGS = 0;
         timer = setInterval('timeGo();', 1000);
         obj.value = "停止计时";
        }else
         {
            clearInterval(timer);
            timer = null;
            obj.value = "开始计时";
         }
}

function timeGo()
{
      TGS++;
     
      if (TGS == 60)
      {
         TGS = 0;
         TGM++;
        
         if (TGM == 60)
         {
            TGM = 0;
            TGH++;
         }
      }
     
      timeShow.innerText = "耗时" + TGH + "时" + TGM + "分" + TGS + "秒";
}

function resetGameNumber(obj)
{
   easy.style.display = "none";
   middle.style.display = "none";
   hard.style.display = "none";
   hardHard.style.display = "none";
  
   if (obj.options[obj.selectedIndex].child == "1")
   {
     var theE = eval(obj.options[obj.selectedIndex].value);
     theE.style.display = "block";
   }
}

function option2Default(obj)
{
   if (obj.options.length)
   {
      setDefault(obj.options[obj.selectedIndex].value, 1,
               fileList.options[fileList.selectedIndex].text
             + "中的" + obj.options[obj.selectedIndex].text);
   }
}

function drawTd()
{//生成td
 
  var tdO,trO;
  for (var forI = forII = 0; forI < 9; forI++)
  {//9 pic tr
     trO = table.insertRow();
    
     for (forII = 0; forII < 9; forII++)
     {//9 pic td
        tdO = trO.insertCell();
        tdO.id = "tds" + (Math.floor(forI / 3) * 3 + Math.floor(forII / 3));
        tdO.innerHTML = '<input class="topInput" maxlength=9>'
                      + '<input class="bottomInput" maxlength=1>';
     }
  }
}

function keyDown()
{
    var theE = event;
    var theInput = theE.srcElement;
   
    switch(theE.keyCode)
    {//left:37,top:38,right:39,bottom:40
     case 8://back
          return true;
          break;
     default:
           //97-105 1-9
       var inputKey = String.fromCharCode(theE.keyCode - 48);
          
       if (
           ( (96 < theE.keyCode) || (theE.keyCode < 106) )
        && (theInput.value.indexOf(inputKey) < 0)
        &&(checkInput(theInput, inputKey)==0)
          )
       {             
              return true;
       }else
        {
              return false;
        }
          
    }
}

function keyUp()
{
    if (event.keyCode == 8)
    {//back 
       setMark(event.srcElement, 0);
    }
}

function checkInput(obj, inputNumber, inSert)
{//fromCharCode(105-48) == 9
   //检查行
   var cellI = obj.parentElement.cellIndex;
   var rowChilds = obj.parentElement.parentElement.children;
   var tds = document.all(obj.parentElement.id);
   var foundI;//3=小宫,2=行,1=列, 0 =无
  
   for (var forI = 0; forI < 9; forI++)
   {
      foundI = 4;
     
      if (
            ( (--foundI) && (tds[forI].lastChild.value == inputNumber) )
         || ( (--foundI) && (rowChilds[forI].lastChild.value == inputNumber) )
         || ( (--foundI) && (table.rows[forI].cells[cellI].lastChild.value == inputNumber) )
         )
      {
         return foundI;
      }
   }
  
   if (inSert == 1)
   {
    obj.value += inputNumber;
   }
  
  
   setMark(obj, 1);
   return 0;
}

function setMark(obj, on)
{
   if (obj.className == "bottomInput")
   {
       if (/^ *$/g.test(obj.value) && (on == 0))
       {
         obj.removeAttribute("style");
       }else if (ifStart.checked)
       {
         if (ifStart.firstNumber != markColor.options[markColor.selectedIndex].text)
         {
           ifStart.firstNumber = markColor.options[markColor.selectedIndex].text;
           obj.style.textDecoration="underline";
         }
       
         obj.style.color = markColor.options[markColor.selectedIndex].text;
       }
   }
}

function checkRusilt()
{//检查结果
   var rowsSum;
   var cellsSum;
   var tdsSum;
  
   for (var forI = forII = 0; forI < 9; forI++)
   {//大
      rowsSum =   cellsSum  = tdsSum = 0;
     
      for (forII = 0; forII < 9; forII++)
      {//小
         rowsSum += table.rows[forI].cells[forII].lastChild.value * 1;//行和
         cellsSum += table.rows[forII].cells[forI].lastChild.value * 1;//列和
         tdsSum += document.all("tds" + forI)[forII].lastChild.value * 1;//小宫和
      }
           
      if (rowsSum != 45)
      {
           alert("第" + (forI + 1) + "行和不是45,排列不正确!");
           return false;
      }else if (cellsSum != 45)
      {
           alert("第" + (forI + 1) + "列和不是45,排列不正确!");
           return false;
      }else if (tdsSum != 45)
      {
           alert("第" + (forI + 1) + "小宫和不是45,排列不正确!");
           return false;
      }
   }
  
   alert("恭喜你!你过关了!");
}

function clearTable()
{
  for (var forI = forII = 0; forI < 9; forI++)
  {
     for (forII = 0; forII < 9; forII++)
     {
        document.all("tds" + forI)[forII].firstChild.value = "";
        document.all("tds" + forI)[forII].lastChild.value = "";
        document.all("tds" + forI)[forII].lastChild.removeAttribute("style");
        document.all("tds" + forI)[forII].lastChild.contentEditable = true;
     }
  }
 
  nameShow.innerText = "";
  clearInterval(timer);
  timer = null;
  timeButton.value = "开始计时";
}

function ifEdit(how)
{
  for (var forI = forII = 0; forI < 9; forI++)
  {
     for (forII = 0; forII < 9; forII++)
     {
       if (document.all("tds" + forI)[forII].lastChild.value != "")
       {
         if (how)
         {
            
             document.all("tds" + forI)[forII].lastChild.contentEditable = true;
             document.all("tds" + forI)[forII].lastChild.removeAttribute("style");
         }else
          {
             document.all("tds" + forI)[forII].lastChild.contentEditable = false;
             document.all("tds" + forI)[forII].lastChild.style.color = "green";
          }
       }
     }
  }
}

function randomDefault()
{alert('未加入此功能');
}

function showMaybe()
{
  if (hasClick == 1)
  {
     return false;
  }
 
  hasClick = 1;
 
  for (var forI = forII = forIII= 0; forI < 9; forI++)
  {
     for (forII = 0; forII < 9; forII++)
     {
       document.all("tds" + forI)[forII].firstChild.value = "";
      
          if (document.all("tds" + forI)[forII].lastChild.value == "")
          {
             for (forIII = 1; forIII < 10; forIII++)
             {           
                checkInput(document.all("tds" + forI)[forII].firstChild, forIII, 1);
             }
          }
     }
  }
 
  alert("可能数计算完成!");
  hasClick = 0;
}

function doDel()
{
  if (hasClick == 1)
  {
     return false;
  }
 
  hasClick = 1;
  eval(fun.options[fun.selectedIndex].value);
  alert("此候选数法删除完成!");
  hasClick = 0;
}

function isOnly()
{//检查是否只有唯一可能数

  var forI = forII = have = 0;
 
  do
  {
     have = 0;
     
     for (forI = forII = 0; forI < 9; forI++)
     {
        for (forII = 0; forII < 9; forII++)
        {      
             if (document.all("tds" + forI)[forII].firstChild.value.length == 1)
             {
                document.all("tds"+forI)[forII].lastChild.value = document.all("tds"+forI)[forII].firstChild.value;
                delNumber(document.all("tds" + forI)[forII], document.all("tds" + forI)[forII].firstChild.value);        
                document.all("tds" + forI)[forII].firstChild.value = "";
                have = 1;
             }
        }
     }
    
  }while (have == 1)
}

function isOnlyHide()
{//检查是否隐性只有唯一可能数

  var rowTop, cellTop, tdsTop;
  var splits;

  for (var forI = forII = 0; forI < 9; forI++)
  {
     rowTop = cellTop = tdsTop = ".";
    
     for (forII = 0; forII < 9; forII++)
     { //把所有行,列,九宫上格合并  
          rowTop += getTd("row", forI, forII).firstChild.value + ".";  
          cellTop += getTd("cell", forI, forII).firstChild.value + ".";  
          tdsTop += getTd("tds", forI, forII).firstChild.value + ".";
     }
     //return alert(rowTop);
     for (forII = 1; forII < 10; forII++)
     { //用1-9测试所有行,列,九宫上格合并是否有唯一数字 
          if ( (splits = rowTop.split(forII)).length == 2)
          {
              splits = getTd("row", forI, splits[0].split(".").length - 2);//得到含有唯一数字的td
              splits.lastChild.value = forII;
              splits.firstChild.value = "";
              delNumber(splits, forII);
              forI = 0;
              break;
          }
            
          if ( (splits = cellTop.split(forII)).length == 2)
          {
              splits = getTd("cell", forI, splits[0].split(".").length - 2);//得到含有唯一数字的td
              splits.lastChild.value = forII;
              splits.firstChild.value = "";
              delNumber(splits, forII);
              forI = 0;
              break;
          }
         
          if ( (splits = tdsTop.split(forII)).length == 2)
          {
              splits = getTd("tds", forI, splits[0].split(".").length - 2);//得到含有唯一数字的td
              splits.lastChild.value = forII;
              splits.firstChild.value = "";
              delNumber(splits, forII);
              forI = 0;
              break;
          }
     }
  }
}

function AreaDel()
{//区块删除法 
  return alert("未写好");
  var tdF, tdT;
  var delRow = delCell = delTds = 1;
  var delTd;
 
  for (var forI = forII = forIII = for4 = for5 = 0; forI < 9; forI++)
  {//行,列,大宫
     for (forII = 0; forII < 9; forII++)
     {//行中小格,列中小格,宫中小格 
          tdF = getTd("row", forI, forII);
         
          if (tdF.firstChild.value.length < 1)
          {
             continue;
          }
         
          for (forIII = 0; forIII < tdF.firstChild.value.length; forIII++)
          {//源td的字符个数
             delRow = delCell = delTds = 1;
            
             for (for4 = 0; for4 < 9; for4++)
             {//要比较宫中九个小格
               tdT = getTd("tds",tdF.id.split("tds")[1],for4);
              
               if (tdT.firstChild.value.indexOf(tdF.firstChild.value.charAt(forIII)) > -1)
               {//包含
                 if (delRow)
                 {
                   delRow = (tdT.parentElement.rowIndex == tdF.parentElement.rowIndex);
                 }
                 //在某个九宫单元格找到此数字,但与源单元格行标不同,说明行不能使用此删除法
                 if (delCell)
                 {
                    delCell = (tdT.cellIndex == tdF.cellIndex);
                 }
                 //在某个九宫单元格找到此数字,但与源单元格列标不同,说明列不能使用此删除法                
               }
              
               if ( (delRow + delCell) == 0)
               {//九宫中,行,列都不能应用退出查找
                 break;
               }else if(for4 == 8)
                {//比较到最后一个单元格
                   if (delRow)
                   {//宫中行可就用
                      for(for5 = 0; for5 < 9; for5++)
                      {//行中九个小格
                        delTd = getTd("row", tdF.parentElement.rowIndex, for5);
                       
                        if (delTd.id != tdF.id)
                        {//删除非tdFid的数字
                         delTd.firstChild.value=delTd.firstChild.value.replace(tdF.firstChild.value.charAt(forIII),'');
                        }
                      }
                   }
                  
                   if (delCell)
                   {//列
                      for(for5 = 0; for5 < 9; for5++)
                      {
                        delTd = getTd("cell", tdF.parentElement.rowIndex, for5);
                       
                        if (delTd.id != tdF.id)
                        {//删除非tdFid的数字,未完成
                          delTd.firstChild.value =
                               delTd.firstChild.value.replace(tdF.firstChild.value.charAt(forIII), "");
                        }
                      }
                   }
                  
                }
             }
          }
     }
  }
 
}

function delNumber(td, number)
{//从行,列,九宫备选数删除数字
    var tds = document.all(td.id);
    var rowIndex = td.parentElement.rowIndex;
    var cellIndex = td.cellIndex;   
   

  for (var forI = 0; forI < 9; forI++)
  {      
          tds[forI].firstChild.value = tds[forI].firstChild.value.replace(number, "");//九宫
          table.rows[rowIndex].cells[forI].firstChild.value =
                            table.rows[rowIndex].cells[forI].firstChild.value.replace(number, "");//rows
          table.rows[forI].cells[cellIndex].firstChild.value =
                            table.rows[forI].cells[cellIndex].firstChild.value.replace(number, "");//cells
         
  }
}

function getTd(what, index1, index2)
{
   switch (what)
   {
       case "row":
         return table.rows[index1].cells[index2];
       case "cell":
         return table.rows[index2].cells[index1];
       case "tds":
         return eval(what + index1 + "[" + index2 + "]");        
   }
}
</script>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数独算法说明:用三个二维数组记录数独每个点的状态,SD(i, j)显示数值,也是真实数值(1到9)。ST(i, j)状态,1可由用户输入,2是题目给定的,不能改。SY(i, j)这符串,记录每个点中可能的值。 1、在进行自动计算时,只计算ST(i, j)为1的点,首先将所有状态为1的点的SY(i, j)值全部设为"123456789",SD(i, j)值全部设为0 2、逐点扫描,找到一个点,然后将该点所在的行、列、区域中已存在的SD(x, y)值从SY(i, j)中删除,因为数独规则是一个数值,在行、列、区域都不重复。 3、经第二步处理后,SY(i, j)为空,说明题目错误,SY(i, j)值为一位数字,就说明该点的值是唯一的,可以确定了。 4、剩余的SY(i, j)值最少也是二个数字的,或更多位数。随机从这些两位数的SY(i, j)中选取一个点。取其中的一位确定为该点的值后,重复第2步。如果错误遇错,则重复执行第4步。直到所有点都被确定。 注意:第2步是需要多次重复执行的,所有可用递归函数完成。如果执行结果出现错误(某数出现重复,或某点无值),需要对该过程所执行的所有操作进行回退。 第4步也是需要重复执行的。本和序用Goto跳转方式实现多次执行。 简单的数独,要么所有的点都具有独一值,第1步执行完成后,就已全部完成。或者具有多个解,随意猜测一个二位数的SY(i, j)的值都能成功。 难的数独,是可唯一确定的点很少,大部分点都有两种或多种可能的值,但最终正确答案只有一种或很少种解。 软件在自动计算过程中,具有很大的偶然性,对于骨灰级的数独题目在计算过程中,时间短的可能不到1秒就能完成,长的可能要几分钟,需要将各种可能性都测试一遍才有结果。 只要题目正确,多计算几次就能得到答案。 程序只处理有两种可能值的情况,对只存在三种可能值的情况未进一步处理,该情况非常极端了。 软件中包含网上下载的200个数独题目。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值