Skip to content

Instantly share code, notes, and snippets.

@margusmartsepp
Created May 26, 2011 11:43
Show Gist options
  • Save margusmartsepp/992977 to your computer and use it in GitHub Desktop.
Save margusmartsepp/992977 to your computer and use it in GitHub Desktop.
Delphi stick game
unit Gamedisplayer;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, Math;
type
TGamedisplay = class(TForm)
ListBox1: TListBox;
Label1: TLabel;
Edit1: TEdit;
Button1: TButton;
Button2: TButton;
GroupBox1: TGroupBox;
GroupBox2: TGroupBox;
GroupBox3: TGroupBox;
Function getWinCounts(): String;
procedure beginGame(total, take: String; humanStarter: boolean);
procedure endGame(winnerPlayer: String);
procedure Edit1Change(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
nrTable: Integer;
maxTake: Integer;
stickCount: Integer;
humanWinCount: Integer;
cpuWinCount: Integer;
isHumanStarter: boolean;
procedure status(player: String; amount: Integer);
procedure cpuMove();
public
isGameOver: boolean;
end;
var
Gamedisplay: TGamedisplay;
implementation
{$R *.dfm}
{
Returns result for the main board score table.
}
Function TGamedisplay.getWinCounts(): String;
begin
Result := IntToStr(TGamedisplay(Self).humanWinCount) + ' : ' +
IntToStr(TGamedisplay(Self).cpuWinCount);
end;
{
Starts the game
}
procedure TGamedisplay.beginGame(total, take: string; humanStarter: boolean);
begin
isGameOver := False;
isHumanStarter := humanStarter;
Button1.Enabled := False;
ListBox1.Items.Add('');
ListBox1.Items.Add('New ' + take + '-take ' + total +
'-stick game has started.');
Label1.Caption := total;
nrTable := StrToInt(total);
maxTake := StrToInt(take);
Edit1.Text := '';
Edit1.Enabled := true;
Edit1.SetFocus;
stickCount := Gamedisplay.nrTable;
ListBox1.TopIndex := ListBox1.Items.Count - 1;
if not humanStarter then
cpuMove();
refresh;
end;
{
Ends the game.
}
procedure TGamedisplay.endGame(winnerPlayer: String);
begin
if AnsiCompareStr(winnerPlayer, 'Player') = 0 then
begin
humanWinCount := humanWinCount + 1;
end
else
cpuWinCount := cpuWinCount + 1;
Gamedisplay.ListBox1.Items.Add(winnerPlayer + ' won!');
Gamedisplay.Edit1.Enabled := False;
isGameOver := true;
end;
{
Does the stick picking and updateing the status.
Also ends the game, sets the focus to input and listbox view range.
}
procedure TGamedisplay.status(player: String; amount: Integer);
begin
stickCount := stickCount - amount;
Gamedisplay.Label1.Caption := IntToStr(stickCount);
Gamedisplay.ListBox1.Items.Add(player + ' took ' + IntToStr(amount) +
' stick(s)');
if (stickCount = 0) then
begin
endGame(player);
end
else
Gamedisplay.Edit1.SetFocus;
ListBox1.TopIndex := ListBox1.Items.Count - 1;
refresh;
end;
{
Makes the computer move.
}
procedure TGamedisplay.cpuMove();
var
amount: Integer;
begin
amount := stickCount mod (maxTake + 1);
if (amount = 0) then
amount := Math.RandomRange(1, maxTake);
status('Computer', amount);
end;
{
Remove possible '' input. This is done by removing take action button fire
event, when there is no input to get.
}
procedure TGamedisplay.Edit1Change(Sender: TObject);
begin
if (Length(Edit1.Text) = 0) and not isGameOver then
begin
Button1.Enabled := False;
end
else
Button1.Enabled := true;
end;
{
Take action button.
Clears the input field, checks for valid input and calls for status updates.
}
procedure TGamedisplay.Button1Click(Sender: TObject);
var
amount: Integer;
nNorm: Integer;
begin
amount := StrToInt(Gamedisplay.Edit1.Text);
nNorm := Math.Min(Gamedisplay.maxTake, stickCount);
Gamedisplay.Edit1.Text := '';
if (amount > nNorm) or (amount < 1) then
begin
Gamedisplay.ListBox1.Items.Add('Invalid amount. You can take only [ 1 - ' +
IntToStr(nNorm) + ' ] sticks per take.');
ListBox1.TopIndex := ListBox1.Items.Count - 1;
Gamedisplay.Edit1.SetFocus;
end
else
begin
status('Player', amount);
if (stickCount > 0) then // computer turn
cpuMove()
end;
end;
{
Restarts the game.
If game is ongoing, then end the game with computer win.
}
procedure TGamedisplay.Button2Click(Sender: TObject);
begin
if not isGameOver then
endGame('Computer');
beginGame(IntToStr(nrTable), IntToStr(maxTake), isHumanStarter);
end;
end.
unit ProjectStickgame;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, Gamedisplayer;
type
TStickgameform = class(TForm)
Edit1: TEdit;
Edit2: TEdit;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
GroupBox1: TGroupBox;
RadioGroup1: TRadioGroup;
RadioButton1: TRadioButton;
RadioButton2: TRadioButton;
Button1: TButton;
Button2: TButton;
Button3: TButton;
Timer1: TTimer;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Stickgameform: TStickgameform;
implementation
{$R *.dfm}
{
Initiates a new game.
If game is already started, return existing game instance.
If game is ongoing, then end the game with computer win.
}
procedure TStickgameform.Button1Click(Sender: TObject);
begin
if not Assigned(Gamedisplay) then begin
Gamedisplay := TGamedisplay.Create(Application);
end else begin
if not Gamedisplay.isGameOver then
Gamedisplay.endGame('Computer');
end;
Gamedisplay.Show;
Gamedisplay.beginGame(Edit1.Text, Edit2.Text, RadioButton1.Checked);
end;
{
Show stick game help.
}
procedure TStickgameform.Button2Click(Sender: TObject);
begin
with Application do
begin
NormalizeTopMosts;
MessageBox('Two players alternately take sticks off the table. ' +
'Either can be taken either one or more ' +
'matches. Who will take the last stick(s) - wins.', 'Help', MB_OK);
RestoreTopMosts;
end;
end;
{
Show info about the stick game.
}
procedure TStickgameform.Button3Click(Sender: TObject);
begin
with Application do
begin
NormalizeTopMosts;
MessageBox('Version: 1.0 Copyright: CC BY-SA 3.0',
'About Stick Game', MB_OK);
RestoreTopMosts;
end;
end;
{
Updates the score table.
}
procedure TStickgameform.Timer1Timer(Sender: TObject);
begin
if Assigned(Gamedisplay) then begin
Label3.Caption := Gamedisplay.getWinCounts;
end;
end;
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment