Pascal - Gra w kółko i krzyżyk

Hej wszystkim,

jako zadanie świąteczne ze Wstępu do Informatyki (jestem po jednym semestrze nauki programowania od podstaw) miałem napisać we Free Pascalu program, który w miarę skutecznie gra w kółko i krzyżyk. Czytałem o algorytmie minimax i chętnie bym go zastosował, ale niestety nie mam pojęcia, jak stworzyć potrzebne do tego drzewo decyzyjne.

Dlatego napisałem sam alternatywną (i pewnie w jakimś sensie ułomną) wersję programu. W moim założeniu program powinien oceniać wolne (na dany moment) pola pod względem wartości obronnej (tzn. co straci rywal, jak my postawimy tam nasz znaczek). Jeśli najwyżej punktowane pola mają tę samą wartość, to dopiero wtedy są porównywane pod względem wartości ofensywnej.

Program poprawnie się kompiluje, ale po wykonaniu dwóch ruchów coś się wiesza.

Dla wyjaśnienia:

  • komputer gra kółkami, człowiek krzyżykami,

  • funkcja koniec sprawdza, czy wszystkie pola są niepuste

  • funkcje skos/poziom/pion zwracają, czy na tych płaszczyznach wygrał komputer, człowiek, czy był remis

  • procedura losuj losuje, kto zaczyna rozgrywkę

  • procedura rysuj rysuje :slight_smile:

  • funkcja atak przypisuje konkretnym polom punkty za atak, a funkcja ocena za obronę (jak jest remis, to wtedy sprawdza, które pole ma ‘lepszy atak’)

  • założeniem procedury ruch jest to, że pierwszy posunięcie wykonuje człowiek.

Pełny kod:

program kolkokrzyzyk;

uses crt;

{$R-}

var A:array[1..3,1..3] of char; {tabela którą będziemy rysować}

B:array[1..9] of char; {tabela na której będzie operował program}

kolejka:boolean; {gdy kolejka to ruch komputera}

i,t,u,e,f,y,h:integer;

k,c,r:char;



function koniec(B:array of char):boolean;

begin

koniec:=false;

if (B[1]<>' ') and (B[2]<>' ') and (B[3]<>' ') and (B[4]<>' ') and (B[5]<>' ') and (B[6]<>' ') and (B[7]<>' ') and (B[8]<>' ') and (B[9]<>' ') then

koniec:=true;

end;


function max(a,b:integer):integer;

begin

if a>b then max:=a

else max:=b;

end;


function skos:char; {k - wygrał komputer, c- człowiek, r - nikt}

begin

skos:=r;

if (B[1]='X') and (B[5]='X') and (B[9]='X') then skos:=c;

if (B[3]='X') and (B[5]='X') and (B[7]='X') then skos:=c;

if (B[1]='O') and (B[5]='O') and (B[9]='O') then skos:=k;

if (B[3]='O') and (B[5]='O') and (B[7]='O') then skos:=k;

end;


function pion:char;

begin

pion:=r;

if (B[1]='X') and (B[4]='X') and (B[7]='X') then pion:=c;

if (B[2]='X') and (B[5]='X') and (B[8]='X') then pion:=c;

if (B[3]='X') and (B[6]='X') and (B[9]='X') then pion:=c;

if (B[1]='O') and (B[4]='O') and (B[7]='O') then pion:=k;

if (B[2]='O') and (B[5]='O') and (B[8]='O') then pion:=k;

if (B[3]='O') and (B[6]='O') and (B[9]='O') then pion:=k;

end;


function poziom:char;

begin

poziom:=r;

if (B[1]='X') and (B[2]='X') and (B[3]='X') then poziom:=c;

if (B[4]='X') and (B[5]='X') and (B[6]='X') then poziom:=c;

if (B[7]='X') and (B[8]='X') and (B[9]='X') then poziom:=c;

if (B[1]='O') and (B[2]='O') and (B[3]='O') then poziom:=k;

if (B[4]='O') and (B[5]='O') and (B[6]='O') then poziom:=k;

if (B[7]='O') and (B[8]='O') and (B[9]='O') then poziom:=k;

end;


procedure losuj;

begin

kolejka:=false;

randomize;

if random(2)=1 then kolejka:=true;

end;



procedure czysctabele;

var m,n,o:integer;

begin

for m:=1 to 3 do

for n:=1 to 3 do

A[m,n]:=' ';

for o:=1 to 9 do

B[o]:=' ';

end;


procedure rysuj;

var m,n,o:integer;

begin

o:=1;

for m:=1 to 3 do

for n:=1 to 3 do

