Changeset 20 for trunk/UGame.pas
- Timestamp:
- Oct 5, 2019, 2:00:50 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/UGame.pas
r19 r20 55 55 FRunning: Boolean; 56 56 FScore: Integer; 57 FCanUndo: Boolean; 58 FBoardUndo: TBoard; 59 function CanMoveDirection(Direction: TDirection): Boolean; 57 60 function GetTileColor(Value: Integer): TColor; 58 61 procedure SetScore(AValue: Integer); 59 62 procedure DoChange; 60 63 procedure RenderTile(Canvas: TCanvas; Tile: TTile; TileRect: TRect); 64 procedure GameOver; 65 procedure Win; 66 function FillRandomTile: Integer; 61 67 public 62 68 Board: TBoard; 63 69 TopScore: Integer; 64 70 AnimationDuration: Integer; 65 Won: Boolean; 66 procedure GameOver; 67 procedure Win; 68 function FillRandomTile: Integer; 71 WinScore: Integer; 72 function CanUndo: Boolean; 73 procedure Undo; 69 74 function CanMove: Boolean; 70 75 procedure Assign(Source: TGame); … … 146 151 CurrentContext := RegContext; 147 152 153 WriteInteger('SizeX', Size.X); 154 WriteInteger('SizeY', Size.Y); 148 155 Value := ''; 149 156 for Y := 0 to Size.Y - 1 do begin … … 171 178 CurrentContext := RegContext; 172 179 180 Size := Point(ReadIntegerWithDefault('SizeX', 4), ReadIntegerWithDefault('SizeY', 4)); 173 181 Items := TStringList.Create; 174 182 Items.Delimiter := ','; … … 257 265 procedure TGame.Win; 258 266 begin 259 if not Won then begin 260 Won := True; 261 if MessageDlg(SWinCaption, SWinMessage, mtConfirmation, 262 mbYesNo, 0) = mrNo then begin 263 Running := False; 264 end; 267 if MessageDlg(SWinCaption, SWinMessage, mtConfirmation, 268 mbYesNo, 0) = mrNo then begin 269 Running := False; 265 270 end; 266 271 end; … … 281 286 282 287 function TGame.CanMove: Boolean; 283 var 284 TempGame: TGame; 285 begin 286 Result := False; 287 TempGame := TGame.Create; 288 try 289 TempGame.Assign(Self); 290 TempGame.AnimationDuration := 0; 291 Result := TempGame.MoveAll(drDown) > 0; 292 if Result then Exit; 293 Result := TempGame.MoveAll(drUp) > 0; 294 if Result then Exit; 295 Result := TempGame.MoveAll(drRight) > 0; 296 if Result then Exit; 297 Result := TempGame.MoveAll(drLeft) > 0; 298 finally 299 TempGame.Free; 300 end; 288 begin 289 Result := CanMoveDirection(drLeft) or CanMoveDirection(drRight) or 290 CanMoveDirection(drUp) or CanMoveDirection(drDown); 301 291 end; 302 292 303 293 procedure TGame.Assign(Source: TGame); 304 var305 X, Y: Integer;306 294 begin 307 295 FScore := Source.FScore; 308 296 TopScore := Source.TopScore; 309 297 AnimationDuration := Source.AnimationDuration; 310 Won := Source.Won;311 298 Board.Assign(Source.Board); 312 299 end; … … 316 303 I: Integer; 317 304 begin 305 FCanUndo := False; 318 306 Board.Clear; 319 307 Score := 0; 320 Won := False;321 308 Running := True; 322 309 for I := 0 to 1 do FillRandomTile; … … 413 400 end; 414 401 402 function TGame.CanUndo: Boolean; 403 begin 404 Result := FCanUndo; 405 end; 406 407 procedure TGame.Undo; 408 begin 409 if CanUndo then begin 410 Board.Assign(FBoardUndo); 411 FCanUndo := False; 412 FRunning := CanMove; 413 DoChange; 414 end; 415 end; 416 417 function TGame.CanMoveDirection(Direction: TDirection): Boolean; 418 var 419 StartPoint: TPoint; 420 AreaSize: TPoint; 421 Increment: TPoint; 422 P: TPoint; 423 PNew: TPoint; 424 PI: TPoint; 425 begin 426 Result := False; 427 case Direction of 428 drLeft: begin 429 StartPoint := Point(1, 0); 430 AreaSize := Point(Board.Size.X - 2, Board.Size.Y - 1); 431 Increment := Point(1, 1); 432 end; 433 drUp: begin 434 StartPoint := Point(0, 1); 435 AreaSize := Point(Board.Size.X - 1, Board.Size.Y - 2); 436 Increment := Point(1, 1); 437 end; 438 drRight: begin 439 StartPoint := Point(Board.Size.X - 2, 0); 440 AreaSize := Point(Board.Size.X - 2, Board.Size.Y - 1); 441 Increment := Point(-1, 1); 442 end; 443 drDown: begin 444 StartPoint := Point(0, Board.Size.Y - 2); 445 AreaSize := Point(Board.Size.X - 1, Board.Size.Y - 2); 446 Increment := Point(1, -1); 447 end; 448 end; 449 450 PI.Y := 0; 451 while PI.Y <= AreaSize.Y do begin 452 PI.X := 0; 453 while PI.X <= AreaSize.X do begin 454 P := Point(StartPoint.X + PI.X * Increment.X, StartPoint.Y + PI.Y * Increment.Y); 455 PNew.X := P.X + DirectionDiff[Direction].X; 456 PNew.Y := P.Y + DirectionDiff[Direction].Y; 457 if IsValidPos(PNew) then begin 458 if (Board.Tiles[P.Y, P.X].Value <> 0) then begin 459 if (Board.Tiles[PNew.Y, PNew.X].Value = 0) or 460 (Board.Tiles[PNew.Y, PNew.X].Value = Board.Tiles[P.Y, P.X].Value) then begin 461 Result := True; 462 Break; 463 end; 464 end; 465 P.X := PNew.X; 466 P.Y := PNew.Y; 467 PNew.X := P.X + DirectionDiff[Direction].X; 468 PNew.Y := P.Y + DirectionDiff[Direction].Y; 469 end; 470 Inc(PI.X); 471 end; 472 if Result then Break; 473 Inc(PI.Y); 474 end; 475 end; 415 476 416 477 function TGame.MoveAll(Direction: TDirection): Integer; … … 430 491 Time: TDateTime; 431 492 Part: Double; 493 HighestValue: Integer; 432 494 begin 433 495 FMoving := True; 496 HighestValue := Board.GetHighestTileValue; 497 FBoardUndo.Assign(Board); 498 FCanUndo := True; 434 499 //Diff := DirectionDiff[Direction]; 435 500 case Direction of … … 535 600 end; 536 601 Result := MovedCount; 602 603 // Update state after move 604 if MovedCount > 0 then FillRandomTile; 605 if not CanMove and (Board.GetEmptyTilesCount = 0) then 606 GameOver; 607 if (HighestValue < WinScore) and 608 (Board.GetHighestTileValue >= WinScore) then Win; 609 537 610 FMoving := False; 538 611 end; … … 560 633 WriteInteger('TopScore', TopScore); 561 634 WriteInteger('AnimationDuration', AnimationDuration); 562 WriteInteger('SizeX', Board.Size.X);563 WriteInteger('SizeY', Board.Size.Y);564 635 WriteInteger('Score', Score); 565 636 WriteBool('GameRunning', FRunning); 566 WriteBool(' Won', Won);637 WriteBool('CanUndo', FCanUndo); 567 638 finally 568 639 Free; 569 640 end; 570 Board.SaveToRegistry(RegContext); 641 FBoardUndo.SaveToRegistry(TRegistryContext.Create(RegContext.RootKey, RegContext.Key + '\BoardUndo')); 642 Board.SaveToRegistry(TRegistryContext.Create(RegContext.RootKey, RegContext.Key + '\Board')); 571 643 end; 572 644 … … 576 648 try 577 649 CurrentContext := RegContext; 578 Board.Size := Point(ReadIntegerWithDefault('SizeX', 4), ReadIntegerWithDefault('SizeY', 4));579 650 AnimationDuration := ReadIntegerWithDefault('AnimationDuration', 30); 580 651 TopScore := ReadIntegerWithDefault('TopScore', 0); 581 652 Score := ReadIntegerWithDefault('Score', 0); 582 653 FRunning := ReadBoolWithDefault('GameRunning', False); 583 Won := ReadBoolWithDefault('Won', False);654 FCanUndo := ReadBoolWithDefault('CanUndo', False); 584 655 finally 585 656 Free; 586 657 end; 587 Board.LoadFromRegistry(RegContext); 658 FBoardUndo.LoadFromRegistry(TRegistryContext.Create(RegContext.RootKey, RegContext.Key + '\BoardUndo')); 659 Board.LoadFromRegistry(TRegistryContext.Create(RegContext.RootKey, RegContext.Key + '\Board')); 588 660 end; 589 661 … … 591 663 begin 592 664 AnimationDuration := 30; 665 WinScore := 2048; 593 666 Board := TBoard.Create; 667 FBoardUndo := TBoard.Create; 594 668 end; 595 669 596 670 destructor TGame.Destroy; 597 671 begin 672 FreeAndNil(FBoardUndo); 598 673 FreeAndNil(Board); 599 674 inherited;
Note:
See TracChangeset
for help on using the changeset viewer.