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
-
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.