6 System.SysUtils, System.Types, System.UITypes, System.Classes,
\r
7 System.Variants, Generics.Collections,
\r
8 FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
\r
9 System.Math, FMX.Objects, FMX.StdCtrls, FMX.Menus;
\r
15 TStoneType = (stNone, stWhite, stBlack, stError, stEffect);
\r
17 TEffectData = record
\r
23 Strings: array [0 .. bmp_count - 1] of array [0 .. bmp_count - 1]
\r
28 TPlayer = class(TObject)
\r
33 property Auto: Boolean read FAuto write FAuto;
\r
34 property Stone: TStoneType read FStone write FStone;
\r
37 TStoneGrid = class(TObject)
\r
39 FStrings: TGridData;
\r
40 FBuffer: array [0 .. bmp_count * bmp_count - 4] of TGridData;
\r
41 FTurnNumber: integer;
\r
42 FTurnIndex: integer;
\r
44 FList: TList<TEffectData>;
\r
45 FEffectStone: TStoneType;
\r
49 function GetStrings(X, Y: integer): TStoneType;
\r
50 procedure SetStrings(X, Y: integer; const Value: TStoneType);
\r
51 procedure SetTurnNumber(const Value: integer);
\r
52 function GetActive: Boolean;
\r
53 procedure SetActive(const Value: Boolean);
\r
54 function GetStone: TStoneType;
\r
57 destructor Destroy; override;
\r
59 function CalScore(Stone: TStoneType; X, Y: integer;
\r
60 out Score: integer): Boolean;
\r
61 function CanSetStone(Stone: TStoneType; X, Y: integer; Reverse: Boolean;
\r
62 const Visible: Boolean = false): Boolean;
\r
63 function NextStone(Stone: TStoneType; var Pos: TPoint): Boolean;
\r
67 function ListExecute: Boolean;
\r
69 procedure Paint(Canvas: TCanvas);
\r
70 procedure ImageCount(X, Y: integer);
\r
71 function AddScore(X, Y: integer; const NG: array of TPoint): integer;
\r
72 property Strings[X, Y: integer]: TStoneType read GetStrings
\r
73 write SetStrings; default;
\r
74 property TurnNumber: integer read FTurnNumber write SetTurnNumber;
\r
75 property Active: Boolean read GetActive write SetActive;
\r
76 property Stone: TStoneType read GetStone;
\r
79 TForm1 = class(TForm)
\r
80 MainMenu1: TMainMenu;
\r
81 MenuItem1: TMenuItem;
\r
82 MenuItem2: TMenuItem;
\r
83 MenuItem3: TMenuItem;
\r
84 MenuItem4: TMenuItem;
\r
85 MenuItem5: TMenuItem;
\r
86 MenuItem6: TMenuItem;
\r
87 MenuItem7: TMenuItem;
\r
88 MenuItem8: TMenuItem;
\r
89 MenuItem9: TMenuItem;
\r
90 MenuItem10: TMenuItem;
\r
91 MenuItem11: TMenuItem;
\r
92 MenuItem12: TMenuItem;
\r
95 PaintBox1: TPaintBox;
\r
99 MenuItem13: TMenuItem;
\r
100 MenuItem14: TMenuItem;
\r
101 MenuItem15: TMenuItem;
\r
102 procedure FormCreate(Sender: TObject);
\r
103 procedure FormDestroy(Sender: TObject);
\r
104 procedure Timer1Timer(Sender: TObject);
\r
105 procedure FormResize(Sender: TObject);
\r
106 procedure MenuItem4Click(Sender: TObject);
\r
107 procedure MenuItem2Click(Sender: TObject);
\r
108 procedure PaintBox1Tap(Sender: TObject; const Point: TPointF);
\r
109 procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
\r
110 Shift: TShiftState; X, Y: Single);
\r
111 procedure PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
\r
112 procedure MenuItem6Click(Sender: TObject);
\r
113 procedure PaintBox1Resize(Sender: TObject);
\r
114 procedure MenuItem8Click(Sender: TObject);
\r
115 procedure MenuItem10Click(Sender: TObject);
\r
116 procedure MenuItem11Click(Sender: TObject);
\r
117 procedure Timer2Timer(Sender: TObject);
\r
119 { Private
\90é
\8c¾ }
\r
120 StoneGrid: TStoneGrid;
\r
123 procedure CompStone;
\r
124 procedure GameStart;
\r
125 procedure ChangePlayer;
\r
126 procedure ChMain(var CapStr: string);
\r
128 { Public
\90é
\8c¾ }
\r
143 function TStoneGrid.AddScore(X, Y: integer; const NG: array of TPoint): integer;
\r
149 if (X = s.X) and (Y = s.Y) then
\r
156 function TStoneGrid.CalScore(Stone: TStoneType; X, Y: integer;
\r
157 out Score: integer): Boolean;
\r
161 waste: array [1 .. 12] of TPoint = ((X: 1; Y: 0), (X: 6; Y: 0), (X: 0; Y: 1),
\r
162 (X: 1; Y: 1), (X: 6; Y: 1), (X: 7; Y: 1), (X: 0; Y: 6), (X: 1; Y: 6), (X: 6;
\r
163 Y: 6), (X: 7; Y: 6), (X: 1; Y: 7), (X: 6; Y: 7));
\r
164 worth: array [1 .. 4] of TPoint = ((X: 0; Y: 0), (X: 7; Y: 0), (X: 0; Y: 7),
\r
170 for m := 0 to bmp_count - 1 do
\r
171 for n := 0 to bmp_count - 1 do
\r
172 if CanSetStone(Stone, m, n, false) = true then
\r
175 inc(Score, AddScore(m, n, worth));
\r
185 for m := 0 to bmp_count - 1 do
\r
186 for n := 0 to bmp_count - 1 do
\r
188 if CanSetStone(Stone, m, n, true) = true then
\r
190 if (loop mod 2) > 0 then
\r
204 FStrings := FBuffer[FTurnIndex + loop];
\r
207 FBuffer[FTurnIndex + loop] := FStrings;
\r
214 if CanSetStone(Stone, X, Y, true) = true then
\r
218 // if FTurnIndex < 50 then
\r
219 inc(Score, AddScore(X, Y, waste));
\r
220 dec(Score, AddScore(X, Y, worth));
\r
227 if (Form1.MenuItem14.IsChecked = true) and (FTurnIndex + 2 <= 60) then
\r
237 FStrings := FBuffer[FTurnIndex];
\r
240 function TStoneGrid.CanSetStone(Stone: TStoneType; X, Y: integer;
\r
241 Reverse: Boolean; const Visible: Boolean): Boolean;
\r
246 procedure Method(m, n: integer);
\r
257 s := GetStrings(X + m * i, Y + n * i);
\r
258 if s = stEffect then
\r
260 if (s = stNone) or (s = stError) then
\r
262 else if s = Stone then
\r
265 if (result = false) and (Reverse = true) then
\r
266 SetStrings(X, Y, Stone);
\r
268 if Reverse = true then
\r
270 Form1.PaintBox1.Repaint;
\r
271 for j := 1 to i - 1 do
\r
273 if Visible = true then
\r
275 FEffectStone := Stone;
\r
276 q.Left := X + m * j;
\r
277 q.Top := Y + n * j;
\r
281 SetStrings(q.Left, q.Top, stEffect);
\r
282 for k := 1 to 10 do
\r
285 Application.ProcessMessages;
\r
289 SetStrings(X + m * j, Y + n * j, Stone);
\r
309 if GetStrings(X, Y) = stNone then
\r
322 procedure TStoneGrid.Clear;
\r
327 for i := 0 to bmp_count - 1 do
\r
328 for j := 0 to bmp_count - 1 do
\r
329 Strings[i, j] := stNone;
\r
330 Strings[3, 3] := stBlack;
\r
331 Strings[4, 4] := stBlack;
\r
332 Strings[4, 3] := stWhite;
\r
333 Strings[3, 4] := stWhite;
\r
336 FBuffer[0] := FStrings;
\r
339 constructor TStoneGrid.Create;
\r
342 FList := TList<TEffectData>.Create;
\r
345 destructor TStoneGrid.Destroy;
\r
351 procedure TStoneGrid.GameOver;
\r
357 function TStoneGrid.GetActive: Boolean;
\r
359 if (FActive = true) and (FList.Count = 0) then
\r
365 function TStoneGrid.GetStone: TStoneType;
\r
367 result := FBuffer[FTurnNumber].Stone;
\r
370 function TStoneGrid.GetStrings(X, Y: integer): TStoneType;
\r
372 if (X >= 0) and (X < bmp_count) and (Y >= 0) and (Y < bmp_count) then
\r
373 result := FStrings.Strings[X, Y]
\r
378 procedure TStoneGrid.ImageCount(X, Y: integer);
\r
384 function TStoneGrid.ListExecute: Boolean;
\r
389 if FList.Count = 0 then
\r
394 while i < FList.Count do
\r
397 if s.X < FIndex_X - 1 then
\r
399 else if s.Y < FIndex_Y - 1 then
\r
406 SetStrings(s.Left, s.Top, FEffectStone);
\r
414 if FList.Count = 0 then
\r
418 FBuffer[FTurnIndex] := FStrings;
\r
419 FBuffer[FTurnIndex].Stone := FEffectStone;
\r
420 Form1.PaintBox1.Repaint;
\r
421 Form1.ChangePlayer;
\r
422 if FGameOver = false then
\r
429 function TStoneGrid.NextStone(Stone: TStoneType; var Pos: TPoint): Boolean;
\r
431 i, j, m, n: integer;
\r
435 for i := 0 to bmp_count - 1 do
\r
436 for j := 0 to bmp_count - 1 do
\r
437 if (CalScore(Stone, i, j, m) = true) and ((result = false) or (m < n))
\r
440 if result = false then
\r
443 Pos := Point(i, j);
\r
447 procedure TStoneGrid.Paint(Canvas: TCanvas);
\r
454 if FEffectStone = stBlack then
\r
455 s := Form1.Image1.Bitmap
\r
457 s := Form1.Image2.Bitmap;
\r
460 Canvas.DrawBitmap(s, RectF(p.X * 50, p.Y * 50, (p.X + 1) * 50,
\r
461 (p.Y + 1) * 50), RectF(p.Left * k, p.Top * k, (p.Left + 1) * k,
\r
462 (p.Top + 1) * k), 1);
\r
466 procedure TStoneGrid.Pause;
\r
471 procedure TStoneGrid.Restart;
\r
474 FGameOver := false;
\r
475 FTurnIndex := FTurnNumber;
\r
478 procedure TStoneGrid.SetActive(const Value: Boolean);
\r
480 if (FGameOver = false) or (Value = false) then
\r
484 procedure TStoneGrid.SetStrings(X, Y: integer; const Value: TStoneType);
\r
486 if (X >= 0) and (X < bmp_count) and (Y >= 0) and (Y < bmp_count) then
\r
487 FStrings.Strings[X, Y] := Value;
\r
490 procedure TStoneGrid.SetTurnNumber(const Value: integer);
\r
492 if Value > FTurnIndex then
\r
493 FTurnNumber := FTurnIndex
\r
494 else if Value < 0 then
\r
497 FTurnNumber := Value;
\r
498 FStrings := FBuffer[FTurnNumber];
\r
501 procedure TStoneGrid.Start;
\r
505 FGameOver := false;
\r
510 procedure TForm1.ChangePlayer;
\r
512 i, j, m, n: integer;
\r
514 function Execute: Boolean;
\r
518 for i := 0 to bmp_count - 1 do
\r
519 for j := 0 to bmp_count - 1 do
\r
520 if StoneGrid.CanSetStone(Index.Stone, i, j, false) = true then
\r
531 if Execute = false then
\r
534 if Execute = false then
\r
538 for i := 0 to bmp_count - 1 do
\r
539 for j := 0 to bmp_count - 1 do
\r
540 case StoneGrid[i, j] of
\r
547 Caption := '
\8fI
\97¹
\82µ
\82Ü
\82µ
\82½';
\r
549 s := 'Player1 Win:' + #13#10
\r
551 s := 'Player2 Win:' + #13#10
\r
553 s := 'Draw:' + #13#10;
\r
554 StoneGrid.GameOver;
\r
555 Showmessage(s + '(Player1) ' + m.ToString + #13#10 + '(Player2) ' +
\r
565 procedure TForm1.ChMain(var CapStr: string);
\r
567 CapStr := (StoneGrid.TurnNumber + 1).ToString + '
\8eè
\96Ú
\81F';
\r
568 if Index = Player1 then
\r
571 CapStr := CapStr + '
\94\92\82Ì
\8eè
\94Ô
\82Å
\82·';
\r
576 CapStr := CapStr + '
\8d\95\82Ì
\8eè
\94Ô
\82Å
\82·';
\r
580 procedure TForm1.CompStone;
\r
584 StoneGrid.Active := false;
\r
585 if StoneGrid.NextStone(Index.Stone, s) = true then
\r
587 StoneGrid.CanSetStone(Index.Stone, s.X, s.Y, true, true);
\r
594 procedure TForm1.GameStart;
\r
599 Caption := '1
\8eè
\96Ú
\81F
\8d\95\82©
\82ç
\8en
\82ß
\82Ü
\82·';
\r
602 procedure TForm1.MenuItem10Click(Sender: TObject);
\r
607 procedure TForm1.MenuItem11Click(Sender: TObject);
\r
615 if Sender = MenuItem11 then
\r
616 TurnNumber := TurnNumber + 1
\r
618 TurnNumber := TurnNumber - 1;
\r
619 if (i = TurnNumber) then
\r
625 if ((TurnNumber = 0) and (Index <> Player1)) or
\r
626 (Index.Stone = FBuffer[TurnNumber].Stone) then
\r
628 if TurnNumber = 60 then
\r
640 if Index = Player1 then
\r
648 procedure TForm1.MenuItem2Click(Sender: TObject);
\r
650 Timer1.Enabled := false;
\r
651 Timer2.Enabled := false;
\r
653 Timer1.Enabled := true;
\r
654 Timer2.Enabled := true;
\r
657 procedure TForm1.MenuItem4Click(Sender: TObject);
\r
662 procedure TForm1.MenuItem6Click(Sender: TObject);
\r
664 Player1.Auto := MenuItem6.IsChecked;
\r
665 Player2.Auto := MenuItem7.IsChecked;
\r
668 procedure TForm1.MenuItem8Click(Sender: TObject);
\r
673 procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
\r
677 if StoneGrid.Active = false then
\r
678 StoneGrid.Paint(Canvas);
\r
679 for i := 0 to bmp_count - 1 do
\r
681 for j := 0 to bmp_count - 1 do
\r
683 case StoneGrid.Strings[i, j] of
\r
685 Canvas.DrawBitmap(Image3.Bitmap, RectF(100, 0, 150, 50),
\r
686 RectF(i * Size, j * Size, (i + 1) * Size, (j + 1) * Size), 1);
\r
688 Canvas.DrawBitmap(Image3.Bitmap, RectF(50, 0, 100, 50),
\r
689 RectF(i * Size, j * Size, (i + 1) * Size, (j + 1) * Size), 1);
\r
693 Canvas.DrawBitmap(Image3.Bitmap, RectF(0, 0, 50, 50),
\r
694 RectF(i * Size, j * Size, (i + 1) * Size, (j + 1) * Size), 1);
\r
696 Canvas.DrawLine(PointF(0, j * Size), PointF(bmp_count * Size,
\r
699 Canvas.DrawLine(PointF(i * Size, 0), PointF(i * Size, Size * bmp_count), 1);
\r
701 Canvas.DrawLine(PointF(bmp_count * Size, 0), PointF(bmp_count * Size,
\r
702 bmp_count * Size), 1);
\r
703 Canvas.DrawLine(PointF(0, bmp_count * Size), PointF(bmp_count * Size,
\r
704 bmp_count * Size), 1);
\r
707 procedure TForm1.PaintBox1Resize(Sender: TObject);
\r
709 Size := Min(ClientWidth, ClientHeight) div bmp_count;
\r
712 procedure TForm1.FormCreate(Sender: TObject);
\r
714 ClientWidth := 400;
\r
715 ClientHeight := 400;
\r
716 StoneGrid := TStoneGrid.Create;
\r
717 StoneGrid.ImageCount(6, 5);
\r
718 Player1 := TPlayer.Create;
\r
719 Player2 := TPlayer.Create;
\r
720 Player1.Stone := stBlack;
\r
721 Player2.Stone := stWhite;
\r
722 Player2.Auto := true;
\r
723 with PaintBox1.Canvas do
\r
725 StrokeDash := TStrokeDash.Solid;
\r
726 Stroke.Color := TAlphaColors.Black;
\r
727 StrokeThickness := 3;
\r
729 PaintBox1Resize(Sender);
\r
733 procedure TForm1.FormDestroy(Sender: TObject);
\r
740 procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
\r
741 Shift: TShiftState; X, Y: Single);
\r
743 PaintBox1Tap(Sender, PointF(X, Y));
\r
746 procedure TForm1.Timer1Timer(Sender: TObject);
\r
748 if (StoneGrid.Active = true) and (Index.Auto = true) then
\r
752 procedure TForm1.Timer2Timer(Sender: TObject);
\r
754 if (StoneGrid.Active = false) and (StoneGrid.ListExecute = true) then
\r
758 procedure TForm1.FormResize(Sender: TObject);
\r
760 Size := Min(ClientWidth, ClientHeight) div bmp_count;
\r
764 procedure TForm1.PaintBox1Tap(Sender: TObject; const Point: TPointF);
\r
766 if Index.Auto = false then
\r
769 if (StoneGrid.Active = true) and
\r
770 (StoneGrid.CanSetStone(Index.Stone, Floor(Point.X / Size),
\r
771 Floor(Point.Y / Size), true, true) = true) then
\r
773 StoneGrid.Active := false;
\r
775 StoneGrid.Active := true;
\r