回 帖 发 新 帖 刷新版面

主题:Pascal程序如何随机产生数独

是数独有特定的pattern ma?? 或是怎样``??如何才知道它是否一个可以解开而且有足够提示去解开的数独?/

请各大大教教我

回复列表 (共5个回复)

沙发

先解释一下数独:在9*9正方形的81个格子内填入9个1..9的序列。
限制条件是:
 1.将9*9的方阵划分为9个3*3的区域(用a[1..9,1..9]的二维数组装的话,可以表述为第一个区域为a[1..3,1..3],第二个区域为a[4..6,1..3]……最后一个区域为a[7..9,7..9])。同一区域内只能不重复的填入1到9。
 2.9*9的方阵中每一行都不能出现重复的数字且只能填1..9。
 3.9*9的方阵中每一列都不能出现重复的数字且只能填1..9。

这个没有专门的过程来做,只能自己写,对于数独来说,限制的条件越多越容易填(答案不一定唯一)。假如用程序来填写数独,可以采用搜索+分治,只要对条件(在指定区域内不出现相同的数字)进行控制判断,应该很容易把程序调出来。

我的思路是:写一个过程判断填入的数是否重复(类似于八皇后问题的判断方式),
用分治算法来对数独进行划分(当然也可以用搜索),对每个区域进行依次的填写,要注意对填入的数进行判断。写一个过程判断并找出可填的数,填写时临时开辟一个数组b[1..9]来装可以填入的数,不断的将数填入方阵中每个区域即可。
以上思路纯属个人见解,如有错误请自行修改。

板凳

这个我也想过,可是时间复杂度怎么保证?

3 楼

在竞赛中就要看你的剪枝能力了,我这只是思路,没有考虑到时间复杂度和空间复杂度。你可以先写出来然后再试着去剪枝。看看程序能否出结果。毕竟优化算法是在能解决问题的基础上实现的。

4 楼

以下程序是从酷叶总站oibh版里转来的,尚未进行调试,仅供参考!
原网址:http://www.kuye.cn/dispbbs.asp?boardID=36&ID=1293
program shudu;
uses crt;

