204 lines
4.3 KiB
ObjectPascal
204 lines
4.3 KiB
ObjectPascal
program Game21;
|
|
|
|
{$APPTYPE CONSOLE}
|
|
|
|
{$R *.res}
|
|
|
|
uses
|
|
System.SysUtils,
|
|
System.StrUtils, // for IfThen
|
|
Winapi.Windows; // for ClearScreen
|
|
|
|
const
|
|
HARD_MODE = True;
|
|
|
|
var
|
|
computerPlayer: string = 'Computer';
|
|
humanPlayer: string = 'Player 1';
|
|
|
|
// for change color
|
|
ConOut: THandle;
|
|
BufInfo: TConsoleScreenBufferInfo;
|
|
|
|
procedure ClearScreen;
|
|
var
|
|
stdout: THandle;
|
|
csbi: TConsoleScreenBufferInfo;
|
|
ConsoleSize: DWORD;
|
|
NumWritten: DWORD;
|
|
Origin: TCoord;
|
|
begin
|
|
stdout := GetStdHandle(STD_OUTPUT_HANDLE);
|
|
Win32Check(stdout <> INVALID_HANDLE_VALUE);
|
|
Win32Check(GetConsoleScreenBufferInfo(stdout, csbi));
|
|
ConsoleSize := csbi.dwSize.X * csbi.dwSize.Y;
|
|
Origin.X := 0;
|
|
Origin.Y := 0;
|
|
Win32Check(FillConsoleOutputCharacter(stdout, ' ', ConsoleSize, Origin, NumWritten));
|
|
Win32Check(FillConsoleOutputAttribute(stdout, csbi.wAttributes, ConsoleSize,
|
|
Origin, NumWritten));
|
|
Win32Check(SetConsoleCursorPosition(stdout, Origin));
|
|
end;
|
|
|
|
procedure ResetColor;
|
|
begin
|
|
SetConsoleTextAttribute(ConOut, BufInfo.wAttributes);
|
|
end;
|
|
|
|
procedure ChangeColor(color: Word);
|
|
begin
|
|
ConOut := TTextRec(Output).Handle;
|
|
GetConsoleScreenBufferInfo(ConOut, BufInfo);
|
|
SetConsoleTextAttribute(TTextRec(Output).Handle, color);
|
|
end;
|
|
|
|
function SwapPlayer(currentPlayer: string): string;
|
|
begin
|
|
Result := IfThen(currentPlayer = humanPlayer, computerPlayer, humanPlayer);
|
|
end;
|
|
|
|
function RandomPlayerSelect(): string;
|
|
begin
|
|
Result := IfThen(Random() < 0.5, computerPlayer, humanPlayer);
|
|
end;
|
|
|
|
function CheckIfCanWin(total: Integer): Boolean;
|
|
begin
|
|
result := (total >= 18);
|
|
end;
|
|
|
|
function CheckIfCanLose(total: Integer; var choose: Integer; hardMode: Boolean =
|
|
False): Boolean;
|
|
var
|
|
range: Integer;
|
|
begin
|
|
range := 17 - total;
|
|
Result := false;
|
|
if (range > 0) and (range < 4) then
|
|
begin
|
|
Result := true;
|
|
if hardMode then
|
|
choose := range
|
|
else
|
|
choose := Random(range - 1) + 1;
|
|
end;
|
|
end;
|
|
|
|
function CompMove(total: Integer): Integer;
|
|
begin
|
|
if (CheckIfCanWin(total)) then
|
|
begin
|
|
exit(21 - total);
|
|
end;
|
|
|
|
if CheckIfCanLose(total, Result, HARD_MODE) then
|
|
exit;
|
|
|
|
Result := Random(3) + 1;
|
|
end;
|
|
|
|
function HumanMove: Integer;
|
|
var
|
|
choice: string;
|
|
begin
|
|
repeat
|
|
Writeln('Choose from numbers: 1, 2, 3');
|
|
Readln(choice);
|
|
until TryStrToInt(choice, Result) and (Result in [1..3]);
|
|
end;
|
|
|
|
procedure PlayGame();
|
|
var
|
|
playAnother: Boolean;
|
|
total, final_, roundChoice, compWins, humanWins: Integer;
|
|
choice, currentPlayer: string;
|
|
begin
|
|
playAnother := True;
|
|
total := 0;
|
|
final_ := 21;
|
|
roundChoice := 0;
|
|
Randomize;
|
|
currentPlayer := RandomPLayerSelect();
|
|
compWins := 0;
|
|
humanWins := 0;
|
|
|
|
while (playAnother) do
|
|
begin
|
|
ClearScreen;
|
|
ChangeColor(FOREGROUND_INTENSITY or FOREGROUND_GREEN);
|
|
Writeln(total);
|
|
ResetColor;
|
|
Writeln('');
|
|
|
|
Writeln('Now playing: ' + currentPlayer);
|
|
if currentPlayer = computerPlayer then
|
|
roundChoice := CompMove(total)
|
|
else
|
|
roundChoice := HumanMove;
|
|
inc(total, roundChoice);
|
|
|
|
if (total = final_) then
|
|
begin
|
|
if (currentPlayer = computerPlayer) then
|
|
begin
|
|
inc(compWins);
|
|
end
|
|
else
|
|
begin
|
|
inc(humanWins);
|
|
end;
|
|
|
|
ClearScreen;
|
|
Writeln('Winner: ' + currentPlayer);
|
|
Writeln('Comp wins: ', compWins, '. Human wins: ', humanWins, #10);
|
|
Writeln('Do you wan to play another round? y/n');
|
|
|
|
readln(choice);
|
|
|
|
if choice = 'y' then
|
|
begin
|
|
total := 0;
|
|
ClearScreen;
|
|
end
|
|
else if choice = 'n' then
|
|
playAnother := false
|
|
else
|
|
begin
|
|
Writeln('Invalid choice! Choose from y or n');
|
|
Continue;
|
|
end;
|
|
end
|
|
else if total > 21 then
|
|
begin
|
|
Writeln('Not the right time to play this game :)');
|
|
break;
|
|
end;
|
|
|
|
currentPlayer := SwapPlayer(currentPlayer);
|
|
end;
|
|
|
|
end;
|
|
|
|
const
|
|
WELLCOME_MSG: array[0..5] of string = ('Welcome to 21 game'#10,
|
|
'21 is a two player game.', 'The game is played by choosing a number.',
|
|
'1, 2, or 3 to be added a total sum.'#10,
|
|
'The game is won by the player reaches exactly 21.'#10, 'Press ENTER to start!'#10);
|
|
|
|
var
|
|
i: Integer;
|
|
|
|
begin
|
|
try
|
|
for i := 0 to High(WELLCOME_MSG) do
|
|
Writeln(WELLCOME_MSG[i]);
|
|
ResetColor;
|
|
Readln; // Wait press enter
|
|
|
|
PlayGame();
|
|
except
|
|
on E: Exception do
|
|
Writeln(E.ClassName, ': ', E.Message);
|
|
end;
|
|
end.
|