数独编程
⑴ 基于SAT的数独游戏求解程序,求c语言代码
用0代表要填的数
#include <stdio.h>
#include <stdlib.h>
#define SIZE 9
#define get_low_bit(x) ((~x&(x-1))+1)
struct{
int left;
char num;
char try;
}board[SIZE][SIZE];
int bit2num(int bit)
{
switch(bit){
case 16:
case 256:
return 9;
基础解法
排除法(摒除法)
摒除法:用数字去找单元内唯一可填空格,称为摒除法,数字可填唯一空格称为排除法 (Hidden Single)。
根据不同的作用范围,摒余解可分为下述三种:
数字可填唯一空格在“宫”单元称为宫排除(Hidden Single in Box),也称宫摒除法。
数字可填唯一空格在“行”单元称为行排除法(Hidden Single in Row),也称行摒除法。
⑵ 数独进入瓶颈了,求解!
编程进行了计算。本题只有一个唯一的解。
附代码:
type x9
integer(1) :: a
integer(1) :: s(9)
integer(1) :: np
end type
type(x9) :: kk(9,9)
data kk%a/ &
0,0,0,0,0,4,0,0,3, &
0,0,0,6,0,8,0,5,0, &
8,0,7,0,3,0,6,0,0, &
0,0,0,1,0,0,9,7,0, &
0,5,0,9,6,3,0,2,0, &
0,1,2,0,0,0,0,0,8, &
0,0,5,0,2,0,4,0,7, &
0,8,0,3,0,9,0,0,0, &
1,0,0,4,0,0,0,0,0 /
kk%np=-kk%a
do i=1,9
do j=1,9
kk(j,i)%s=0
if(kk(j,i)%np.eq.0) then
do k=1,9
do il=1,9
if(kk(il,i)%a.eq.k) exit
end do
if(il.le.9) cycle
do ih=1,9
if(kk(j,ih)%a.eq.k) exit
end do
if(ih.le.9) cycle
ni=((i+2)/3-1)*3+1
nj=((j+2)/3-1)*3+1
do ih=ni,ni+2
do il=nj,nj+2
if(kk(il,ih)%a.eq.k) exit
end do
if(il.le.nj+2) exit
end do
if(ih.le.ni+2) cycle
if(il.le.nj+2) cycle
kk(j,i)%s(k)=k
end do
else
kk(j,i)%s(1)=kk(j,i)%a
end if
end do
end do
n=1
kk%a=0
kk%np=0
m=0
do while(.true.)
if(n.gt.81) exit
i=(n+8)/9
j=n-9*(i-1)
kk(j,i)%np=kk(j,i)%np+1
k=kk(j,i)%np
if(k.gt.9) then
if(n.eq.1) exit
kk(j,i)%a=0
n=n-1
cycle
else
kk(j,i)%a=0
end if
if(kk(j,i)%s(k).eq.0) then
cycle
else
do ih=1,i
if(kk(j,ih)%a.eq.kk(j,i)%s(k)) exit
end do
if(ih.le.i) cycle
do il=1,j
if(kk(il,i)%a.eq.kk(j,i)%s(k)) exit
end do
if(il.le.j) cycle
ni=((i+2)/3-1)*3+1
nj=((j+2)/3-1)*3+1
do ih=ni,i
do il=nj,nj+2
if(kk(il,ih)%a.eq.kk(j,i)%s(k)) exit
end do
if(il.le.nj+2) exit
end do
if(il.le.nj+2) cycle
if(ih.le.i) cycle
kk(j,i)%a=kk(j,i)%s(k)
if(n.eq.81) then
m=m+1
write(*,'(/,2x,a,i3)') 'find = ',m
do jj=1,9
write(*,'(1x,9i2)') kk(1:9,jj)%a
end do
else
n=n+1
i=(n+8)/9
j=n-9*(i-1)
kk(j,i)%np=0
cycle
end if
end if
end do
end
⑶ 谁能告诉我数独游戏的编程思维啊
一、解数独
1、标记
2、利用各种方法减少标记数量,例如显性数对删减法、隐形唯一数法、隐形数对法、区域删减法、区块删减法、三四链数删减法等等
3、填充,利用唯一值法,如果那个标记中只有一个可填了,这就是结果了。
4、假设法,如果各种方法(至少你知道的)都用了还是没有唯一数,那只能假设了,按一定顺序某个单元格标记中假设一个就是要填充的数,然后重复上面的步骤,如果得到无解(就是出现某个单元格的没有可填的数),那就退回,换一个数继续。(一般这个过程用递归完成)
二、如何生成题目
会解数独后,生成就不是问题了,我的方法是分为两步首先随机填充1-9到第一行,然后用上诉方法产生一个解。再次,随机一个一个数删除,每删除一个数重复上诉方法,看看是否是唯一解,如果是继续删除(不是就恢复,删其它的),直到达到一定目的为止。这样就产生一个数独题目。
⑷ 怎么用excel做数独游戏
用excel做数独游戏是比较复杂的,首先要学会VBA编程。
⑸ 学数独好呢!还是编程好
数独是学习解决问题的思路,编程是学习赖以生存的手段。
只会编程不会数独可能人生少了点什么但不会混不下去,只会数独不会编程可能连吃饱都是个问题。
⑹ 81格的九宫格,用c语言编程,求助
#include"stdio.h"
//定义栈的最大长度
#defineMAXSTACKLENGTH81
//待求解的九宫格矩阵,空白位置用0表示
intjiuGongArray[][9]={{0,0,0,0,4,0,0,3,2},
{4,0,0,0,0,1,0,0,0},
{5,3,0,6,0,0,0,0,7},
{3,0,0,5,1,0,7,0,0},
{0,0,5,0,3,0,2,0,0},
{0,0,9,0,7,4,0,0,3},
{1,0,0,0,0,9,0,4,6},
{0,0,0,1,0,0,0,0,9},
{8,9,0,0,6,0,0,0,0}};
//空缺数据组成的矩阵,共有九个九宫格单元,从左到右,然后从上到下编号为0-8;
//例如:第一个九宫格单元空缺的数字为1,4,8,则矩阵dataNeedToBeInsert的第一行
//为{1,0,0,4,0,0,0,8,0}
intdataNeedToBeInsert[][9]={{1,2,3,4,5,6,7,8,9},
{1,2,3,4,5,6,7,8,9},
{1,2,3,4,5,6,7,8,9},
{1,2,3,4,5,6,7,8,9},
{1,2,3,4,5,6,7,8,9},
{1,2,3,4,5,6,7,8,9},
{1,2,3,4,5,6,7,8,9},
{1,2,3,4,5,6,7,8,9},
{1,2,3,4,5,6,7,8,9}};
//定义栈单元的结构
typedefstruct
{
intxPosition;
intyPosition;
intjiuGongGePosition;
intnum;
}node;
//定义栈数组
nodestack[MAXSTACKLENGTH];
//由给定的九宫格矩阵,查找空缺的数据
voidFindDataToBeInsert(void)
{
inti,j;
intx,y;
for(i=0;i<9;i++)
for(j=0;j<9;j++)
{
if(jiuGongArray[i][j]!=0)
{
x=(i/3)*3+j/3;
y=jiuGongArray[i][j]-1;
dataNeedToBeInsert[x][y]=0;
}
}
}
//输出m*n的矩阵
voidPrintArray(int*ptr,intm,intn)
{
inti,j;
intdata;
inttemp;
temp=n-1;
for(i=0;i<m;i++)
for(j=0;j<n;j++)
{
data=*(ptr+i*n+j);
printf("%d",data);
if(j==temp)
{
printf(" ");
}
}
}
//核实是否满足结束条件
intCheckEnd(void)
{
inti,j,sum;
for(i=0;i<9;i++)
{
sum=0;
for(j=0;j<9;j++)
{
sum+=jiuGongArray[i][j];
}
if(sum!=45)
{
return-1;
}
}
for(j=0;j<9;j++)
{
sum=0;
for(i=0;i<9;i++)
{
sum+=jiuGongArray[i][j];
}
if(sum!=45)
{
return-1;
}
}
return0;
}
//从矩阵dataNeedToBeInsert[][]中查找下一个数据
intFindNextData(intm,intn,int*xPosition,int*yPosition)
{
intstate=0;
if(n>8)
{
n=0;
m++;
}
if(m>8)
{
state=CheckEnd();
if(state!=0)
return-1;
else
return1;
}
while(dataNeedToBeInsert[m][n]==0)
{
if(n<8)
n++;
else
{
n=0;
m++;
if(m>8)
{
state=CheckEnd();
if(state!=0)
return-1;
else
return1;
}
}
}
*xPosition=m;
*yPosition=n;
return0;
}
//核实元素对应的行和列是否有相同的数字
intCheckLine(intm,intn,intnum)
{
inti;
for(i=0;i<9;i++)
{
if(jiuGongArray[m][i]==num)
return-1;
}
for(i=0;i<9;i++)
{
if(jiuGongArray[i][n]==num)
return-1;
}
return0;
}
//核实是否满足入栈条件
intCheckCanPush(intm,intn,int*position)
{
intstart=*position;
inti,temp1,temp2,temp3,temp4;
intnum;
temp1=(m/3)*3;
temp2=(m%3)*3;
num=dataNeedToBeInsert[m][n];
for(i=start;i<10;i++)
{
temp3=temp1+(start-1)/3;
temp4=temp2+(start-1)%3;
if(jiuGongArray[temp3][temp4]!=0)
{
start++;
continue;
}
if(CheckLine(temp3,temp4,num)!=0)
{
start++;
continue;
}
else
{
*position=start;
return0;
}
}
return-1;
}
//入栈
intPush(int*top,intxPosition,intyPosition,intjiuGongGePosition,intnum)
{
if(*top>=MAXSTACKLENGTH)
{
printf("Reachstacktop! ");
return-1;
}
else
{
(*top)++;
stack[*top].xPosition=xPosition;
stack[*top].yPosition=yPosition;
stack[*top].jiuGongGePosition=jiuGongGePosition;
stack[*top].num=num;
return0;
}
}
//出栈
intPop(int*top,int*xPosition,int*yPosition,int*jiuGongGePosition,int*num)
{
if(*top==-1)
{
printf("Reachstackbottom! ");
return-1;
}
else
{
*xPosition=stack[*top].xPosition;
*yPosition=stack[*top].yPosition;
*jiuGongGePosition=stack[*top].jiuGongGePosition;
*num=stack[*top].num;
(*top)--;
return0;
}
}
voidmain()
{
intend=0;
intline=0;
introw=0;
inttop=-1;
intpositionInUnitArray=1;
intstate=0;
intnum;
FindDataToBeInsert();
PrintArray(jiuGongArray,9,9);
while(end!=1)
{
state=FindNextData(line,row,&line,&row);
if(state==0)
{
state=CheckCanPush(line,row,&positionInUnitArray);
if(state==0)
{
state=Push(&top,line,row,positionInUnitArray,dataNeedToBeInsert[line][row]);
if(state==0)
{
jiuGongArray[(line/3)*3+(positionInUnitArray-1)/3][(line%3)*3+(positionInUnitArray-1)%3]=dataNeedToBeInsert[line][row];
row++;
positionInUnitArray=1;
}
else
end=1;
}
else
{
state=Pop(&top,&line,&row,&positionInUnitArray,&num);
if(state==0)
{
jiuGongArray[(line/3)*3+(positionInUnitArray-1)/3][(line%3)*3+(positionInUnitArray-1)%3]=0;
positionInUnitArray++;
}
else
end=1;
}
}
elseif(state==1)
{
printf(" ");
PrintArray(jiuGongArray,9,9);
end=1;
}
else
{
printf("Someerroroccur! ");
end=1;
}
}
}
⑺ 如何用pascal编程解“数独”
这是个好问题,我也想知道,我想楼主是不是把帖子发的编程那边。
⑻ 数独算法
给你数独计算器:
http://blog.xunlei.com/web/category.html?uin=mianmiany1978&category_id=143
数独游戏:
http://blog.xunlei.com/web/category.html?uin=mianmiany1978&category_id=174
数独算法:
http://www.puzzle8.com/suku/news.asp
数独快速入门(上篇)
数独快速入门(中篇)
数独快速入门(下篇)
唯一解法
唯一候选数法
隐性三链数删减法
隐性数对删减法
三链列删减法
区块删减法
矩形顶点删减法
关键数删减法
补充:
合格的数独是只有唯一解。
而数独有难易度的分类,找一份报纸注意刊登的数独谜题是1星,还是5星。
在网络上,更分成容易题、进阶题、难题、极难题、超难题....
一般都是依据需要运用的技巧,而技巧是区分难易的。
数独不用猜测,解题全部是运用逻辑推理。
数独不用电脑程序分析,就可以解的题目是直观法数独题。
而超难题是需要电脑分析,及把全盘标示可选数,那是可选数谜题。
没有所谓解题通则。
1.直观解(一般报纸、书籍)
直观法技巧
直观法技巧 01 (容易级) 唯一解
直观法技巧 02 (容易级) 基本摒除
直观法技巧 03 (进阶级) 宫对行列摒除
直观法技巧 04 (进阶级) 行列对宫摒除
直观法技巧 05 (进阶级) 群组解法
直观法技巧 06 (困难级) X-Wing摒除法01
直观法技巧 06 (困难级) X-Wing摒除法02
直观法技巧 07 (困难级) 数偶摒除法
http://hi..com/kiwy07/blog/item/181fc482a153f3bd6c8119ab.html
2.可选数(以程序自动生成可选数)
Last value in block, row or column
Hidden Single in block
Hidden Single in row or column
Direct Pointing
Direct Claiming
Direct Hidden Pair
Naked Single
Direct Hidden Triplet
Pointing
Claiming
Naked Pair, X-Wing, Hidden Pair
Naked Triplet, Swordfish, Hidden Triplet
XY-Wing, XYZ-Wing
Unique rectangles and loops
Naked Quad, Jellyfish, Hidden Quad
Bivalue Universal Graves
Aligned Pair Exclusion
Bidirectioal X-Cycles and Y-Cycles
Forcing X-Chains
Forcing Chains, Bidirectional Cycles
Nishio
Cell/Region Forcing Chains
Dynamic Forcing Chains
http://diuf.unifr.ch/people/juillera/Sudoku/FAQ.html
通则无法解的题
直观难题
006589307
030602008
809703500
000891403
394265871
180374000
003026785
000458030
008037200
可选数极难题
970000000
003927000
008410709
300700400
060050070
007040003
105074900
000068507
786000042
不要把谜题解一次列出,而是找出下一步,及他的逻辑推理方法。
不要用猜测。