begin

A[m,n]:=B[o];

o:=o+1;

end;

clrscr;

writeln;

writeln;

writeln(' Kolko i krzyzyk');

writeln(' (Ty jestes krzyzykiem)');

writeln;

writeln;

writeln(' ',A[1,1],'I',A[1,2],'I',A[1,3]);

writeln('-------');

writeln(' ',A[2,1],'I',A[2,2],'I',A[2,3]);

writeln('-------');

writeln(' ',A[3,1],'I',A[3,2],'I',A[3,3]);

readln;

end;


function atak(a:integer):integer;

var ofens:array[1..9] of integer;

begin

for t:=1 to 9 do ofens[t]:=1;

t:=1;

if (B[1]=' ') then begin

if (B[2]='O') then ofens[1]:=ofens[1]*3;

if (B[3]='O') then ofens[1]:=ofens[1]*3;

if (B[4]='O') then ofens[1]:=ofens[1]+3;

if (B[7]='O') then ofens[1]:=ofens[1]+3;

if (B[4]='O') and (B[7]='O') then ofens[1]:=ofens[1]+10;

if (B[5]='O') then ofens[1]:=ofens[1]+3;

if (B[9]='O') then ofens[1]:=ofens[1]+3;

if (B[5]='O') and (B[9]='O') then ofens[1]:=ofens[1]+10;

end

else ofens[1]:=0;

if (B[2]=' ') then begin

if (B[1]='O') then ofens[2]:=ofens[2]*3;

if (B[3]='O') then ofens[2]:=ofens[2]*3;

if (B[5]='O') then ofens[2]:=ofens[2]+3;

if (B[5]='O') then ofens[2]:=ofens[2]+3;

if (B[5]='O') and (B[8]='O') then ofens[2]:=ofens[2]+10;

end

else ofens[2]:=0;

if (B[3]=' ') then begin

if (B[2]='O') then ofens[3]:=ofens[3]*3;

if (B[1]='O') then ofens[3]:=ofens[3]*3;

if (B[6]='O') then ofens[3]:=ofens[3]+3;

if (B[9]='O') then ofens[3]:=ofens[3]+3;

if (B[6]='O') and (B[9]='O') then ofens[3]:=ofens[3]+10;

if (B[5]='O') then ofens[3]:=ofens[3]+3;

if (B[7]='O') then ofens[3]:=ofens[3]+3;

if (B[5]='O') and (B[7]='O') then ofens[3]:=ofens[3]+10;

end

else ofens[3]:=0;

if (B[4]=' ') then begin

if (B[5]='O') then ofens[4]:=ofens[4]*3;

if (B[6]='O') then ofens[4]:=ofens[4]*3;

if (B[1]='O') then ofens[4]:=ofens[4]+3;

if (B[7]='O') then ofens[4]:=ofens[4]+3;

if (B[1]='O') and (B[7]='O') then ofens[4]:=ofens[4]+10;

end

else ofens[4]:=0;

if (B[5]=' ') then begin

if (B[4]='O') then ofens[5]:=ofens[5]*3;

if (B[6]='O') then ofens[5]:=ofens[5]*3;

if (B[2]='O') then ofens[5]:=ofens[5]+3;

if (B[8]='O') then ofens[5]:=ofens[5]+3;

if (B[2]='O') and (B[8]='O') then ofens[5]:=ofens[5]+10;

if (B[1]='O') then ofens[5]:=ofens[5]+3;

if (B[9]='O') then ofens[5]:=ofens[5]+3;

if (B[1]='O') and (B[9]='O') then ofens[5]:=ofens[5]+10;

if (B[3]='O') then ofens[5]:=ofens[5]+3;

if (B[7]='O') then ofens[5]:=ofens[5]+3;

if (B[3]='O') and (B[7]='O') then ofens[5]:=ofens[5]+10;

end

else ofens[5]:=0;

if (B[6]=' ') then begin

if (B[5]='O') then ofens[6]:=ofens[6]*3;

if (B[4]='O') then ofens[6]:=ofens[6]*3;

if (B[3]='O') then ofens[6]:=ofens[6]+3;

if (B[9]='O') then ofens[6]:=ofens[6]+3;

if (B[3]='O') and (B[9]='O') then ofens[6]:=ofens[6]+10;

end

else ofens[6]:=0;

if (B[7]=' ') then begin

if (B[8]='O') then ofens[7]:=ofens[7]*3;

if (B[9]='O') then ofens[7]:=ofens[7]*3;

if (B[1]='O') then ofens[7]:=ofens[7]+3;