const atgx:array[1..9]of byte=(2,4,6,8,10,12,14,16,18);
    atgy:array[1..9]of byte=(2,4,6,8,10,12,14,16,18);
    ch:array[1..4,1..11]of char=((#218,#196,#191,#179,#192 ,#190,#195,#180,
    #193,#194,#197),(#220,#220,#220,#219,#220,#220,#219,#219,#220,#220,#219),
    (#201,#205,#187,#186,#200,#188,#204,#185,#202,#203,#206),(' ',' ',' ',' ',
    ' ',' ', ' ',' ',' ',' ',' '));
var a:array[1..9,1..9]of 0..9;
  b,d,e,f:array[1..9,1..9]of boolean;
  i,j:integer;
PROCEDURE draws(k,color:byte);
VAR i,j:integer;
BEGIN
  window(31,3,50,21);
  textbackground(color);
  clrscr;
  textcolor(12);
  write(ch[k,1]);
  for j:=1 to 8 do
  write(ch[k,2],ch[k,10]);
  writeln(ch[k,2],ch[k,3]);
  for i:=1 to 8 do
    begin
    for j:=1 to 9 do
    write(ch[k,4],' ');
    writeln(ch[k,4]);
    write(ch[k,7]);
    for j:=1 to 8 do
      write(ch[k,2],ch[k,11]);
    writeln(ch[k,2],ch[k,8]);
    end;
    for i:=1 to 9 do write(ch[k,4], ' ');
    writeln(ch[k,4]);
    write(ch[k,5]);
    for i:=1 to 8 do
    write(ch[k,2],ch[k,9]);
    write(ch[k,2],ch[k,6]);
    textcolor(lightgray);gotoxy(wherex,wherey-1)
END;
PROCEDURE inputs;
  VAR
    b1,b2,am,is,are:byte;
    cha:char;
    flag:boolean;
  BEGIN
    window(20,1,60,2);textcolor(red);
    write('PRESS<ESC><ENTER><F1>(F1 to no input!)');
    flag:=false;
    repeat
    cha:=readkey;
    case cha of
      #27:halt;
      #13:flag:=true;
      #59:exit;
    end
    until flag;
    clrscr;
    flag:=false;
    gotoxy(20,2);
    writeln('Inputting...');
    write('       Press    <Backspace><Enter>');
    draws(1,10);
    gotoxy(atgx[1],atgy[1]);
    textcolor(red);
  repeat
  cha:=readkey;
  case cha of
  '1'..'9':BEGIN
  a[(wherex)div 2,(wherey)div 2]:=ord(cha)-ord('0');
  write(ord(cha)-ord('0'));
  gotoxy(wherex-1,wherey);
  b[(wherex)div 2,(wherey)div 2]:=true;
  END;
  #77:gotoxy(wherex+2,wherey);
  #75:gotoxy(wherex-2,wherey);
  #72:gotoxy(wherex,wherey-2);
  #80:gotoxy(wherex,wherey+2);
  #13:exit;
  #08:BEGIN b1:=wherex;b2:=wherey;
  a[(wherex)div 2,(wherey)div 2]:=0;write(' ');
  gotoxy(wherex-1,wherey);
  b[(b2)div 2,(b1)div 2]:=false;END;
  end
UNTIL flag;
end;
PROCEDURE clear;
VAR i,j:integer;
BEGIN
window(31,3,50,21);
for i:=1 to 9 do
FOR j:=1 to 9 DO
  IF not b[i,j] THEN BEGIN
  gotoxy(atgx,atgy[j]);write(' ');end;
END;
PROCEDURE print;
VAR i,j:integer;
BEGIN
window(31,3,50,21);
textcolor(14);
for i:=1 to 9 do
FOR j:=1 to 9 DO
BEGIN
  IF b[i,j]=false THEN BEGIN
    gotoxy(atgx,atgy[j]);
    write(a[i,j]);sound(200+a[i,j]*10);
    delay(50);nosound;delay(20);END;

end;readkey;clear;
END;
procedure andy(mm,nn:integer);
var i,t,p:integer;fl:boolean;
begin                       //1
if mm>9 then print
else if b[mm,nn]=false then
BEGIN                     //2
p:=random(9)+1;
For i:=p to 9 do
If (d[mm,i])then if(e[nn,i])then
  BEGIN                   //3
  t:=(mm-1)div 3+1+((nn-1) div 3)*3;
  IF f[t,i] then begin         //4
  d[mm,i]:=false;
  a[mm,nn]:=i;
  e[nn,i]:=false;
  f[t,i]:=false;
  iF nn=9
  then andy(mm+1,1)
  ELSE andy(mm,nn+1);
  f[t,i]:=true;
  d[mm,i]:=true;
  e[nn,i]:=true
  end;END;                   //4,3
For i:=p-1 downto 1 do
If (d[mm,i])then if(e[nn,i])then
  BEGIN
  t:=(mm-1)div 3+1+((nn-1) div 3)*3;
  IF f[t,i] then begin
  d[mm,i]:=false;
  a[mm,nn]:=i;
  e[nn,i]:=false;
  f[t,i]:=false;
  iF nn=9
  then andy(mm+1,1)
  ELSE andy(mm,nn+1);
  f[t,i]:=true;
  d[mm,i]:=true;
  e[nn,i]:=true end             //4
END;                       //3
END                       //2
else if nn=9 then andy(mm+1,1)
        else andy(mm,nn+1)
end;

BEGIN
textbackground(lightgreen);
clrscr;
for i:= 1 to 9 do
  for j:=1 to 9 do
  BEGIN
      b[i,j]:=false;d[i,j]:=true;
      e[i,j]:=true;f[i,j]:=true
  END;
inputs;
for i:=1 to 9 do
  for j:=1 to 9 do
  BEGIN
IF b[i,j] THEN BEGIN
  d[i,a[i,j]]:=false;e[j,a[i,j]]:=false;
  f[(i-1)div 3+1+((j-1) div 3)*3,a[i,j]]:=false END;
END;
inc(i);
andy(1,1);
window(0,0,26,80);
textbackground(lightgreen);
textcolor(yellow);
clrscr
END.

5 楼

关于4楼的程序。事实证明。应该是行的,在时间上快的难以置信。不过有必要深究一下。
还有 pascal好像没有//这个注释标记的吧
编译时在   gotoxy(atgx,atgy[j]); 一类地方出错。 请在atgx后加[i] 即可
再有一个,可以修改一下,让它多求几组解,不用老这种,这样更能让人信服

我来回复

您尚未登录,请登录后再回复。点此登录或注册