Kółko i krzyżyk - tłumaczenie dla nooba ...

0

Witam !

Niedawno zainteresowałem się delphi i znajomy mi "podpowiedział" że dobrze jest zacząć od klasycznej gry "kółko i krzyżyk". Znalazłem więc w internecie 'gotowca' ale nie bardzo rozumiem jak on działa (tzn sam algorytm myślący).

Czy ktoś mógłby wytłumaczyć na czym ta rzecz polega ?

Wstawiam tutaj kod całej gry ... wiem ze dla fachowcow to jedno spojrzenie pewnie, ale ja sie glowie od dwoch dni :P

var
  Form1: TForm1;
  p:array[1..9]of TPanel; {tworzy kratki do gry}
  k,los:byte;
implementation

uses Unit2;

{$R *.DFM}

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  for k:=1 to 9 do
    p[k].free  {czyści kratki po grze}
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  randomize;
  for k:=1 to 9 do
  begin
    p[k]:=TPanel.Create(form1);
    p[k].parent:=form1;
    p[k].left:=100+55*((k-1) mod 3);
    p[k].top:=200+55*((k-1) div 3);
    p[k].width:=50;
    p[k].height:=50;
    p[k].color:=clwhite;
    p[k].OnClick:=Click;
    p[k].font.size:=12;
    p[k].font.name:='Comic Sans MS';
    p[k].enabled:=false;
  end
end;

procedure TForm1.Click(sender: TObject);
begin
  If ((sender is TPanel)and((sender as TPanel).caption=''))and(not koniec) then {!!!!!!!}
  begin
    If x.checked then
      with (sender as TPanel) do
      begin
        caption:='x';
        font.color:=clnavy
      end
    else
      with (sender as TPanel) do
      begin
        caption:='o';
        font.color:=clmaroon
      end;
    if (not remis)and(not koniec) then
    case wybor.ItemIndex of
      0:komp1;
      1:komp2;
    end
  end
end;

procedure TForm1.startClick(Sender: TObject);
begin
  if start.caption='Rozpocznij grę' then
    if not wybor.ItemIndex in [0,1] then showmessage('Wybierz poziom trudności!')
    else if (x.checked=false)and(o.checked=false) then showmessage('Wybierz kółko albo krzyżyk!')
         else
           begin
             los:=random(2)+1;
             case los of
               1:label1.caption:='zaczyna gracz!';
               2:label1.caption:='zaczyna komputer!';
             end;
             x.enabled:=false;
             o.enabled:=false;
             wybor.enabled:=false;
             start.enabled:=false;
             for k:=1 to 9 do
               p[k].enabled:=true;
             if los=2 then poczatek
           end
  else
    begin
      button1.visible:=false;
      x.enabled:=true;
      o.enabled:=true;
      wybor.enabled:=true;
      start.enabled:=true;
      start.caption:='Rozpocznij grę';
      panel.caption:='kólko i krzyzyk';
      label1.caption:='';
      for k:=1 to 9 do
      begin
        p[k].caption:='';
        p[k].enabled:=false;
        p[k].color:=clwhite
      end
    end
end;

procedure TForm1.poczatek;
var j,i:byte;
begin
  j:=random(4);
  case j of
    0:i:=1;
    1:i:=3;
    2:i:=7;
    3:i:=9
  end;
  wstaw(i)
end;

procedure TForm1.Komp1;
var i:byte;
begin
  repeat
    i:=random(9)+1
  until p[i].caption='';
  wstaw(i);
  koniec;
  remis
end;

procedure TForm1.Komp2;
var z:string;
    a:byte;
