Iks-Oks je stara igra kojoj ovo sigurno neće biti prvo interaktivno izdanje, ali je to dobar primjer programiranja u Delphiju.
Dakle, prvo se pobrinimo za izgled. Primjenimo sljedeće promjene osobina Form1:
Caption | Iks - Oks |
ClientHeight | 300 |
ClientWidth | 300 |
BorderIcons biMaximize |
False |
BorderStyle | bsSingle |
Position | poScreenCenter |
Iks-Oks sam izabrao iz mnogih razloga, ali glavni je
upotreba Canvas-a ( prim. prev. Platno ). Dakle, pomoću Canvas po Formu se
može
crtati, pisati, bojiti...
Pomoću Canvas-a, mi ćemo nacrtati polje za igru,
ispisivati znakove i križati pobjednika.
Dakle, na tabli Event Object Inspector-a, kliknimo dvaput na OnPaint. U proceduru upišimo sljedeće:
procedure TForm1.FormPaint(Sender: TObject);
begin
Canvas.Pen.Width := 1;
Canvas.Brush.Color := clBlack;
Canvas.MoveTo(100,0);
Canvas.LineTo(100,300);
Canvas.MoveTo(200,0);
Canvas.LineTo(200,300);
Canvas.MoveTo(0,100);
Canvas.LineTo(300,100);
Canvas.MoveTo(0,200);
Canvas.LineTo(300,200);
Ispis;
end;
Primjetimo: MoveTo pomjera fokus do tačke M(x,y), a
LineTo crta liniju od tačke M to tačke N(x1,y1). Brush.Color je boja kojom ce
Canvas crtati.
Toliko o izgledu.
Sad pređimo na pravo programiranje. Potez se igra tako što se klikne u kvadrat u koji želimo postaviti svoj znak ( igrač ce biti X, a računar O ). Polje treba posmatrati kao matricu, te kao privatnu definišemo matricu a:
a: Array[1..9]of Integer;
A uz nju i
k: Integer;
Gornje lijevo polje biće a[1] i tako dalje do donjeg desnog koje je a[9]. Kad igrač odigra u određeno polje, to polje dobija vrijednost 1, a kad odigra racunar -1. Poslije svakog poteza treba provjeriti da li je igra završena ( pobjeda, poraz ili nerješeno ). Zato kao privatnu definišemo funkciju Provjera. Kao što je rečeno u poglavlju Funkcije, funkcija vraća neku vrijednost, pa će ova funkcija vraćati vrijednost 1, 2 ... 11 ( 1 - ništa, 2 - poraz, 3 - nerješeno, 4..11 pobjeda na određenom mjestu ).
function Provjera: Integer;
A funkcija izgleda ovako:
function TForm1.Provjera: Integer;
var
b: Array[1..8]of Integer;
i, t: Integer;
begin
t := 3;
b[1] := a[1] +
a[2] + a[3];
b[2] := a[4] +
a[5] + a[6];
b[3] := a[7] +
a[8] + a[9];
b[4] := a[1] +
a[4] + a[7];
b[5] := a[2] +
a[5] + a[8];
b[6] := a[3] +
a[6] + a[9];
b[7] := a[1] +
a[5] + a[9];
b[8] := a[7] +
a[5] + a[3];
for i := 1 to 9
do
if a[i] = 0 then
t := 1;
for i := 1 to 8
do
begin
if b[i] = 3 then
t := 3 +
i;
if b[i] = -3 then
t := 2;
end;
Provjera := t;
end;
Nova matrica sadrži zbirove po tri polja na kojima
mora biti isti znak za pobjedu. Dakle, ako bar jedan zbir iznosi 3 ili -3
postoji pobjednik. Ako bar jedno polje nosi vrijednost 0, ono nije zauzeto, pa
nije nerješeno.
Da ne bi došlo do greške, potrebno je prije prvog
poteza svakom polju dodijeliti vrijednost 0. Dakle, dvoklik na Form ( ili na
tabli Events Object Inspector-a na OnCreate ):
procedure TForm1.FormCreate(Sender: TObject);
var
i: Integer;
begin
for i
:= 1 to 9
do
a[i] := 0;
end;
A kako to odigrati potez?
To će doći malo kasnije. Prvo definišimo privatne procedure Ispis i Potez. U private pišemo:
procedure Ispis(q, w, p: Integer);
procedure Potez;
a u reference:
procedure TForm1.Ispis;
var
s: String;
i ,x, y: Integer;
begin
Canvas.Brush.Color := clBtnFace;
Canvas.Font.Color := clBlack;
Canvas.Font.Size := 48;
Canvas.Font.Style := [fsBold];
for i := 1 to 9
do
begin
case a[i] of
0: s := '';
1: s := 'X';
2: s := 'O';
end;
x := 25 + ((i - 1) mod
3) * 100;
y := 15 + ((i - 1) div
3) * 100;
Canvas.TextOut(x, y, s);
end;
if Provjera = 2 then
begin
Form1.Caption := 'Iks - Oks
: Pobjeda O';
Canvas.Pen.Width := 5;
Canvas.Brush.Color := clBlack;
case k of
1: begin
Canvas.MoveTo(10, 50);
Canvas.LineTo(290, 50);
end;
2: begin
Canvas.MoveTo(10, 150);
Canvas.LineTo(290, 150);
end;
3: begin
Canvas.MoveTo(10, 250);
Canvas.LineTo(290, 250);
end;
4: begin
Canvas.MoveTo(50, 10);
Canvas.LineTo(50, 290);
end;
5: begin
Canvas.MoveTo(150, 10);
Canvas.LineTo(150, 290);
end;
6: begin
Canvas.MoveTo(250, 10);
Canvas.LineTo(250, 290);
end;
7: begin
Canvas.MoveTo(10, 10);
Canvas.LineTo(290, 290);
end;
8: begin
Canvas.MoveTo(10, 290);
Canvas.LineTo(290, 10);
end;
end;
end;
if Provjera = 3 then
Form1.Caption := 'Iks - Oks :
Nerjeseno';
if Provjera > 3
then
begin
Form1.Caption := 'Iks
- Oks : Pobjeda X';
Canvas.Pen.Width := 5;
Canvas.Brush.Color :=
clBlack;
case (Provjera - 3)
of
1:
begin
Canvas.MoveTo(10, 50);
Canvas.LineTo(290, 50);
end;
2:
begin
Canvas.MoveTo(10, 150);
Canvas.LineTo(290, 150);
end;
3:
begin
Canvas.MoveTo(10, 250);
Canvas.LineTo(290, 250);
end;
4:
begin
Canvas.MoveTo(50, 10);
Canvas.LineTo(50, 290);
end;
5:
begin
Canvas.MoveTo(150, 10);
Canvas.LineTo(150, 290);
end;
6:
begin
Canvas.MoveTo(250, 10);
Canvas.LineTo(250, 290);
end;
7:
begin
Canvas.MoveTo(10, 10);
Canvas.LineTo(290, 290);
end;
8:
begin
Canvas.MoveTo(10, 290);
Canvas.LineTo(290, 10);
end;
end;
end;
end;
Ovdje vidimo još neke Canvas funkcije. U proceduru FormPaint sada dodajemo:
Ispis;
Dakle, nikakva promjena na ekranu neće uticati na izgled polja.
Procedura Potez je, ustvari, potez računara. Prvo razvijamo strategiju. Računar prvo treba da provjeri da li ima negdje mogućnost za pobjedu i, ako ima, vuče taj potez. Ako nema, gleda da li igrač ima mogućnost za pobjedu i, ako ima, zatvara. Ako nema onda igra na prvo slobodno mjesto, gledajući s lijeva na desno.
procedure TForm1.Potez;
var
b: Array[1..8]of Integer;
i: Integer;
Odig, po: Boolean;
begin
Odig := False;
po := False;
k := 0;
b[1] := a[1] +
a[2] + a[3];
b[2] := a[4] +
a[5] + a[6];
b[3] := a[7] +
a[8] + a[9];
b[4] := a[1] +
a[4] + a[7];
b[5] := a[2] +
a[5] + a[8];
b[6] := a[3] +
a[6] + a[9];
b[7] := a[1] +
a[5] + a[9];
b[8] := a[3] +
a[5] + a[7];
for i := 1 to 8
do
begin
if b[i] = -2 then
begin
k := i;
po := True;
end;
if (b[i] = 2)
and not po then
k := i;
end;
case k of
1: begin
if a[1]
= 0 then
a[1]
:= -1;
if a[2]
= 0 then
a[2]
:= -1;
if a[3]
= 0 then
a[3]
:= -1;
Odig := True;
end;
2: begin
if a[4]
= 0 then
a[4]
:= -1;
if a[5]
= 0 then
a[5]
:= -1;
if a[6]
= 0 then
a[6]
:= -1;
Odig := True;
end;
3: begin
if a[7]
= 0 then
a[7]
:= -1;
if a[8]
= 0 then
a[8]
:= -1;
if a[9]
= 0 then
a[9]
:= -1;
Odig := True;
end;
4: begin
if a[1]
= 0 then
a[1]
:= -1;
if a[4]
= 0 then
a[4]
:= -1;
if a[7]
= 0 then
a[7]
:= -1;
Odig := True;
end;
5: begin
if a[2]
= 0 then
a[2]
:= -1;
if a[5]
= 0 then
a[5]
:= -1;
if a[8]
= 0 then
a[8]
:= -1;
Odig := True;
end;
6: begin
if a[3]
= 0 then
a[3]
:= -1;
if a[6]
= 0 then
a[6]
:= -1;
if a[9]
= 0 then
a[9]
:= -1;
Odig := True;
end;
7: begin
if a[1]
= 0 then
a[1]
:= -1;
if a[5]
= 0 then
a[5]
:= -1;
if a[9]
= 0 then
a[9]
:= -1;
Odig := True;
end;
8: begin
if a[3]
= 0 then
a[3]
:= -1;
if a[5]
= 0 then
a[5]
:= -1;
if a[7]
= 0 then
a[7]
:= -1;
Odig := True;
end;
end;
if not Odig then
begin
for i := 9 downto
1 do
if a[i] = 0
then
k := i;
a[k] := -1;
end;
Ispis;
end;
Sad napokon dolazimo do definisanja igračevog poteza. Na Events tabli Object Inspector-a kliknimo dvaput na OnMouseDown.
procedure
TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
m: Integer;
Odig: Boolean;
begin
if (Button = mbLeft) and (Provjera = 1)
then
begin
Odig := False;
m := X div 100
+ 3 * (Y div 100) +
1;
if a[m] = 0 then
begin
a[m] := 1;
Odig := True;
end;
Ispis;
if (Provjera = 1)
and Odig then
Potez;
end;
end;
Sad da izvedemo završne radove. Dodajmo TPopupMenu na Form1 i osobinu Form1 - PopupMenu promjenimo na PopupMenu1. U PopupMenu1 stavimo 'Nova igra' i 'Izlaz'. Za 'Izlaz' u Events tabli Object Inspector-a, opcija OnClick, kreiramo proceduru:
procedure TForm1.Izlaz1Click(Sender: TObject);
begin
Close;
end;
Isto uradimo za 'Nova igra':
procedure
TForm1.Novaigra1Click(Sender: TObject);
var
i: Integer;
begin
for i := 1 to 9
do
a[i] := 0;
i := 0;
if Form1.Caption[Length(Form1.Caption)] = 'O'
then
i := 1;
Form1.Caption := 'Iks - Oks';
Form1.Color := clGreen;
Form1.Color := clBtnFace;
FormPaint(Sender);
if i = 0 then
Potez;
end;
To bi bilo to. A ovako bi to trebalo da izgleda u radu: