Changeset 29 for trunk/UGame.pas
- Timestamp:
- Oct 6, 2019, 9:53:39 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/UGame.pas
r28 r29 36 36 procedure Clear; 37 37 procedure ClearMerged; 38 function GetValueSum: Integer; 38 39 function GetHighestTileValue: Integer; 39 40 function GetEmptyTilesCount: Integer; … … 53 54 FMoving: Boolean; 54 55 FOnChange: TNotifyEvent; 56 FOnGameOver: TNotifyEvent; 57 FOnWin: TNotifyEvent; 55 58 FRunning: Boolean; 56 59 FScore: Integer; 57 60 FCanUndo: Boolean; 58 61 FBoardUndo: TBoard; 59 function CanMoveDirection(Direction: TDirection): Boolean;60 62 function GetTileColor(Value: Integer): TColor; 61 63 procedure SetScore(AValue: Integer); … … 73 75 function CanUndo: Boolean; 74 76 procedure Undo; 77 function CanMergeDirection(Direction: TDirection): Boolean; 78 function CanMoveDirection(Direction: TDirection): Boolean; 75 79 function CanMove: Boolean; 76 80 procedure Assign(Source: TGame); … … 78 82 procedure Render(Canvas: TCanvas; CanvasSize: TPoint); 79 83 procedure MoveAll(Direction: TDirection); 84 procedure MoveAllAndUpdate(Direction: TDirection); 80 85 procedure MoveTile(SourceTile, TargetTile: TTile); 81 86 function IsValidPos(Pos: TPoint): Boolean; … … 87 92 property Running: Boolean read FRunning write FRunning; 88 93 property OnChange: TNotifyEvent read FOnChange write FOnChange; 94 property OnWin: TNotifyEvent read FOnWin write FOnWin; 95 property OnGameOver: TNotifyEvent read FOnGameOver write FOnGameOver; 89 96 property Moving: Boolean read FMoving; 97 end; 98 99 TGames = class(TFPGObjectList<TGame>) 90 100 end; 91 101 … … 94 104 (X: -1; Y: 0), (X: 0; Y: -1), (X: 1; Y: 0), (X: 0; Y: 1) 95 105 ); 106 DirectionText: array[TDirection] of string = ('Left', 'Up', 'Right', 'Down'); 96 107 97 108 resourcestring 98 SGameOverCaption = 'Lost';99 SGameOverMessage = 'Game over!';100 SWinCaption = 'Win';101 SWinMessage = 'You reached %d and won! You can continue to play to get higher score.';102 109 SScore = 'Score'; 103 110 STopScore = 'Top score'; … … 212 219 end; 213 220 221 function TBoard.GetValueSum: Integer; 222 var 223 X, Y: Integer; 224 begin 225 Result := 0; 226 for Y := 0 to Size.Y - 1 do 227 for X := 0 to Size.X - 1 do 228 Inc(Result, Tiles[Y, X].Value); 229 end; 230 214 231 function TBoard.GetEmptyTilesCount: Integer; 215 232 var … … 260 277 procedure TGame.GameOver; 261 278 begin 262 if Running then MessageDlg(SGameOverCaption, SGameOverMessage, mtInformation, [mbOK], 0);279 if Running and Assigned(FOnGameOver) then FOnGameOver(Self); 263 280 Running := False; 264 281 end; … … 266 283 procedure TGame.Win; 267 284 begin 268 MessageDlg(SWinCaption, Format(SWinMessage, [WinScore]), mtInformation, [mbOk], 0);285 if Assigned(FOnWin) then FOnWin(Self); 269 286 end; 270 287 … … 293 310 procedure TGame.Assign(Source: TGame); 294 311 begin 295 FScore := Source.FScore; 312 Board.Assign(Source.Board); 313 FBoardUndo.Assign(Source.FBoardUndo); 314 FCanUndo := Source.FCanUndo; 296 315 TopScore := Source.TopScore; 297 316 AnimationDuration := Source.AnimationDuration; 298 Board.Assign(Source.Board); 317 WinScore := Source.WinScore; 318 UndoEnabled := Source.UndoEnabled; 319 FScore := Source.FScore; 320 FRunning := Source.FRunning; 299 321 end; 300 322 … … 412 434 FRunning := CanMove; 413 435 DoChange; 436 end; 437 end; 438 439 function TGame.CanMergeDirection(Direction: TDirection): Boolean; 440 var 441 StartPoint: TPoint; 442 AreaSize: TPoint; 443 Increment: TPoint; 444 P: TPoint; 445 PNew: TPoint; 446 PI: TPoint; 447 I: Integer; 448 begin 449 Result := False; 450 case Direction of 451 drLeft: begin 452 StartPoint := Point(1, 0); 453 AreaSize := Point(Board.Size.X - 2, Board.Size.Y - 1); 454 Increment := Point(1, 1); 455 end; 456 drUp: begin 457 StartPoint := Point(0, 1); 458 AreaSize := Point(Board.Size.X - 1, Board.Size.Y - 2); 459 Increment := Point(1, 1); 460 end; 461 drRight: begin 462 StartPoint := Point(Board.Size.X - 2, 0); 463 AreaSize := Point(Board.Size.X - 2, Board.Size.Y - 1); 464 Increment := Point(-1, 1); 465 end; 466 drDown: begin 467 StartPoint := Point(0, Board.Size.Y - 2); 468 AreaSize := Point(Board.Size.X - 1, Board.Size.Y - 2); 469 Increment := Point(1, -1); 470 end; 471 end; 472 473 for I := 0 to Max(Board.Size.X, Board.Size.Y) - 1 do begin 474 PI.Y := 0; 475 while PI.Y <= AreaSize.Y do begin 476 PI.X := 0; 477 while PI.X <= AreaSize.X do begin 478 P := Point(StartPoint.X + PI.X * Increment.X, StartPoint.Y + PI.Y * Increment.Y); 479 PNew.X := P.X + DirectionDiff[Direction].X; 480 PNew.Y := P.Y + DirectionDiff[Direction].Y; 481 if IsValidPos(PNew) then begin 482 if (Board.Tiles[PNew.Y, PNew.X].Value = 0) then begin 483 Board.Tiles[PNew.Y, PNew.X].Value := Board.Tiles[P.Y, P.X].Value; 484 Board.Tiles[P.Y, P.X].Value := 0; 485 end else 486 if (Board.Tiles[P.Y, P.X].Value <> 0) then begin 487 if Board.Tiles[PNew.Y, PNew.X].Value = Board.Tiles[P.Y, P.X].Value then begin 488 Result := True; 489 Break; 490 end; 491 end; 492 P.X := PNew.X; 493 P.Y := PNew.Y; 494 PNew.X := P.X + DirectionDiff[Direction].X; 495 PNew.Y := P.Y + DirectionDiff[Direction].Y; 496 end; 497 Inc(PI.X); 498 end; 499 if Result then Break; 500 Inc(PI.Y); 501 end; 414 502 end; 415 503 end; … … 490 578 Time: TDateTime; 491 579 Part: Double; 492 HighestValue: Integer;493 580 begin 494 581 if not CanMoveDirection(Direction) then Exit; 495 582 FMoving := True; 496 HighestValue := Board.GetHighestTileValue;497 583 FBoardUndo.Assign(Board); 498 584 FCanUndo := True; … … 596 682 DoChange; 597 683 end; 598 599 // Update state after move 684 FMoving := False; 685 end; 686 687 procedure TGame.MoveAllAndUpdate(Direction: TDirection); 688 var 689 HighestValue: Integer; 690 begin 691 HighestValue := Board.GetHighestTileValue; 692 MoveAll(Direction); 600 693 FillRandomTile; 601 694 if not CanMove and (Board.GetEmptyTilesCount = 0) then … … 603 696 if (HighestValue < WinScore) and 604 697 (Board.GetHighestTileValue >= WinScore) then Win; 605 606 FMoving := False;607 698 end; 608 699
Note:
See TracChangeset
for help on using the changeset viewer.