begin
  a:=0;
  if x.checked then z:='o' else z:='x';
  if por2(1,5,9,z)<>0 then a:=por2(1,5,9,z) else
  if por2(3,5,7,z)<>0 then a:=por2(3,5,7,z) else
  if por2(1,2,3,z)<>0 then a:=por2(1,2,3,z) else
  if por2(4,5,6,z)<>0 then a:=por2(4,5,6,z) else
  if por2(7,8,9,z)<>0 then a:=por2(7,8,9,z) else
  if por2(1,4,7,z)<>0 then a:=por2(1,4,7,z) else
  if por2(2,5,8,z)<>0 then a:=por2(2,5,8,z) else
  if por2(3,6,9,z)<>0 then a:=por2(3,6,9,z) else
  begin
    if z='o' then z:='x' else z:='o';
    if por2(1,5,9,z)<>0 then a:=por2(1,5,9,z) else
    if por2(3,5,7,z)<>0 then a:=por2(3,5,7,z) else
    if por2(1,2,3,z)<>0 then a:=por2(1,2,3,z) else
    if por2(4,5,6,z)<>0 then a:=por2(4,5,6,z) else
    if por2(7,8,9,z)<>0 then a:=por2(7,8,9,z) else
    if por2(1,4,7,z)<>0 then a:=por2(1,4,7,z) else
    if por2(2,5,8,z)<>0 then a:=por2(2,5,8,z) else
    if por2(3,6,9,z)<>0 then a:=por2(3,6,9,z) else
    begin
      if z='o' then z:='x' else z:='o';
      if por1(1,5,9,z)<>0 then a:=por1(1,5,9,z) else
      if por1(3,5,7,z)<>0 then a:=por1(3,5,7,z) else
      if por1(1,2,3,z)<>0 then a:=por1(1,2,3,z) else
      if por1(4,5,6,z)<>0 then a:=por1(4,5,6,z) else
      if por1(7,8,9,z)<>0 then a:=por1(7,8,9,z) else
      if por1(1,4,7,z)<>0 then a:=por1(1,4,7,z) else
      if por1(2,5,8,z)<>0 then a:=por1(2,5,8,z) else
      if por1(3,6,9,z)<>0 then a:=por1(3,6,9,z) else
      begin
        if z='o' then z:='x' else z:='o';
        if por1(1,5,9,z)<>0 then a:=por1(1,5,9,z) else
        if por1(3,5,7,z)<>0 then a:=por1(3,5,7,z) else
        if por1(1,2,3,z)<>0 then a:=por1(1,2,3,z) else
        if por1(4,5,6,z)<>0 then a:=por1(4,5,6,z) else
        if por1(7,8,9,z)<>0 then a:=por1(7,8,9,z) else
        if por1(1,4,7,z)<>0 then a:=por1(1,4,7,z) else
        if por1(2,5,8,z)<>0 then a:=por1(2,5,8,z) else
        if por1(3,6,9,z)<>0 then a:=por1(3,6,9,z)
      end
    end
  end;
  if a<>0 then
  begin
    wstaw(a);
    koniec;
    remis
  end else komp1;
end;

procedure TForm1.wstaw(a:byte);
begin
  if x.checked then
  begin
    p[a].caption:='o';
    p[a].font.color:=clmaroon
  end else
      begin
        p[a].caption:='x';
        p[a].font.color:=clnavy
      end
end;

function TForm1.por1(a1,a2,a3: byte; s:string):byte;
begin
  if (p[a1].caption=p[a2].caption)and(p[a3].caption=s)and(p[a1].caption='')
    then por1:=a1
  else if (p[a3].caption=p[a2].caption)and(p[a1].caption=s)and(p[a3].caption='')
         then por1:=a3
       else if (p[a1].caption=p[a3].caption)and(p[a2].caption=s)and(p[a1].caption='')
              then por1:=a1
                else por1:=0
end;

function TForm1.por2(a1,a2,a3: byte; s:string):byte;
begin
  if (p[a1].caption=p[a2].caption)and(p[a3].caption='')and(p[a1].caption=s)
    then por2:=a3
  else if (p[a3].caption=p[a2].caption)and(p[a1].caption='')and(p[a3].caption=s)
         then por2:=a1
       else if (p[a1].caption=p[a3].caption)and(p[a2].caption='')and(p[a1].caption=s)
              then por2:=a2
            else por2:=0
end;

function TForm1.por3(a1,a2,a3: byte):string;
begin
  if (p[a1].caption<>'')and
    ((p[a1].caption=p[a2].caption)and(p[a2].caption=p[a3].caption))then
  begin
    p[a1].color:=clFuchsia;
    p[a2].color:=clFuchsia;
    p[a3].color:=clFuchsia;
    por3:=p[a1].caption
  end else por3:=''
end;

function TForm1.koniec:boolean;
var s:string;
    kon:boolean;
begin
  s:=por3(1,2,3);
  s:=s+por3(4,5,6);
  s:=s+por3(7,8,9);
  s:=s+por3(1,4,7);
  s:=s+por3(2,5,8);
  s:=s+por3(3,6,9);
  s:=s+por3(1,5,9);
  s:=s+por3(3,5,7);
  if s<>'' then
  begin
    kon:=true;
    if ((o.checked)and(s[1]='o'))or((x.checked)and(s[1]='x'))then
      Panel.caption:='Welll dan!'
    else Panel.caption:='Komputer okazal się mondrzejszy';
    start.enabled:=true;
    start.caption:='Jeszcze raz?';
    button1.visible:=true;
  end else kon:=false;
  koniec:=kon
end;

function TForm1.remis:boolean;
begin
if not koniec then
  if (p[1].caption<>'')and(p[2].caption<>'')and(p[3].caption<>'')and
     (p[4].caption<>'')and(p[5].caption<>'')and(p[6].caption<>'')and
     (p[7].caption<>'')and(p[8].caption<>'')and(p[9].caption<>'')then
    begin
      remis:=true;
      Panel.caption:='remis';
      start.enabled:=true;
      start.caption:='Jeszcze raz?';
      button1.visible:=true;
    end
  else remis:=false
