以前很喜欢玩数独游戏,最近有空突然想到何不用php写个程序来计算数独
琢磨了一下, 大致思路是 横纵9个方格 放9个数字,每个数字在其横纵范围只出现一次.
php 里可以用二维数组表示 例如
array(
array(6 , 7 , 9 , 4 , 5 , 8 , 2 , 1 , 3)
array(2 , 3 , 5 , 9 , 1 , 4 , 7 , 6 , 8)
array(1 , 2 , 4 , 8 , 9 , 3 , 6 , 5 , 7)
array(9 , 1 , 3 , 7 , 8 , 2 , 5 , 4 , 6)
array(8 , 9 , 2 , 6 , 7, 1 , 4 , 3 , 5)
array(3 , 4 , 6 , 1 , 2 , 5 , 8 , 7 , 9)
array(7 , 8 , 1 , 5 , 6 , 9 , 3 , 2 , 4)
array(4 , 5 , 7 , 2 , 3 , 6 , 9 , 8 , 1)
array(5 , 6 , 8 , 3 , 4 , 7 , 1 , 9 , 2)
);
上面的二维数组就是一个数独的解.而数独游戏就是挖去里面的一些数字,然后靠推理计算得出这个解.
那么程序里可以把这些被挖去的数字设置为0
例如:
array(
array(6 , 7 , 0 , 4 , 5 , 0 , 2 , 1 , 3)
array(2 , 0 , 5 , 0, 1 , 4 , 7 , 6 , 8)
array(1 , 0 , 0 , 0 , 9 , 3 , 6 , 5 , 7)
array(9 , 1 , 3 , 7 , 8 , 0 , 5 , 4 ,0)
array(8 , 9 , 0 , 6 , 7, 1 , 4 , 3 , 0)
array(0 , 4 , 0 , 1 , 2 , 0 , 8 , 7 , 0)
array(7 , 0 , 1 , 5 , 0 , 9 , 3 , 2 , 4)
array(0 , 5 , 7 , 2 , 3 , 6 , 9 , 8 , 1)
array(5 , 6 , 8 , 0, 0 , 0 , 1 , 9 , 2)
);
这就是一个数独题. 现在就需要写个程序来求出解.
初步代码就很简单了.如下
class shudu{
public $data;
function shudu($data){
$this->data = array();
foreach($data as $k=>$v){
foreach($v as $ka=>$va){
$this->data[$k][$ka] = $va;
$this->row[$k][]=$va;
$this->col[$ka][]=$va;
}
}
}
function cal(){
for($i=0;$i<9;$i++){
for($j=0;$j<9;$j++){
if($this->data[$i][$j] == 0) {
for($n=1;$n<10;$n++){
if(in_array($n,$this->row[$i]) || in_array($n,$this->col[$j])) continue;
$this->data[$i][$j] = $n;
$this->row[$i][]=$n;
$this->col[$j][]=$n;
$s = new shudu($this->data);
$s->cal();
}
if($this->data[$i][$j] == 0){
return false;
}
}
}
}
$this->out();
}
function out(){
for($i = 0; $i < 9; $i++){
for($j = 0; $j < 9; $j++){
echo " ".$this->data[$i][$j]." ";
}
echo "\n";
}
die;
}
}
$arr = array(
array(6,7,0,4,5,0,2,1,3),
array(2,0,5,0,1,4,7,6,8),
array(1,0,0,0,9,3,6,5,7),
array(9,1,3,7,8,0,5,4,0),
array(8,9,0,6,7,1,4,3,0),
array(0,4,0,1,2,0,8,7,0),
array(7,0,1,5,0,9,3,2,4),
array(0,5,7,2,3,6,9,8,1),
array(5,6,8,0,0,0,1,9,2),
);
$s=new shudu($arr);
$s->cal();
结果输出
6 7 9 4 5 8 2 1 3
2 3 5 9 1 4 7 6 8
1 2 4 8 9 3 6 5 7
9 1 3 7 8 2 5 4 6
8 9 2 6 7 1 4 3 5
3 4 6 1 2 5 8 7 9
7 8 1 5 6 9 3 2 4
4 5 7 2 3 6 9 8 1
5 6 8 3 4 7 1 9 2
就得到答案了..
程序本身还可以优化一下.目前是一行一行扫描可以考虑用随机填空的模式或者根据当前已知出现最多的数字来一个个填或者缺少数字最少的行或者列开始扫描.计算速度就会快很多了.
算法有待完善.不过这个程序应付一般的数独题目应该是足够了.
更高级的应用还有采用多线程和分布式计算.多行多列同时扫描, 那样计算速度还会以数量级的形式上升.当然这就有点大炮打文字的感觉了.