if (B[4]='O') then ofens[7]:=ofens[7]+3;

if (B[1]='O') and (B[4]='O') then ofens[7]:=ofens[7]+10;

if (B[5]='O') then ofens[7]:=ofens[7]+3;

if (B[3]='O') then ofens[7]:=ofens[7]+3;

if (B[5]='O') and (B[3]='O') then ofens[7]:=ofens[7]+10;

end

else ofens[7]:=0;

if (B[8]=' ') then begin

if (B[7]='O') then ofens[8]:=ofens[8]*3;

if (B[9]='O') then ofens[8]:=ofens[8]*3;

if (B[5]='O') then ofens[8]:=ofens[8]+3;

if (B[2]='O') then ofens[8]:=ofens[8]+3;

if (B[2]='O') and (B[5]='O') then ofens[8]:=ofens[8]+10;

end

else ofens[8]:=0;

if (B[9]=' ') then begin

if (B[8]='O') then ofens[9]:=ofens[9]*3;

if (B[7]='O') then ofens[9]:=ofens[9]*3;

if (B[3]='O') then ofens[9]:=ofens[9]+3;

if (B[6]='O') then ofens[9]:=ofens[9]+3;

if (B[3]='O') and (B[6]='O') then ofens[9]:=ofens[9]+10;

if (B[5]='O') then ofens[9]:=ofens[9]+3;

if (B[1]='O') then ofens[9]:=ofens[9]+3;

if (B[5]='O') and (B[1]='O') then ofens[9]:=ofens[9]+10;

end

else ofens[9]:=0;

for t:=1 to 9 do

atak:=ofens[t];

end;


function ocena(B:array of char):integer;

var obrona:array[1..9] of integer;

begin

for e:=1 to 9 do obrona[e]:=1;

e:=1;

if (B[1]=' ') then begin

if (B[2]='X') then obrona[1]:=obrona[1]*3;

if (B[3]='X') then obrona[1]:=obrona[1]*3;

if (B[4]='X') then obrona[1]:=obrona[1]+3;

if (B[7]='X') then obrona[1]:=obrona[1]+3;

if (B[4]='X') and (B[7]='X') then obrona[1]:=obrona[1]+15;

if (B[5]='X') then obrona[1]:=obrona[1]+3;

if (B[9]='X') then obrona[1]:=obrona[1]+3;

if (B[5]='X') and (B[9]='X') then obrona[1]:=obrona[1]+15;

end

else obrona[1]:=0;

if (B[2]=' ') then begin

if (B[1]='X') then obrona[2]:=obrona[2]*3;

if (B[3]='X') then obrona[2]:=obrona[2]*3;

if (B[5]='X') then obrona[2]:=obrona[2]+3;

if (B[5]='X') then obrona[2]:=obrona[2]+3;

if (B[5]='X') and (B[8]='X') then obrona[2]:=obrona[2]+15;

end

else obrona[2]:=0;

if (B[3]=' ') then begin

if (B[2]='X') then obrona[3]:=obrona[3]*3;

if (B[1]='X') then obrona[3]:=obrona[3]*3;

if (B[6]='X') then obrona[3]:=obrona[3]+3;

if (B[9]='X') then obrona[3]:=obrona[3]+3;

if (B[6]='X') and (B[9]='X') then obrona[3]:=obrona[3]+15;

if (B[5]='X') then obrona[3]:=obrona[3]+3;

if (B[7]='X') then obrona[3]:=obrona[3]+3;

if (B[5]='X') and (B[7]='X') then obrona[3]:=obrona[3]+15;

end

else obrona[3]:=0;

if (B[4]=' ') then begin

if (B[5]='X') then obrona[4]:=obrona[4]*3;

if (B[6]='X') then obrona[4]:=obrona[4]*3;

if (B[1]='X') then obrona[4]:=obrona[4]+3;

if (B[7]='X') then obrona[4]:=obrona[4]+3;

if (B[1]='X') and (B[7]='X') then obrona[4]:=obrona[4]+15;

end

else obrona[4]:=0;

if (B[5]=' ') then begin

if (B[4]='X') then obrona[5]:=obrona[5]*3;

if (B[6]='X') then obrona[5]:=obrona[5]*3;

if (B[2]='X') then obrona[5]:=obrona[5]+3;

if (B[8]='X') then obrona[5]:=obrona[5]+3;

if (B[2]='X') and (B[8]='X') then obrona[5]:=obrona[5]+15;

if (B[1]='X') then obrona[5]:=obrona[5]+3;

if (B[9]='X') then obrona[5]:=obrona[5]+3;

