Develop and Download Open Source Software

Browse Subversion Repository

Contents of /Unit1.pas

Parent Directory Parent Directory | Revision Log Revision Log


Revision 38 - (show annotations) (download) (as text)
Sun Aug 30 14:04:08 2015 UTC (8 years, 6 months ago) by yamat0jp
File MIME type: text/x-pascal
File size: 18774 byte(s)
Manual対戦のバグを減らすことができました
1 unit Unit1;
2
3 interface
4
5 uses
6 System.SysUtils, System.Types, System.UITypes, System.Classes,
7 System.Variants, Generics.Collections,
8 FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Menus,
9 System.Math, FMX.Objects, FMX.StdCtrls;
10
11 const
12 bmp_count = 8;
13
14 type
15 TStoneType = (stNone, stWhite, stBlack, stError, stEffect);
16
17 TEffectData = record
18 X, Y: integer;
19 Left, Top: integer;
20 end;
21
22 TGridData = record
23 Strings: array [0 .. bmp_count - 1] of array [0 .. bmp_count - 1]
24 of TStoneType;
25 Stone: TStoneType;
26 end;
27
28 TPlayer = class(TObject)
29 private
30 FAuto: Boolean;
31 FStone: TStoneType;
32 public
33 property Auto: Boolean read FAuto write FAuto;
34 property Stone: TStoneType read FStone write FStone;
35 end;
36
37 TStoneGrid = class(TObject)
38 private
39 FStrings: TGridData;
40 FBuffer: array [0 .. bmp_count * bmp_count - 4] of TGridData;
41 FTurnNumber: integer;
42 FTurnIndex: integer;
43 FActive: Boolean;
44 FList: TList<TEffectData>;
45 FEffectStone: TStoneType;
46 FIndex_X: integer;
47 FIndex_Y: integer;
48 FGameOver: Boolean;
49 function GetStrings(X, Y: integer): TStoneType;
50 procedure SetStrings(X, Y: integer; const Value: TStoneType);
51 procedure SetTurnNumber(const Value: integer);
52 function GetActive: Boolean;
53 procedure SetActive(const Value: Boolean);
54 function GetStone: TStoneType;
55 public
56 constructor Create;
57 destructor Destroy; override;
58 procedure Clear;
59 function CalScore(Stone: TStoneType; X, Y: integer;
60 out Score: integer): Boolean;
61 function CanSetStone(Stone: TStoneType; X, Y: integer; Reverse: Boolean;
62 const Visible: Boolean = false): Boolean;
63 function NextStone(Stone: TStoneType; var Pos: TPoint): Boolean;
64 procedure Start;
65 procedure Restart;
66 procedure Pause;
67 function ListExecute: Boolean;
68 procedure GameOver;
69 procedure Paint(Canvas: TCanvas);
70 procedure ImageCount(X, Y: integer);
71 function AddScore(X, Y: integer; const NG: array of TPoint): integer;
72 property Strings[X, Y: integer]: TStoneType read GetStrings
73 write SetStrings; default;
74 property TurnNumber: integer read FTurnNumber write SetTurnNumber;
75 property Active: Boolean read GetActive write SetActive;
76 property Stone: TStoneType read GetStone;
77 end;
78
79 TForm1 = class(TForm)
80 Timer1: TTimer;
81 MainMenu1: TMainMenu;
82 MenuItem1: TMenuItem;
83 MenuItem2: TMenuItem;
84 MenuItem3: TMenuItem;
85 MenuItem4: TMenuItem;
86 MenuItem5: TMenuItem;
87 MenuItem6: TMenuItem;
88 MenuItem7: TMenuItem;
89 PaintBox1: TPaintBox;
90 MenuItem8: TMenuItem;
91 MenuItem9: TMenuItem;
92 MenuItem10: TMenuItem;
93 MenuItem11: TMenuItem;
94 MenuItem12: TMenuItem;
95 Timer2: TTimer;
96 Image1: TImage;
97 Image2: TImage;
98 Image3: TImage;
99 MenuItem13: TMenuItem;
100 MenuItem14: TMenuItem;
101 MenuItem15: TMenuItem;
102 procedure FormCreate(Sender: TObject);
103 procedure FormDestroy(Sender: TObject);
104 procedure Timer1Timer(Sender: TObject);
105 procedure FormResize(Sender: TObject);
106 procedure MenuItem4Click(Sender: TObject);
107 procedure MenuItem2Click(Sender: TObject);
108 procedure PaintBox1Tap(Sender: TObject; const Point: TPointF);
109 procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
110 Shift: TShiftState; X, Y: Single);
111 procedure PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
112 procedure MenuItem6Click(Sender: TObject);
113 procedure PaintBox1Resize(Sender: TObject);
114 procedure MenuItem8Click(Sender: TObject);
115 procedure MenuItem10Click(Sender: TObject);
116 procedure MenuItem11Click(Sender: TObject);
117 procedure Timer2Timer(Sender: TObject);
118 private
119 { Private ���� }
120 StoneGrid: TStoneGrid;
121 Index: TPlayer;
122 Size: integer;
123 procedure CompStone;
124 procedure GameStart;
125 procedure ChangePlayer;
126 procedure ChMain(var CapStr: string);
127 public
128 { Public ���� }
129 end;
130
131 var
132 Player1: TPlayer;
133 Player2: TPlayer;
134
135 Form1: TForm1;
136
137 implementation
138
139 {$R *.fmx}
140 {$R *.Windows.fmx MSWINDOWS}
141 {$R *.XLgXhdpiTb.fmx ANDROID}
142 { TStoneGrid }
143
144 function TStoneGrid.AddScore(X, Y: integer; const NG: array of TPoint): integer;
145 var
146 s: TPoint;
147 begin
148 result := 0;
149 for s in NG do
150 if (X = s.X) and (Y = s.Y) then
151 begin
152 result := 10;
153 break;
154 end;
155 end;
156
157 function TStoneGrid.CalScore(Stone: TStoneType; X, Y: integer;
158 out Score: integer): Boolean;
159 var
160 loop: integer;
161 const
162 waste: array [1 .. 12] of TPoint = ((X: 1; Y: 0), (X: 6; Y: 0), (X: 0; Y: 1),
163 (X: 1; Y: 1), (X: 6; Y: 1), (X: 7; Y: 1), (X: 0; Y: 6), (X: 1; Y: 6), (X: 6;
164 Y: 6), (X: 7; Y: 6), (X: 1; Y: 7), (X: 6; Y: 7));
165 worth: array [1 .. 4] of TPoint = ((X: 0; Y: 0), (X: 7; Y: 0), (X: 0; Y: 7),
166 (X: 7; Y: 7));
167 label Last;
168 procedure Easy;
169 var
170 m, n: integer;
171 begin
172 for m := 0 to bmp_count - 1 do
173 for n := 0 to bmp_count - 1 do
174 if CanSetStone(Stone, m, n, false) = true then
175 begin
176 inc(Score);
177 inc(Score, AddScore(m, n, worth));
178 end;
179 end;
180 procedure Hard;
181 var
182 m, n: integer;
183 begin
184 if loop > 1 then
185 Exit;
186 inc(loop);
187 for m := 0 to bmp_count - 1 do
188 for n := 0 to bmp_count - 1 do
189 begin
190 if CanSetStone(Stone, m, n, true) = true then
191 begin
192 if (loop mod 2) > 0 then
193 inc(Score)
194 else
195 dec(Score);
196 case Stone of
197 stBlack:
198 Stone := stWhite;
199 stWhite:
200 Stone := stBlack;
201 end;
202 Hard;
203 if loop > 1 then
204 begin
205 Easy;
206 FStrings := FBuffer[FTurnIndex + loop];
207 end
208 else
209 FBuffer[FTurnIndex + loop] := FStrings;
210 end;
211 end;
212 dec(loop);
213 end;
214
215 begin
216 if CanSetStone(Stone, X, Y, true) = true then
217 begin
218 Score := 0;
219 result := true;
220 if FTurnIndex < 50 then
221 inc(Score, AddScore(X, Y, waste));
222 dec(Score, AddScore(X, Y, worth));
223 case Stone of
224 stBlack:
225 Stone := stWhite;
226 stWhite:
227 Stone := stBlack;
228 end;
229 if (Form1.MenuItem14.IsChecked = true) and (FTurnIndex + 2 <= 60) then
230 begin
231 loop := 0;
232 Hard;
233 end
234 else
235 Easy;
236 end
237 else
238 result := false;
239 FStrings := FBuffer[FTurnIndex];
240 end;
241
242 function TStoneGrid.CanSetStone(Stone: TStoneType; X, Y: integer;
243 Reverse: Boolean; const Visible: Boolean): Boolean;
244 var
245 i: integer;
246 p: Boolean;
247 q: TEffectData;
248 procedure Method(m, n: integer);
249 var
250 s: TStoneType;
251 j: integer;
252 k: integer;
253 begin
254 if p = false then
255 Exit;
256 i := 1;
257 while true do
258 begin
259 s := GetStrings(X + m * i, Y + n * i);
260 if s = stEffect then
261 s := FEffectStone;
262 if (s = stNone) or (s = stError) then
263 break
264 else if s = Stone then
265 if i > 1 then
266 begin
267 if (result = false) and (Reverse = true) then
268 SetStrings(X, Y, Stone);
269 result := true;
270 if Reverse = true then
271 begin
272 Form1.PaintBox1.Repaint;
273 for j := 1 to i - 1 do
274 begin
275 if Visible = true then
276 begin
277 FEffectStone := Stone;
278 q.Left := X + m * j;
279 q.Top := Y + n * j;
280 q.X := 0;
281 q.Y := 0;
282 FList.Add(q);
283 SetStrings(q.Left, q.Top, stEffect);
284 for k := 1 to 10 do
285 begin
286 Sleep(15);
287 Application.ProcessMessages;
288 end;
289 end
290 else
291 SetStrings(X + m * j, Y + n * j, Stone);
292 end;
293 break;
294 end
295 else
296 begin
297 p := false;
298 break;
299 end;
300 end
301 else
302 break
303 else
304 inc(i);
305 end;
306 end;
307
308 begin
309 result := false;
310 p := true;
311 if GetStrings(X, Y) = stNone then
312 begin
313 Method(-1, -1);
314 Method(-1, 0);
315 Method(-1, 1);
316 Method(0, -1);
317 Method(0, 1);
318 Method(1, -1);
319 Method(1, 0);
320 Method(1, 1);
321 end;
322 end;
323
324 procedure TStoneGrid.Clear;
325 var
326 i, j: integer;
327 begin
328 FList.Clear;
329 for i := 0 to bmp_count - 1 do
330 for j := 0 to bmp_count - 1 do
331 Strings[i, j] := stNone;
332 Strings[3, 3] := stBlack;
333 Strings[4, 4] := stBlack;
334 Strings[4, 3] := stWhite;
335 Strings[3, 4] := stWhite;
336 FTurnNumber := 0;
337 FTurnIndex := 0;
338 FBuffer[0] := FStrings;
339 end;
340
341 constructor TStoneGrid.Create;
342 begin
343 inherited;
344 FList := TList<TEffectData>.Create;
345 end;
346
347 destructor TStoneGrid.Destroy;
348 begin
349 FList.Free;
350 inherited;
351 end;
352
353 procedure TStoneGrid.GameOver;
354 begin
355 FGameOver := true;
356 FActive := false;
357 end;
358
359 function TStoneGrid.GetActive: Boolean;
360 begin
361 if (FActive = true) and (FList.Count = 0) then
362 result := true
363 else
364 result := false;
365 end;
366
367 function TStoneGrid.GetStone: TStoneType;
368 begin
369 result := FBuffer[FTurnNumber].Stone;
370 end;
371
372 function TStoneGrid.GetStrings(X, Y: integer): TStoneType;
373 begin
374 if (X >= 0) and (X < bmp_count) and (Y >= 0) and (Y < bmp_count) then
375 result := FStrings.Strings[X, Y]
376 else
377 result := stError;
378 end;
379
380 procedure TStoneGrid.ImageCount(X, Y: integer);
381 begin
382 FIndex_X := X;
383 FIndex_Y := Y;
384 end;
385
386 function TStoneGrid.ListExecute: Boolean;
387 var
388 i: integer;
389 s: TEffectData;
390 begin
391 if FList.Count = 0 then
392 result := false
393 else
394 begin
395 i := 0;
396 while i < FList.Count do
397 begin
398 s := FList[i];
399 if s.X < FIndex_X - 1 then
400 s.X := s.X + 1
401 else if s.Y < FIndex_Y - 1 then
402 begin
403 s.X := 0;
404 s.Y := s.Y + 1;
405 end
406 else
407 begin
408 SetStrings(s.Left, s.Top, FEffectStone);
409 FList.Delete(i);
410 inc(i);
411 continue;
412 end;
413 FList[i] := s;
414 inc(i);
415 end;
416 if FList.Count = 0 then
417 begin
418 inc(FTurnIndex);
419 inc(FTurnNumber);
420 FBuffer[FTurnIndex] := FStrings;
421 FBuffer[FTurnIndex].Stone := FEffectStone;
422 Form1.PaintBox1.Repaint;
423 Form1.ChangePlayer;
424 if FGameOver = false then
425 FActive := true
426 end;
427 result := true;
428 end;
429 end;
430
431 function TStoneGrid.NextStone(Stone: TStoneType; var Pos: TPoint): Boolean;
432 var
433 i, j, m, n: integer;
434 begin
435 result := false;
436 n := 0;
437 for i := 0 to bmp_count - 1 do
438 for j := 0 to bmp_count - 1 do
439 if (CalScore(Stone, i, j, m) = true) and ((result = false) or (m < n))
440 then
441 begin
442 if result = false then
443 result := true;
444 n := m;
445 Pos := Point(i, j);
446 end;
447 end;
448
449 procedure TStoneGrid.Paint(Canvas: TCanvas);
450 var
451 k: integer;
452 s: TBitmap;
453 p: TEffectData;
454 begin
455 k := Form1.Size;
456 if FEffectStone = stBlack then
457 s := Form1.Image1.Bitmap
458 else
459 s := Form1.Image2.Bitmap;
460 for p in FList do
461 begin
462 Canvas.DrawBitmap(s, RectF(p.X * 50, p.Y * 50, (p.X + 1) * 50,
463 (p.Y + 1) * 50), RectF(p.Left * k, p.Top * k, (p.Left + 1) * k,
464 (p.Top + 1) * k), 1);
465 end;
466 end;
467
468 procedure TStoneGrid.Pause;
469 begin
470 FActive := false;
471 end;
472
473 procedure TStoneGrid.Restart;
474 begin
475 FActive := true;
476 FGameOver := false;
477 FTurnIndex := FTurnNumber;
478 end;
479
480 procedure TStoneGrid.SetActive(const Value: Boolean);
481 begin
482 if (FGameOver = false) or (Value = false) then
483 FActive := Value;
484 end;
485
486 procedure TStoneGrid.SetStrings(X, Y: integer; const Value: TStoneType);
487 begin
488 if (X >= 0) and (X < bmp_count) and (Y >= 0) and (Y < bmp_count) then
489 FStrings.Strings[X, Y] := Value;
490 end;
491
492 procedure TStoneGrid.SetTurnNumber(const Value: integer);
493 begin
494 if Value > FTurnIndex then
495 FTurnNumber := FTurnIndex
496 else if Value < 0 then
497 FTurnNumber := 0
498 else
499 FTurnNumber := Value;
500 FStrings := FBuffer[FTurnNumber];
501 end;
502
503 procedure TStoneGrid.Start;
504 begin
505 Clear;
506 FActive := true;
507 FGameOver := false;
508 end;
509
510 { TForm1 }
511
512 procedure TForm1.ChangePlayer;
513 var
514 i, j, m, n: integer;
515 s: string;
516 function Execute: Boolean;
517 var
518 i, j: integer;
519 begin
520 for i := 0 to bmp_count - 1 do
521 for j := 0 to bmp_count - 1 do
522 if StoneGrid.CanSetStone(Index.Stone, i, j, false) = true then
523 begin
524 result := true;
525 Exit;
526 end;
527 result := false;
528 end;
529
530 begin
531 s := '';
532 ChMain(s);
533 if Execute = false then
534 begin
535 ChMain(s);
536 if Execute = false then
537 begin
538 m := 0;
539 n := 0;
540 for i := 0 to bmp_count - 1 do
541 for j := 0 to bmp_count - 1 do
542 case StoneGrid[i, j] of
543 stBlack:
544 inc(m);
545 stWhite:
546 inc(n);
547 end;
548 ChMain(s);
549 Caption := '�I����������';
550 if m > n then
551 s := 'Player1 Win:' + #13#10
552 else if m < n then
553 s := 'Player2 Win:' + #13#10
554 else
555 s := 'Draw:' + #13#10;
556 StoneGrid.GameOver;
557 Showmessage(s + '(Player1) ' + m.ToString + #13#10 + '(Player2) ' +
558 n.ToString);
559 end
560 else
561 Caption := s;
562 end
563 else
564 Caption := s;
565 end;
566
567 procedure TForm1.ChMain(var CapStr: string);
568 begin
569 CapStr := (StoneGrid.TurnNumber + 1).ToString + '�����F';
570 if Index = Player1 then
571 begin
572 Index := Player2;
573 CapStr := CapStr + '������������';
574 end
575 else
576 begin
577 Index := Player1;
578 CapStr := CapStr + '������������';
579 end;
580 end;
581
582 procedure TForm1.CompStone;
583 var
584 s: TPoint;
585 begin
586 StoneGrid.Active := false;
587 if StoneGrid.NextStone(Index.Stone, s) = true then
588 begin
589 StoneGrid.CanSetStone(Index.Stone, s.X, s.Y, true, true);
590 PaintBox1.Repaint;
591 end
592 else
593 ChangePlayer;
594 end;
595
596 procedure TForm1.GameStart;
597 begin
598 Index := Player1;
599 StoneGrid.Start;
600 PaintBox1.Repaint;
601 Caption := '1�����F�������n������';
602 end;
603
604 procedure TForm1.MenuItem10Click(Sender: TObject);
605 begin
606 StoneGrid.Restart;
607 end;
608
609 procedure TForm1.MenuItem11Click(Sender: TObject);
610 var
611 i: integer;
612 s: string;
613 begin
614 with StoneGrid do
615 begin
616 i := TurnNumber;
617 if Sender = MenuItem11 then
618 TurnNumber := TurnNumber + 1
619 else
620 TurnNumber := TurnNumber - 1;
621 if (i = TurnNumber) then
622 Exit
623 else
624 Pause;
625 PaintBox1.Repaint;
626 s := '';
627 if ((TurnNumber = 0) and (Index <> Player1)) or
628 (Index.Stone = FBuffer[TurnNumber].Stone) then
629 begin
630 if TurnNumber = 60 then
631 ChangePlayer
632 else
633 begin
634 ChMain(s);
635 Caption := s;
636 end;
637 end
638 else
639 begin
640 ChMain(s);
641 Caption := s;
642 if Index = Player1 then
643 Index := Player2
644 else
645 Index := Player1;
646 end;
647 end;
648 end;
649
650 procedure TForm1.MenuItem2Click(Sender: TObject);
651 begin
652 Timer1.Enabled := false;
653 Timer2.Enabled := false;
654 GameStart;
655 Timer1.Enabled := true;
656 Timer2.Enabled := true;
657 end;
658
659 procedure TForm1.MenuItem4Click(Sender: TObject);
660 begin
661 Close;
662 end;
663
664 procedure TForm1.MenuItem6Click(Sender: TObject);
665 begin
666 Player1.Auto := MenuItem6.IsChecked;
667 Player2.Auto := MenuItem7.IsChecked;
668 end;
669
670 procedure TForm1.MenuItem8Click(Sender: TObject);
671 begin
672 StoneGrid.Pause;
673 end;
674
675 procedure TForm1.PaintBox1Paint(Sender: TObject; Canvas: TCanvas);
676 var
677 i, j: integer;
678 begin
679 if StoneGrid.Active = false then
680 StoneGrid.Paint(Canvas);
681 for i := 0 to bmp_count - 1 do
682 begin
683 for j := 0 to bmp_count - 1 do
684 begin
685 case StoneGrid.Strings[i, j] of
686 stWhite:
687 Canvas.DrawBitmap(Image3.Bitmap, RectF(100, 0, 150, 50),
688 RectF(i * Size, j * Size, (i + 1) * Size, (j + 1) * Size), 1);
689 stBlack:
690 Canvas.DrawBitmap(Image3.Bitmap, RectF(50, 0, 100, 50),
691 RectF(i * Size, j * Size, (i + 1) * Size, (j + 1) * Size), 1);
692 stEffect:
693 continue;
694 else
695 Canvas.DrawBitmap(Image3.Bitmap, RectF(0, 0, 50, 50),
696 RectF(i * Size, j * Size, (i + 1) * Size, (j + 1) * Size), 1);
697 end;
698 Canvas.DrawLine(PointF(0, j * Size), PointF(bmp_count * Size,
699 j * Size), 1);
700 end;
701 Canvas.DrawLine(PointF(i * Size, 0), PointF(i * Size, Size * bmp_count), 1);
702 end;
703 Canvas.DrawLine(PointF(bmp_count * Size, 0), PointF(bmp_count * Size,
704 bmp_count * Size), 1);
705 Canvas.DrawLine(PointF(0, bmp_count * Size), PointF(bmp_count * Size,
706 bmp_count * Size), 1);
707 end;
708
709 procedure TForm1.PaintBox1Resize(Sender: TObject);
710 begin
711 Size := Min(ClientWidth, ClientHeight) div bmp_count;
712 end;
713
714 procedure TForm1.FormCreate(Sender: TObject);
715 begin
716 ClientWidth := 400;
717 ClientHeight := 400;
718 StoneGrid := TStoneGrid.Create;
719 StoneGrid.ImageCount(6, 5);
720 Player1 := TPlayer.Create;
721 Player2 := TPlayer.Create;
722 Player1.Stone := stBlack;
723 Player2.Stone := stWhite;
724 Player2.Auto := true;
725 with PaintBox1.Canvas do
726 begin
727 StrokeDash := TStrokeDash.Solid;
728 Stroke.Color := TAlphaColors.Black;
729 StrokeThickness := 3;
730 end;
731 PaintBox1Resize(Sender);
732 GameStart;
733 end;
734
735 procedure TForm1.FormDestroy(Sender: TObject);
736 begin
737 StoneGrid.Free;
738 Player1.Free;
739 Player2.Free;
740 end;
741
742 procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
743 Shift: TShiftState; X, Y: Single);
744 begin
745 PaintBox1Tap(Sender, PointF(X, Y));
746 end;
747
748 procedure TForm1.Timer1Timer(Sender: TObject);
749 begin
750 if (StoneGrid.Active = true) and (Index.Auto = true) then
751 CompStone;
752 end;
753
754 procedure TForm1.Timer2Timer(Sender: TObject);
755 begin
756 if (StoneGrid.Active = false) and (StoneGrid.ListExecute = true) then
757 PaintBox1.Repaint;
758 end;
759
760 procedure TForm1.FormResize(Sender: TObject);
761 begin
762 Size := Min(ClientWidth, ClientHeight) div bmp_count;
763 PaintTo(Canvas);
764 end;
765
766 procedure TForm1.PaintBox1Tap(Sender: TObject; const Point: TPointF);
767 begin
768 if Index.Auto = false then
769 begin
770 StoneGrid.Restart;
771 if (StoneGrid.Active = true) and
772 (StoneGrid.CanSetStone(Index.Stone, Floor(Point.X / Size),
773 Floor(Point.Y / Size), true, true) = true) then
774 begin
775 StoneGrid.Active := false;
776 PaintBox1.Repaint;
777 StoneGrid.Active := true;
778 end;
779 end;
780 end;
781
782 end.

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26