home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1999 January
/
Chip_1999-01_cd.bin
/
zkuste
/
delphi
/
D1
/
DRBOBC.ZIP
/
TTT.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1996-02-20
|
10KB
|
300 lines
unit TTT;
{
File: TTT.PAS
Author: Bob Swart [100434,2072]
Purpose: Tic-tac-toe game component
Usage: Install on component palette. Make sure MAGIC.DLL is available
in the WINDOWS\SYSTEM directory or the directory with the final
application itself. Otherwise, the component will not work and
raise an exception.
Design: Published in The Delphi Magazine issue #2
Send your name & (postal)address to Chris Frizelle at 70630,717
for a free sample issue.
}
{$DEFINE EXCEPTIONS}
interface
uses SysUtils, Classes, Controls, StdCtrls, Dialogs, Magic;
{$IFDEF EXCEPTIONS}
Type
EBadChar = class(Exception);
EDLLNotLoaded = class(Exception);
{$ENDIF EXCEPTIONS}
Type
TTicTacToe = class(TWinControl)
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
private { Magic DLL handle }
Game: HGame;
private { 9 game buttons }
Button: Array[TPlace] of TButton;
procedure ButtonClick(Sender: TObject);
procedure ComputerMove;
procedure UserMove(Move: TPlace);
private { start button }
TheStartButton: TButton;
procedure StartButtonClick(Sender: TObject);
private { game properties }
FStartButton: Boolean;
FUserStarts: Boolean;
FGameEnded: Boolean;
FUserChar: Char;
FCompChar: Char;
FVersion: Integer;
FDummy: Integer; { to catch the FVersion changes... }
protected { design interface }
procedure SetStartButton(Value: Boolean);
procedure SetUserStarts(Value: Boolean);
procedure SetUserChar(Value: Char);
procedure SetCompChar(Value: Char);
function GetCaption: String;
procedure SetCaption(Value: String);
published { user interface }
property StartButton: Boolean
read FStartButton write FStartButton
default False;
property Caption: String
read GetCaption write SetCaption;
property UserStarts: Boolean
read FUserStarts write SetUserStarts
default False;
property GameEnded: Boolean
read FGameEnded
default False;
property UserChar: Char
read FUserChar write SetUserChar
default 'X';
property CompChar: Char
read FCompChar write SetCompChar
default '0';
property Version: Integer
read FVersion write FDummy
default 2;
end {TTicTacToe};
implementation
constructor TTicTacToe.Create(AOwner: TComponent);
var ButtonIndex: TPlace;
begin
inherited Create(AOwner);
Game := 0;
UserStarts := False;
FGameEnded := True;
FUserChar := 'X';
FCompChar := '0';
FVersion := 2; { my version number }
TheStartButton := TButton.Create(Self);
TheStartButton.Parent := Self;
TheStartButton.Visible := True;
{ TheStartButton.Caption := 'Humor me...'; }
TheStartButton.OnClick := StartButtonClick;
for ButtonIndex := Low(ButtonIndex) to High(ButtonIndex) do
begin
Button[ButtonIndex] := TButton.Create(Self);
Button[ButtonIndex].Parent := Self;
Button[ButtonIndex].Caption := '';
Button[ButtonIndex].Visible := False;
Button[ButtonIndex].OnClick := ButtonClick;
end;
SetBounds(Left,Top,132,132)
end {Create};
destructor TTicTacToe.Destroy;
var ButtonIndex: TPlace;
begin
if (Game > 0) then EndGame(Game);
TheStartButton.Destroy;
for ButtonIndex := Low(ButtonIndex) to High(ButtonIndex) do
Button[ButtonIndex].Destroy;
inherited Destroy
end {Destroy};
procedure TTicTacToe.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
Const Grid = 3;
GridX = 2;
GridY = 2;
var X,DX,W,Y,DY,H: Word;
begin
Inherited SetBounds(ALeft,ATop,AWidth,AHeight);
TheStartButton.SetBounds(0,0,Width,Height);
X := GridX;
DX := (Width div (Grid * (GridX+GridX))) * (GridX+GridX);
W := DX - GridX;
Y := GridY;
DY := (Height div (Grid * (GridY+GridY))) * (GridY+GridY);
H := DY - GridY;
Button[8].SetBounds(X, Y, W,H);
Button[1].SetBounds(X, Y+DY, W,H);
Button[6].SetBounds(X, Y+DY+DY, W,H);
Inc(X,DX);
Button[3].SetBounds(X, Y, W,H);
Button[5].SetBounds(X, Y+DY, W,H);
Button[7].SetBounds(X, Y+DY+DY, W,H);
Inc(X,DX);
Button[4].SetBounds(X, Y, W,H);
Button[9].SetBounds(X, Y+DY, W,H);
Button[2].SetBounds(X, Y+DY+DY, W,H)
end {SetBounds};
procedure TTicTacToe.StartButtonClick(Sender: TObject);
var ButtonIndex: TPlace;
begin
if MagicLoaded then
begin
Game := NewGame;
FGameEnded := False;
TheStartButton.Visible := False;
for ButtonIndex := Low(ButtonIndex) to High(ButtonIndex) do
Button[ButtonIndex].Visible := True;
if UserStarts then
begin
MessageDlg('You may start...', mtInformation, [mbOk], 0);
Button[5].SetFocus; { hint... }
end
else
ComputerMove
end
else
{$IFDEF EXCEPTIONS}
raise EDLLNotLoaded.Create('MAGIC.DLL could not be loaded!')
{$ELSE}
MessageDlg('Error loading MAGIC.DLL...', mtInformation, [mbOk], 0)
{$ENDIF}
end {ButtonClick};
procedure TTicTacToe.ButtonClick(Sender: TObject);
var ButtonIndex: TPlace;
begin
for ButtonIndex := Low(ButtonIndex) to High(ButtonIndex) do
if Button[ButtonIndex] = Sender as TButton then
UserMove(ButtonIndex)
end {ButtonClick};
procedure TTicTacToe.ComputerMove;
var Move: TMove;
begin
if IsWinner(Game) = NoneID then
begin
Move := NextMove(Game,CompID);
if Move = 0 then
begin
FGameEnded := True;
MessageDlg('Neither has won, the game is a draw!', mtInformation, [mbOk], 0)
end
else
begin
MakeMove(Game,CompID,Move);
Button[Move].Caption := CompChar;
if IsWinner(Game) = CompID then
MessageDlg('I have won!', mtInformation, [mbOk], 0)
else
begin
Move := NextMove(Game,UserID);
if Move = 0 then
begin
FGameEnded := True;
MessageDlg('Neither has won, the game is a draw!', mtInformation, [mbOk], 0)
end
else Button[Move].SetFocus { hint... }
end
end
end
end {ComputerMove};
procedure TTicTacToe.UserMove(Move: TPlace);
begin
if IsWinner(Game) <> NoneID then
begin
if IsWinner(Game) = UserID then
MessageDlg('You have already won!', mtInformation, [mbOk], 0)
else
MessageDlg('I have already won!', mtInformation, [mbOk], 0)
end
else
begin
if FGameEnded then
MessageDlg('The game has already ended!', mtInformation, [mbOk], 0)
else
begin
if GetValue(Game, Move) <> NoneID then
MessageDlg('This place is occupied!', mtWarning, [mbOk], 0)
else
begin
Button[Move].Caption := UserChar;
MakeMove(Game,UserID,Move);
if IsWinner(Game) = UserID then
MessageDlg('Congratulations, you have won!', mtInformation, [mbOk], 0)
else
ComputerMove
end
end
end
end {UserMove};
procedure TTicTacToe.SetUserChar(Value: Char);
begin
if Value = FCompChar then
{$IFDEF EXCEPTIONS}
raise EBadChar.Create(Value+' already in use by CompChar!')
{$ELSE}
MessageDlg('Character '+Value+' already in use by CompChar!', mtError, [mbOk], 0)
{$ENDIF}
else FUserChar := Value
end {SetUserChar};
procedure TTicTacToe.SetCompChar(Value: Char);
begin
if Value = FUserChar then
{$IFDEF EXCEPTIONS}
raise EBadChar.Create(Value+' already in use by UserChar!')
{$ELSE}
MessageDlg('Character '+Value+' already in use by UserChar!', mtError, [mbOk], 0)
{$ENDIF}
else FCompChar := Value
end {SetCompChar};
procedure TTicTacToe.SetUserStarts(Value: Boolean);
begin
FUserStarts := Value;
{$IFDEF DEBUG}
if FUserStarts then
MessageDlg('User Starts!', mtInformation, [mbOk], 0)
else
MessageDlg('I''ll Start!', mtInformation, [mbOk], 0)
{$ENDIF DEBUG}
end {SetUserStarts};
procedure TTicTacToe.SetStartButton(Value: Boolean);
begin
FStartButton := Value
end {SetStartButton};
function TTicTacToe.GetCaption: String;
begin
GetCaption := TheStartButton.Caption
end {GetCaption};
procedure TTicTacToe.SetCaption(Value: String);
begin
TheStartButton.Caption := Value
end {SetCaption};
end.