求一个能随机产生数独的源码(200分)

  • 主题发起人 主题发起人 yxgszm
  • 开始时间 开始时间
[B)][B)][B)][B)][B)][B)][B)][B)][B)][B)]
 
朋友写了个C++的,哪位高手帮我转化成delphi 的嘛,一样给分哈
Demo请发送到yxgszm@163.com 谢谢
源码如下:
#ifndef SUDOKU_RICK_0701_
#define SUDOKU_RICK_0701_
class CSudoku
{
int map[9][9];
int smod;
int solves;
int check(int,int,int*);
void dfs();
public:
enum{ANY=0,ALL=1};
CSudoku(int n=40);// 随机生成数独,n越大越难
CSudoku(int *data);// 人工指定数独
virtual ~CSudoku();
void display();// 显示数独
int resolve(int mod=ALL);// 解数独
};
#endif
#include "sudoku.h"
#include "stdio.h"
#include "stdlib.h"
#include "time.h"
CSudoku::CSudoku(int n)
{
int i,j;
srand(time(0));
do
{
for(i=0;i<9;++i)
{
for(j=0;j<9;++j)
map[j]=0;
j=rand()%9;
map[j]=i+1;
}
}
while(!resolve(ANY));
// 挖窟窿
for(int k=0;k<n;)
{
i=rand()%81;
j=i%9;
i=i/9;
if(map[j]>0)
{
map[j]=0;
++k;
}
}
//printf("(randomized sudoku created with %d blanks.)/n",blanks);
}
CSudoku::CSudoku(int *data)
{
int *pm=(int*)map;
for(int i=0;i<81;++i)
pm=data;
}
CSudoku::~CSudoku()
{
return;
}
void CSudoku::display()
{
for(int i=0;i<9;++i)
{
for(int j=0;j<9;++j)
{
if(map[j]>0)
printf("< %d > ",map[j]);
else
printf("[ ] ");
}
printf("/n");
}
}
int CSudoku::resolve(int mod)
{
smod=mod;
if(mod==ALL)
{
solves=0;
dfs();
return solves;
}
else
if(mod==ANY)
{
try
{
dfs();
return 0;
}
catch(int)
{
return 1;
}
}
return 0;
}
int CSudoku::check(int y,int x,int *mark)
{
int i,j,is,js,count=0;
for(i=1;i<=9;++i)
mark=0;
for(i=0;i<9;++i)
mark[map[y]]=1;
for(i=0;i<9;++i)
mark[map[x]]=1;
is=y/3*3;
js=x/3*3;
for(i=0;i<3;++i)
{
for(j=0;j<3;++j)
mark[map[is+i][js+j]]=1;
}
for(i=1;i<=9;++i)
if(mark==0)
count++;
return count;
}
void CSudoku::dfs()
{
int i,j,im=-1,jm,min=10;
int mark[10];
for(i=0;i<9;++i)
{
for(j=0;j<9;++j)
{
if(map[j])
continue;
int c=check(i,j,mark);
if(c==0)
return;
if(c<min)
{
im=i;
jm=j;
min=c;
}
}
}
if(im==-1)
{
if(smod==ALL)
{
printf("No. %d:/n",++solves);
display();
return;
}
else
if(smod==ANY)
{
throw(1);
}
}
check(im,jm,mark);
for(i=1;i<=9;++i)
{
if(mark==0)
{
map[im][jm]=i;
dfs();
}
}
map[im][jm]=0;
}
#include <iostream>
#include "sudoku.h"
using namespace std;
int main()
{
int data1[]=
{4,9,0,0,0,6,0,2,7,
5,0,0,0,1,0,0,0,4,
6,0,0,0,0,8,0,0,3,
1,0,4,0,0,0,0,0,0,
0,6,0,0,0,0,0,5,0,
0,0,0,0,0,0,2,0,8,
7,0,0,2,0,0,0,0,5,
8,0,0,0,9,0,0,0,1,
3,4,0,5,0,0,0,6,2
};
int data2[]=
{7,4,0,0,8,0,0,1,6,
9,0,0,0,3,5,0,0,4,
0,0,0,7,0,0,0,0,0,
0,7,0,0,0,9,5,0,0,
6,1,0,0,5,0,0,8,7,
0,0,2,6,0,0,0,4,0,
0,0,0,0,0,4,0,0,0,
3,0,0,5,6,0,0,0,2,
5,6,0,0,1,0,0,3,9
};
int blanks;
cout<<"随机生成一个数独,输入空格数";
cin>>blanks;
CSudoku s(blanks);
s.display();
cout<<"开始解数独:"<<endl;
s.resolve();
return 0;
}
测试运行结果:

随机生成一个数独,输入空格数40
[ ] < 7 > < 8 > [ ] [ ] [ ] [ ] [ ] < 6 >
< 6 > < 3 > [ ] < 7 > [ ] < 2 > < 8 > [ ] < 5 >
< 2 > [ ] [ ] < 8 > [ ] [ ] [ ] [ ] < 9 >
< 3 > < 9 > [ ] < 1 > [ ] [ ] < 2 > < 5 > [ ]
[ ] [ ] [ ] < 2 > < 5 > < 4 > < 6 > [ ] < 3 >
< 4 > [ ] [ ] [ ] [ ] [ ] < 7 > < 1 > [ ]
[ ] [ ] [ ] < 4 > < 7 > [ ] [ ] < 3 > < 1 >
< 9 > < 4 > [ ] < 6 > < 2 > < 1 > < 5 > < 8 > [ ]
[ ] [ ] < 7 > < 9 > < 3 > [ ] [ ] < 6 > < 2 >
开始解数独:
No. 1:
< 1 > < 7 > < 8 > < 5 > < 4 > < 9 > < 3 > < 2 > < 6 >
< 6 > < 3 > < 9 > < 7 > < 1 > < 2 > < 8 > < 4 > < 5 >
< 2 > < 5 > < 4 > < 8 > < 6 > < 3 > < 1 > < 7 > < 9 >
< 3 > < 9 > < 6 > < 1 > < 8 > < 7 > < 2 > < 5 > < 4 >
< 7 > < 8 > < 1 > < 2 > < 5 > < 4 > < 6 > < 9 > < 3 >
< 4 > < 2 > < 5 > < 3 > < 9 > < 6 > < 7 > < 1 > < 8 >
< 5 > < 6 > < 2 > < 4 > < 7 > < 8 > < 9 > < 3 > < 1 >
< 9 > < 4 > < 3 > < 6 > < 2 > < 1 > < 5 > < 8 > < 7 >
< 8 > < 1 > < 7 > < 9 > < 3 > < 5 > < 4 > < 6 > < 2 >
No. 2:
< 1 > < 7 > < 8 > < 5 > < 4 > < 9 > < 3 > < 2 > < 6 >
< 6 > < 3 > < 9 > < 7 > < 1 > < 2 > < 8 > < 4 > < 5 >
< 2 > < 5 > < 4 > < 8 > < 6 > < 3 > < 1 > < 7 > < 9 >
< 3 > < 9 > < 6 > < 1 > < 8 > < 7 > < 2 > < 5 > < 4 >
< 7 > < 8 > < 1 > < 2 > < 5 > < 4 > < 6 > < 9 > < 3 >
< 4 > < 2 > < 5 > < 3 > < 9 > < 6 > < 7 > < 1 > < 8 >
< 8 > < 6 > < 2 > < 4 > < 7 > < 5 > < 9 > < 3 > < 1 >
< 9 > < 4 > < 3 > < 6 > < 2 > < 1 > < 5 > < 8 > < 7 >
< 5 > < 1 > < 7 > < 9 > < 3 > < 8 > < 4 > < 6 > < 2 >
Press any key to continue
 
“生成容易,怎么判断难度值.”先为我说这句话的冒失向楼主道歉。以下是我写的代码,能够按规则随机生成数独,但仅仅是能够而已。
program Project2;
{$APPTYPE CONSOLE}
type
TArr33 = array [0..2, 0..2] of Byte;
TArr99 = array [0..8, 0..8] of Byte;
var
Square: TArr99;
i: Integer;
Blank: Integer;
procedure Print(const A: TArr99);
var
i, j: Integer;
begin
for i:=0 to 8do
begin
for j:=0 to 8do
if A[i, j]>0 then
Write(A[i, j]: 2)
else
Write('_':2);
WriteLn
end
end;

procedure RandomFill(var A: TArr33);
var
t: array [0..8] of Integer;
Len: Integer;
i, j, k: Integer;
begin
for i:=0 to 8do
t:=i+1;
Len:=9;
for i:=0 to 2do
for j:=0 to 2do
begin
k:=Random(Len);
A[i, j]:=t[k];
t[k]:=t[Len-1];
Dec(Len)
end
end;

procedure Init(var A: TArr99);
var
Temp: TArr33;
i, j, k, l: Integer;
begin
for i:=0 to 2do
for j:=0 to 2do
begin
RandomFill(Temp);
for k:=0 to 2do
for l:=0 to 2do
A[i*3+k, j*3+l]:=Temp[k, l]
end
end;

function RegulateRow(var A: TArr99;
const Index: Integer): Integer;
var
i, j, k: Integer;
t: array [1..9] of array of Integer;
begin
Result:=0;
for i:=1 to 9do
SetLength(t, 0);
for i:=0 to 8do
if A[Index, i]<>0 then
begin
SetLength(t[A[Index, i]], Length(t[A[Index, i]])+1);
t[A[Index, i], Length(t[A[Index, i]])-1]:=i
end;
for i:=1 to 9do
if Length(t)>1 then
begin
k:=Random(Length(t));
for j:=0 to Length(t)-1do
if j<>k then
begin
A[Index, t[i, j]]:=0;
Inc(Result)
end
end
end;

function RegulateCol(var A: TArr99;
const Index: Integer): Integer;
var
i, j, k: Integer;
t: array [1..9] of array of Integer;
begin
Result:=0;
for i:=1 to 9do
SetLength(t, 0);
for i:=0 to 8do
if A[i, Index]<>0 then
begin
SetLength(t[A[i, Index]], Length(t[A[i, Index]])+1);
t[A[i, Index], Length(t[A[i, Index]])-1]:=i
end;
for i:=1 to 9do
if Length(t)>1 then
begin
k:=Random(Length(t));
for j:=0 to Length(t)-1do
if j<>k then
begin
A[t[i, j], Index]:=0;
Inc(Result)
end
end
end;

begin
Randomize;
Init(Square);
Blank:=0;
for i:=0 to 8do
begin
Blank:=Blank+RegulateRow(Square, i);
Blank:=Blank+RegulateCol(Square, i)
end;
Print(Square);
WriteLn('Blank=', Blank);
ReadLn
end.
但是,俺后来深入看了一下数独的一些网站,一个成功的数独题要满足以下几个条件:
1.有且仅有一组解
2.求解过程中每个数字都必须是通过逻辑推理填进去的,不能有任何猜测或代入的操作
3.日系数独题还强调点对称
这段代码没有一点能满足,因此设计“成功”的数独题是个小概率事件。
 
后来俺就想了,要保证出的题目有解,最好是生成一个完整的数独解,再挖掉一些数字。貌似搜索这个万金油又能出来了,但搜索和随机怎么兼顾又成问题。看了楼主贴的c++代码,好象是绕过了这个矛盾——先在每一行上只填一个数字,然后用搜索求一解,再从解里挖掉若干数字。这样既能保证有解,又能保证一定的随机。但是,没有考虑多解的情况。难不成挖了以后再来求解的数目,等于1时才结束?虽然这种方法俺能用程序实现,但未免太笨拙了一点。不知哪位有更好的思路,帮俺提示提示。不一定需要程序的思路,只要知道人来做怎么考虑就行。
 
to LeeChange
能不能将c++的代码,转化成delphi的,发个到我邮箱里面,谢谢!
祝大家节日快乐哈
 

Similar threads

S
回复
0
查看
1K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
900
SUNSTONE的Delphi笔记
S
后退
顶部