if (B[1]='X') and (B[9]='X') then obrona[5]:=obrona[5]+15;

if (B[3]='X') then obrona[5]:=obrona[5]+3;

if (B[7]='X') then obrona[5]:=obrona[5]+3;

if (B[3]='X') and (B[7]='X') then obrona[5]:=obrona[5]+15;

end

else obrona[5]:=0;

if (B[6]=' ') then begin

if (B[5]='X') then obrona[6]:=obrona[6]*3;

if (B[4]='X') then obrona[6]:=obrona[6]*3;

if (B[3]='X') then obrona[6]:=obrona[6]+3;

if (B[9]='X') then obrona[6]:=obrona[6]+3;

if (B[3]='X') and (B[9]='X') then obrona[6]:=obrona[6]+15;

end

else obrona[6]:=0;

if (B[7]=' ') then begin

if (B[8]='X') then obrona[7]:=obrona[7]*3;

if (B[9]='X') then obrona[7]:=obrona[7]*3;

if (B[1]='X') then obrona[7]:=obrona[7]+3;

if (B[4]='X') then obrona[7]:=obrona[7]+3;

if (B[1]='X') and (B[4]='X') then obrona[7]:=obrona[7]+15;

if (B[5]='X') then obrona[7]:=obrona[7]+3;

if (B[3]='X') then obrona[7]:=obrona[7]+3;

if (B[5]='X') and (B[3]='X') then obrona[7]:=obrona[7]+15;

end

else obrona[7]:=0;

if (B[8]=' ') then begin

if (B[7]='X') then obrona[8]:=obrona[8]*3;

if (B[9]='X') then obrona[8]:=obrona[8]*3;

if (B[5]='X') then obrona[8]:=obrona[8]+3;

if (B[2]='X') then obrona[8]:=obrona[8]+3;

if (B[2]='X') and (B[5]='X') then obrona[8]:=obrona[8]+15;

end

else obrona[8]:=0;

if (B[9]=' ') then begin

if (B[8]='X') then obrona[9]:=obrona[9]*3;

if (B[7]='X') then obrona[9]:=obrona[9]*3;

if (B[3]='X') then obrona[9]:=obrona[9]+3;

if (B[6]='X') then obrona[9]:=obrona[9]+3;

if (B[3]='X') and (B[6]='X') then obrona[9]:=obrona[9]+15;

if (B[5]='X') then obrona[9]:=obrona[9]+3;

if (B[1]='X') then obrona[9]:=obrona[9]+3;

if (B[5]='X') and (B[1]='X') then obrona[9]:=obrona[9]+15;

end

else obrona[9]:=0;

ocena:=obrona[1];

for f:=2 to 9 do

ocena:=max(obrona[f],ocena);

for f:=1 to 9 do

if ocena=obrona[f] then ocena:=f;

y:=f;

for f:=1 to 9 do

if (ocena=obrona[f]) and (f<>y) then

begin

if atak(f)>atak(y) then ocena:=f

else ocena:=y;

end;

end;



procedure ruch; {zakładamy, że zaczyna człowiek}

var r,n:integer;

begin

writeln('Które pole wybierasz (od 1 do 9)?');

read(i);

B[i]:='X';

B[ocena(B)]:='O';

end;





begin

czysctabele;

losuj;

if kolejka then

        begin

        writeln('Zaczynam!');

        B[1]:='O';

        rysuj;

        end

else

        begin

        writeln('Zaczynasz!');

        ruch;

        rysuj;

        end;

while not koniec(B) do begin

        ruch;

        rysuj;

        end;

if koniec(B) then begin

        if (skos=r) and (pion=r) and (poziom=r) then writeln('Remis.');

        if (skos=c) or(pion=c) or (poziom=c) then writeln('Wygrales... :(')

        else writeln('Wygralem! :)');

        readln;

        end;

end.

Będę wdzięczny za wszelakie wskazówki.

Czy ty słyszałeś może coś o pętlach?

for, while, repeat?

W niektórych miejscach używasz, ale nie wszędzie tam gdzie jest to wskazane.

Np funkcje koniec, skos, pion, poziom warto zrobić za pomocą pętli.

Nie rozumiem czemu nie używasz żadnego formatowania kodu?

Nie rozumiem też czemu komputer ma operować na innej tabeli?

Owszem, słyszałem o pętlach for i while, ale repeat nie, może się gdzieś tu przydać?

Komputer pracuje na tabeli B[1…9] tylko i wyłącznie dla ułatwienia zapisu.

A formatowanie kodu to niestety rzecz, jaką słyszę pierwszy raz.