end;


procedure TForm1.Button1Click(Sender: TObject);
var pytanie:word;
begin
  pytanie:= MessageDlg('Czy napewno chcesz skończyć grę? ',mtConfirmation,[mbYes,mbNo,mbCancel],0);
  case pytanie of
    mrYes:close;
    mrNo:button1.visible:=false
  end;
end;


procedure TForm1.Button2Click(Sender: TObject);
    var F: TextFile;
begin
  form1.Visible:=false;
  form2.visible:=true;

   AssignFile(F, 'instrukcja');
  Rewrite(F);
  Writeln(F, 'Just created file with this text in it...');
  CloseFile(F);

end;
procedure TForm1.Button3Click(Sender: TObject);
begin
Close
end;

end.
0

poczytaj najlepiej jakieś kursy z przykładami :P ja od tego zaczynałem
prosty edytor tekstu itp. ;P na gry przyjdzie czasu ;)

0

ale on napisał że nie rozumie tylko algorytmu "myślącego", a więc że mi się nudzi to tak:

każde pole ma swój indeks, plansza wygląda więc tak:

1 2 3
4 5 6
7 8 9

analizę najlepiej zacząć od d**y strony czyli zobaczyć co robią funkcję, a więc:
funkcja por1 przyjmuje trzy indeksy pól i oznaczenie pola do którego ma przyrównywać a zwraca indeks jednego z dwóch pól pustych z tych o podanych indeksach o ile w trzecim z podanych pól jest znak który podano w parametrze
jeśli nie dojdzie do sytuacji dwóch pól pustych i jednego zapełnionego przez podany znak to zwraca 0, np dla tablicy:

x o o
o x
o

i dla danych: 1, 5, 9, 'x' zwróci 0 bo znak "x" znajduje się zarówno na polu 1 jak i 5 (na dwóch polach a nie na jednym)
zaś dla danych: 3, 6, 9, 'o' zwróci 6 lub 9 (bo te są puste), ale według implementacji akurat wychodzi że zwróci to pole które jest pierwsze lub trzecie więc zwróci 9

funkcja por2 także przyjmuje trzy indeksy pól i oznaczenie a zwraca indeks pola pustego (jednego z trzech podanych) o ile pozostałe dwa są zapełnione przez podany znak (np "x"), jeżeli nie doszło do takiej sytuacji (np dwa pola z podanych są puste albo jedno jest zapełnione przez inny znak np "o") to zwraca 0
np dla tablicy powyższej i dla danych: 1, 5, 9, 'x' zwróci 9 bo to pole jest puste a pozostałe dwa zapełnione przez "x", zaś dla danych: 4, 5, 6 zwróci 0 bo w jednym z tych pól jest "o"

dalej to już po prostu zwykły (choć prosty) algorytm którego rozumienie nie zależy od rozumienia języka (może go rozumieć ktoś kto nie zna języka i może go śmiało nie rozumieć ten kto język zna):

najpierw sprawdzane jest czy w której z linii (poziomych, pionowych lub ukośnych) jest sytuacja uszczęśliwiająca funkcję por2 (czyli jedno pole puste a pozostałe zapełnione przez znak komputera), jeśli tak to właśnie w to miejsce komputer postawi swój znaczek (a := por2(a, b, c, z)) co jest akurat zrozumiałe - stawia trzeci znak żeby wygrać grę

jeśli natomiast taka sytuacja się nie pojawi to sprawdza czy jest sytuacja "kryzysowa" - czyli czy gdzieś nie ma takiej samej sytuacji ale dla znaku przeciwnika (gracza) - jeśli tak to stawia tam swój znak żeby zablokować wygranę gracza

gdy nie ma takiej linii to komputer sprawdza linie dla swojego znaku i stawia punkcik w tej linii w której jest już jego znak a nie ma jeszcze znaczku gracza

gdy nie zaszła żadna z powyższych sytuacji to komputer stawia znaczek w tej linii, w której gracz już postawił swój znak a pozostałe dwa pola są puste (sprawdzanie funkcją por1 dla znaku gracza)

gdy żadna z sytuacji nie zaszła:

if a<>0 then begin
//
end else komp1; // <--

to komputer wstawia znaczek w losowe miejsce na planszy (to dzieje się już w funkcji komp1 która robi tylko to co powyżej). Komputer cały czas korzysta tylko z funkcji komp1 jeśli wybrano łatwy poziom trudności (czyli nic nie "myśli" tylko wstawia gdzie popadnie)

1 użytkowników online, w tym zalogowanych: 0, gości: 1