Skocz do zawartości

[Delphi] TSudoku - czyli zalążek modułu


Stelma

Polecane posty

Witam

 

Z racji iż jest to mój pierwszy post chciałem się przywitać :)

 

Chciałem spytać bardziej doświadczonych kolegów czy poniższy modulik można ulepszyć zachowując jego pierwotne założenia losowania. Nie chciał bym zmieniać mu rodzaju losowania z prostej przyczyny gwarantuje on wylosowanie mi planszy w czasie krótszym niż 4 sekundy.

 

Jednak jego ilość prób jest oszałamiająca ponieważ sięga u mnie czasami do 20 mln (Wliczając w to próby udane jak i nie). I oto właściwie chodzi chciałbym stworzyć coś bardziej zwięzłego.

 

 

unit TTSudoku;

{      ////////////////PAWEŁ STELMASIAK\\\\\\\\\\\\\\\\\\\\
     ///////////////////stedi2@o2.pl\\\\\\\\\\\\\\\\\\\\\\\
    /////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

Moduł jest wolno dostępny dla wszystkich którym może się przydać.

Plansza jest tworzona na zasadzie rzucania piłeczki na stół pokryty otworami i
 zaklejanie tych które już nie uczesniczą w grze. Plansza jest zwracana typu
 tradycyjnego sudoku.

Funkcja "Generator" zwraca wartość False w przypadku nie powodzenia losowania.
 Wystarczy tę funkcję wywołać w pętli Repeat..Until, While..do

Zwracana tablica "R" posiada wartości 0-8 w celu szybszego generowania. Tablica
 jest całkiem (w zakresie pozwolenia Random, Randomize) losowa. Dzięki czemu
 moduł może działać samodzielnie bez potrzeby dodawania dodatkowych plików

Testowany na :
 Procek : 1,6 Ghz  "1 rdzeń"
 Ram : 512 DDR + 4 GB rzucanie na dysk twardy
 Dysk : Samsung 40 GB 5400 obr/min
 System : Windows XP pro Service Pack 3
 Kompilator : Delphi 7 EN

Czas reakcji
 Średnio 2 sekundy. Zawsze udawało mu się wygenerować planszę poniżej 4 sekund
}

interface
uses
 Forms;          //Moduły delphi

type
TSudoku = class(TObject)
  function Generator(Sender : TSudoku): boolean;                   //funkcja służy do generowania planszy
 public
  R : array [1..9, 1..9] of byte;                                  //Deklaracja tablicy {R} Prawdziwa, {P} Pomocznicza
 private
  P : array [1..9, 1..9] of byte;                                  //Deklaracja tablicy {P} Pomocznicza
  procedure CreateEmptyTable(Sender : TSudoku);                    //Funkcja służy do wyczyszczenia tablicy {R}
  procedure CreateHelpTable(Sender : TSudoku);                     //Funkcja "układa" pomocniczą tablice {P}
  procedure ElminateHelpTable(var x, y : Byte; Sender : TSudoku);  //Funkcja w tablicy {P} zaznacza miejsca które są zajęte
end;

implementation

procedure TSudoku.CreateEmptyTable(Sender : TSudoku);
Var
 i, j :Integer;
begin
For i := 1 to 9 do For j := 1 to 9 do (Sender as TSudoku).R[i][j] := 0;
end;

procedure TSudoku.CreateHelpTable(Sender : TSudoku);
Var
 i, j :Integer;
begin
For i := 1 to 9 do
  For j := 1 to 9 do
     IF (Sender as TSudoku).R[i][j] = 0 then (Sender as TSudoku).P[i][j] := 0
       else (Sender as TSudoku).P[i][j] := 1;
end;

procedure TSudoku.ElminateHelpTable(var x, y : Byte; Sender : TSudoku);
var
 i, j : Integer;
begin
For i := 1 to 9 do begin
  (Sender as TSudoku).P[i][x] := 1;           //Zaznaczenie poziomów
  (Sender as TSudoku).P[y][i] := 1;           //Zaznaczenie pionów
end;

x := (x - 1) div 3 * 3 + 1;                   //Ustalanie kwadratu X

y := (y - 1) div 3 * 3 + 1;                   //Ustalanie kwadratu Y

For i := 0 to 2 do                            //Zaznaczanie kwadratu X / Y
  For j := 0 to 2 do
    (Sender as TSudoku).P[y + i][x + j] := 1;

end;

function TSudoku.Generator(Sender : TSudoku): boolean;
const Max = 2500;                                          //Ilosc prób rzutów do zakończenia funkcji fiaskiem  {2500} wydaje mi się optymalna
var
 i, j, min : Integer;
 x, y : Byte;
begin
result := False;
IF not (Sender is TSudoku) then exit;                       //Sprawdzanie czy klasa jest typu TSudoku

Randomize;
min := 0;
(Sender as TSudoku).CreateEmptyTable(Sender);              //Tworzenie pustej tabli

For i := 1 to 8 do begin
  (Sender as TSudoku).CreateHelpTable(Sender);             //Tworzenie tablicy pomocniczej

      Application.ProcessMessages;                         //Chwila oddechu dla procesora

  For j := 1 to 9 do begin
    Repeat
      y := Random(9) + 1;                                  //Losowanie poziomu
      x := Random(9) + 1;                                  //Losowanie pionu
      IF min = Max then exit                               //Sprawdzanie czy już przekroczono ilosc prób
        else Inc(min);                                     //Jeżeli nie przekroczono to dopisz
    Until (Sender as TSudoku).P[y][x] = 0;                 //Jeżeli na planszy nie ma cyfry to skończ szukac

    (Sender as TSudoku).R[y][x] := i;                      //Zapisanie cyfry
    (Sender as TSudoku).ElminateHelpTable(x, y, Sender);   //Wyeliminowanie miejsc w których liczba nie może wystąpic
  end;
end;

result := True;

end;




end.

 

Z góry dziękuję za pomoc jak i przepraszam za chaotycznie napisany temat jak i moduł ;p

Link do komentarza
Udostępnij na innych stronach

Zarchiwizowany

Ten temat jest archiwizowany i nie można dodawać nowych odpowiedzi.

×
×
  • Utwórz nowe...