- Timestamp:
- Oct 12, 2019, 10:47:02 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Forms/UFormComputer.pas
r29 r31 13 13 TGameTry = class 14 14 Game: TGame; 15 Moves: array of T Direction;15 Moves: array of TMoveDirection; 16 16 constructor Create; 17 17 destructor Destroy; override; … … 58 58 function TGameTry.GetFitness: Double; 59 59 const 60 DirWeight: array[T Direction] of Double = (0.25, -10000, 0.5, 0.75);60 DirWeight: array[TMoveDirection] of Double = (0, 0.25, -10000, 0.5, 0.75); 61 61 var 62 62 I: Integer; … … 221 221 procedure TFormComputer.TryAllDirections(GameTries: TGameTries; GameTry: TGameTry); 222 222 var 223 Direction: T Direction;223 Direction: TMoveDirection; 224 224 NewTry: TGameTry; 225 225 begin 226 for Direction := Low(T Direction) to High(TDirection) do begin226 for Direction := Low(TMoveDirection) to High(TMoveDirection) do begin 227 227 if GameTry.Game.CanMoveDirection(Direction) then begin 228 228 NewTry := TGameTry.Create; -
trunk/Forms/UFormMain.lfm
r29 r31 37 37 Action = Core.AComputer 38 38 end 39 object MenuItem5: TMenuItem 40 Action = Core.AHistory 41 end 39 42 end 40 43 object MenuItemHelp: TMenuItem -
trunk/Forms/UFormMain.pas
r29 r31 19 19 MenuItem3: TMenuItem; 20 20 MenuItem4: TMenuItem; 21 MenuItem5: TMenuItem; 21 22 MenuItemTools: TMenuItem; 22 23 MenuItemNew: TMenuItem; -
trunk/Forms/UFormNew.lfm
r28 r31 8 8 ClientWidth = 487 9 9 DesignTimePPI = 144 10 OnClose = FormClose 10 11 OnCreate = FormCreate 12 OnShow = FormShow 11 13 LCLVersion = '2.0.2.0' 12 14 object Label1: TLabel -
trunk/Forms/UFormNew.pas
r28 r31 19 19 ComboBoxSize: TComboBox; 20 20 Label1: TLabel; 21 procedure FormClose(Sender: TObject; var CloseAction: TCloseAction); 21 22 procedure FormCreate(Sender: TObject); 23 procedure FormShow(Sender: TObject); 22 24 private 23 25 … … 44 46 end; 45 47 48 procedure TFormNew.FormShow(Sender: TObject); 49 begin 50 Core.PersistentForm1.Load(Self); 51 end; 52 53 procedure TFormNew.FormClose(Sender: TObject; var CloseAction: TCloseAction); 54 begin 55 Core.PersistentForm1.Save(Self); 56 end; 57 46 58 procedure TFormNew.Load(Game: TGame); 47 59 begin -
trunk/Game2048.lpi
r29 r31 82 82 </Item2> 83 83 </RequiredPackages> 84 <Units Count=" 9">84 <Units Count="10"> 85 85 <Unit0> 86 86 <Filename Value="Game2048.lpr"/> … … 140 140 <ResourceBaseClass Value="Form"/> 141 141 </Unit8> 142 <Unit9> 143 <Filename Value="Forms/UFormHistory.pas"/> 144 <IsPartOfProject Value="True"/> 145 <ComponentName Value="FormHistory"/> 146 <HasResources Value="True"/> 147 <ResourceBaseClass Value="Form"/> 148 </Unit9> 142 149 </Units> 143 150 </ProjectOptions> -
trunk/Game2048.lpr
r29 r31 9 9 Interfaces, SysUtils,// this includes the LCL widgetset 10 10 Forms, UGame, Common, UFormSettings, UFormMain, UCore, UFormHelp, 11 UFormComputer 11 UFormComputer, UFormHistory 12 12 { you can add units after this }; 13 13 -
trunk/Languages/Game2048.cs.po
r29 r31 32 32 msgstr "Nápověda" 33 33 34 #: tcore.ahistory.caption 35 msgctxt "tcore.ahistory.caption" 36 msgid "Moves history" 37 msgstr "Historie pohybů" 38 34 39 #: tcore.anew.caption 35 40 msgctxt "tcore.anew.caption" … … 81 86 msgstr "Nápověda" 82 87 88 #: tformhistory.caption 89 msgctxt "tformhistory.caption" 90 msgid "Moves history" 91 msgstr "Historie pohybů" 92 83 93 #: tformmain.caption 84 94 msgid "2048" -
trunk/Languages/Game2048.po
r29 r31 22 22 msgstr "" 23 23 24 #: tcore.ahistory.caption 25 msgctxt "tcore.ahistory.caption" 26 msgid "Moves history" 27 msgstr "" 28 24 29 #: tcore.anew.caption 25 30 msgctxt "tcore.anew.caption" … … 71 76 msgstr "" 72 77 78 #: tformhistory.caption 79 msgctxt "tformhistory.caption" 80 msgid "Moves history" 81 msgstr "" 82 73 83 #: tformmain.caption 74 84 msgid "2048" -
trunk/UCore.lfm
r29 r31 76 76 ShortCut = 115 77 77 end 78 object AHistory: TAction 79 Caption = 'Moves history' 80 OnExecute = AHistoryExecute 81 end 78 82 end 79 83 end -
trunk/UCore.lrj
r29 r31 6 6 {"hash":378031,"name":"tcore.aundo.caption","sourcebytes":[85,110,100,111],"value":"Undo"}, 7 7 {"hash":322608,"name":"tcore.ahelp.caption","sourcebytes":[72,101,108,112],"value":"Help"}, 8 {"hash":1113,"name":"tcore.acomputer.caption","sourcebytes":[65,73],"value":"AI"} 8 {"hash":1113,"name":"tcore.acomputer.caption","sourcebytes":[65,73],"value":"AI"}, 9 {"hash":191263657,"name":"tcore.ahistory.caption","sourcebytes":[77,111,118,101,115,32,104,105,115,116,111,114,121],"value":"Moves history"} 9 10 ]} -
trunk/UCore.pas
r29 r31 16 16 AAbout: TAction; 17 17 AComputer: TAction; 18 AHistory: TAction; 18 19 AHelp: TAction; 19 20 AUndo: TAction; … … 30 31 procedure AExitExecute(Sender: TObject); 31 32 procedure AHelpExecute(Sender: TObject); 33 procedure AHistoryExecute(Sender: TObject); 32 34 procedure ANewExecute(Sender: TObject); 33 35 procedure ASettingsExecute(Sender: TObject); … … 54 56 55 57 uses 56 UFormMain, UFormSettings, UFormAbout, UFormNew, UFormHelp, UFormComputer; 58 UFormMain, UFormSettings, UFormAbout, UFormNew, UFormHelp, UFormComputer, 59 UFormHistory; 57 60 58 61 resourcestring … … 131 134 end; 132 135 136 procedure TCore.AHistoryExecute(Sender: TObject); 137 begin 138 FormHistory := TFormHistory.Create(nil); 139 try 140 FormHistory.ShowModal; 141 finally 142 FreeAndNil(FormHistory); 143 end; 144 end; 145 133 146 procedure TCore.ANewExecute(Sender: TObject); 134 147 begin -
trunk/UGame.pas
r30 r31 10 10 11 11 type 12 TGame = class; 13 TMoveDirection = (drNone, drLeft, drUp, drRight, drDown); 12 14 13 15 { TTile } 14 16 15 17 TTile = class 18 Index: TPoint; 16 19 Value: Integer; 17 20 NewValue: Integer; … … 32 35 function Create(P1, P2: TPoint): TArea; overload; 33 36 function Create(X1, Y1, X2, Y2: Integer): TArea; overload; 37 end; 38 39 { THistoryMove } 40 41 THistoryMove = class 42 Direction: TMoveDirection; 43 NewItemPos: TPoint; 44 NewItemValue: Integer; 45 procedure SaveToRegistry(RegContext: TRegistryContext); 46 procedure LoadFromRegistry(RegContext: TRegistryContext); 47 end; 48 49 { THistoryMoves } 50 51 THistoryMoves = class(TFPGObjectList<THistoryMove>) 52 procedure SaveToRegistry(RegContext: TRegistryContext); 53 procedure LoadFromRegistry(RegContext: TRegistryContext); 54 end; 55 56 { THistory } 57 58 THistory = class 59 Game: TGame; 60 Moves: THistoryMoves; 61 InitialTilesPos: array of TPoint; 62 procedure GetStep(GameStep: TGame; Step: Integer); 63 constructor Create; 64 destructor Destroy; override; 65 procedure SaveToRegistry(RegContext: TRegistryContext); 66 procedure LoadFromRegistry(RegContext: TRegistryContext); 34 67 end; 35 68 … … 55 88 end; 56 89 57 TDirection = (drLeft, drUp, drRight, drDown);58 59 90 { TGame } 60 91 … … 75 106 procedure GameOver; 76 107 procedure Win; 77 function FillRandomTile(Value4Change: Double = 0.1): Integer;78 function GetMoveArea(Direction: T Direction): TArea;108 function FillRandomTile(Value4Change: Double = 0.1): TTile; 109 function GetMoveArea(Direction: TMoveDirection): TArea; 79 110 public 80 111 Board: TBoard; … … 83 114 WinScore: Integer; 84 115 UndoEnabled: Boolean; 116 History: THistory; 85 117 function CanUndo: Boolean; 86 118 procedure Undo; 87 function CanMergeDirection(Direction: T Direction): Boolean;88 function CanMoveDirection(Direction: T Direction): Boolean;119 function CanMergeDirection(Direction: TMoveDirection): Boolean; 120 function CanMoveDirection(Direction: TMoveDirection): Boolean; 89 121 function CanMove: Boolean; 90 122 procedure Assign(Source: TGame); 91 123 procedure New; 92 124 procedure Render(Canvas: TCanvas; CanvasSize: TPoint); 93 procedure MoveAll(Direction: T Direction);94 procedure MoveAllAndUpdate(Direction: T Direction);125 procedure MoveAll(Direction: TMoveDirection); 126 procedure MoveAllAndUpdate(Direction: TMoveDirection); 95 127 procedure MoveTile(SourceTile, TargetTile: TTile); 96 128 function IsValidPos(Pos: TPoint): Boolean; … … 111 143 112 144 const 113 DirectionDiff: array[T Direction] of TPoint = (114 (X: -1; Y: 0), (X: 0; Y: -1), (X: 1; Y: 0), (X: 0; Y: 1)145 DirectionDiff: array[TMoveDirection] of TPoint = ( 146 (X: 0; Y: 0), (X: -1; Y: 0), (X: 0; Y: -1), (X: 1; Y: 0), (X: 0; Y: 1) 115 147 ); 116 DirectionText: array[T Direction] of string = ('Left', 'Up', 'Right', 'Down');148 DirectionText: array[TMoveDirection] of string = ('None', 'Left', 'Up', 'Right', 'Down'); 117 149 118 150 resourcestring … … 121 153 122 154 implementation 155 156 { THistoryMoves } 157 158 procedure THistoryMoves.SaveToRegistry(RegContext: TRegistryContext); 159 var 160 I: Integer; 161 begin 162 with TRegistryEx.Create do 163 try 164 CurrentContext := RegContext; 165 WriteInteger('Count', Count); 166 for I := 0 to Count - 1 do begin 167 Items[I].SaveToRegistry(TRegistryContext.Create(RegContext.RootKey, RegContext.Key + '/' + IntToStr(I))); 168 end; 169 finally 170 Free; 171 end; 172 end; 173 174 procedure THistoryMoves.LoadFromRegistry(RegContext: TRegistryContext); 175 var 176 I: Integer; 177 C: Integer; 178 HistoryMove: THistoryMove; 179 begin 180 with TRegistryEx.Create do 181 try 182 CurrentContext := RegContext; 183 C := ReadIntegerWithDefault('Count', 0); 184 for I := 0 to C - 1 do begin 185 HistoryMove := THistoryMove.Create; 186 Add(HistoryMove); 187 HistoryMove.LoadFromRegistry(TRegistryContext.Create(RegContext.RootKey, RegContext.Key + '/' + IntToStr(I))); 188 end; 189 finally 190 Free; 191 end; 192 end; 193 194 { THistoryMove } 195 196 procedure THistoryMove.SaveToRegistry(RegContext: TRegistryContext); 197 begin 198 with TRegistryEx.Create do 199 try 200 CurrentContext := RegContext; 201 WriteInteger('Direction', Integer(Direction)); 202 WriteInteger('NewItemPosX', NewItemPos.X); 203 WriteInteger('NewItemPosY', NewItemPos.Y); 204 WriteInteger('NewItemValue', NewItemValue); 205 finally 206 Free; 207 end; 208 end; 209 210 procedure THistoryMove.LoadFromRegistry(RegContext: TRegistryContext); 211 begin 212 with TRegistryEx.Create do 213 try 214 CurrentContext := RegContext; 215 Direction := TMoveDirection(ReadIntegerWithDefault('Direction', Integer(drNone))); 216 NewItemPos := Point(ReadIntegerWithDefault('NewItemPosX', 0), 217 ReadIntegerWithDefault('NewItemPosY', 0)); 218 NewItemValue := ReadIntegerWithDefault('NewItemValue', 0); 219 finally 220 Free; 221 end; 222 end; 223 224 { THistory } 225 226 procedure THistory.GetStep(GameStep: TGame; Step: Integer); 227 var 228 I: Integer; 229 begin 230 GameStep.Board.Size := Game.Board.Size; 231 GameStep.Board.Clear; 232 GameStep.Score := 0; 233 for I := 0 to Length(InitialTilesPos) - 1 do 234 GameStep.Board.Tiles[InitialTilesPos[I].Y, InitialTilesPos[I].X].Value := 2; 235 for I := 0 to Step - 1 do 236 with Moves[I] do begin 237 GameStep.MoveAll(Direction); 238 if GameStep.Board.Tiles[NewItemPos.Y, NewItemPos.X].Value = 0 then 239 GameStep.Board.Tiles[NewItemPos.Y, NewItemPos.X].Value := NewItemValue 240 else raise Exception.Create('Tile should be empty'); 241 end; 242 end; 243 244 constructor THistory.Create; 245 begin 246 Moves := THistoryMoves.Create; 247 end; 248 249 destructor THistory.Destroy; 250 begin 251 FreeAndNil(Moves); 252 inherited Destroy; 253 end; 254 255 procedure THistory.SaveToRegistry(RegContext: TRegistryContext); 256 var 257 I: Integer; 258 begin 259 with TRegistryEx.Create do 260 try 261 CurrentContext := TRegistryContext.Create(RegContext.RootKey, RegContext.Key + '\InitialTilesPos'); 262 WriteInteger('Count', Length(InitialTilesPos)); 263 for I := 0 to Length(InitialTilesPos) - 1 do begin 264 WriteInteger('X' + IntToStr(I), InitialTilesPos[I].X); 265 WriteInteger('Y' + IntToStr(I), InitialTilesPos[I].Y); 266 end; 267 finally 268 Free; 269 end; 270 Moves.SaveToRegistry(RegContext); 271 end; 272 273 procedure THistory.LoadFromRegistry(RegContext: TRegistryContext); 274 var 275 I: Integer; 276 begin 277 with TRegistryEx.Create do 278 try 279 CurrentContext := TRegistryContext.Create(RegContext.RootKey, RegContext.Key + '\InitialTilesPos'); 280 SetLength(InitialTilesPos, ReadIntegerWithDefault('Count', 0)); 281 for I := 0 to Length(InitialTilesPos) - 1 do begin 282 InitialTilesPos[I] := Point(ReadIntegerWithDefault('X' + IntToStr(I), 0), 283 ReadIntegerWithDefault('Y' + IntToStr(I), 0)); 284 end; 285 finally 286 Free; 287 end; 288 Moves.LoadFromRegistry(RegContext); 289 end; 123 290 124 291 { TArea } … … 154 321 SetLength(Tiles, FSize.Y, FSize.X); 155 322 for Y := 0 to FSize.Y - 1 do 156 for X := 0 to FSize.X - 1 do 323 for X := 0 to FSize.X - 1 do begin 157 324 Tiles[Y, X] := TTile.Create; 325 Tiles[Y, X].Index := Point(X, Y); 326 end; 158 327 end; 159 328 … … 228 397 end; 229 398 end; 399 Lines.Free; 400 Items.Free; 230 401 finally 231 402 Free; … … 315 486 end; 316 487 317 function TGame.FillRandomTile(Value4Change: Double = 0.1): Integer;488 function TGame.FillRandomTile(Value4Change: Double = 0.1): TTile; 318 489 var 319 490 EmptyTiles: TTiles; 320 491 NewValue: Integer; 321 492 begin 322 Result := 0;493 Result := nil; 323 494 EmptyTiles := TTiles.Create(False); 324 495 Board.GetEmptyTiles(EmptyTiles); 325 496 if EmptyTiles.Count > 0 then begin 326 497 if Random < Value4Change then NewValue := 4 else NewValue := 2; 327 EmptyTiles[Random(EmptyTiles.Count)].Value := NewValue;328 Result := 1;498 Result := EmptyTiles[Random(EmptyTiles.Count)]; 499 Result.Value := NewValue; 329 500 end; 330 501 EmptyTiles.Free; 331 502 end; 332 503 333 function TGame.GetMoveArea(Direction: T Direction): TArea;504 function TGame.GetMoveArea(Direction: TMoveDirection): TArea; 334 505 begin 335 506 case Direction of … … 371 542 var 372 543 I: Integer; 544 NewTile: TTile; 373 545 begin 374 546 FCanUndo := False; … … 376 548 Score := 0; 377 549 Running := True; 378 for I := 0 to 1 do FillRandomTile(0); 550 with History do begin 551 Moves.Clear; 552 553 SetLength(InitialTilesPos, 0); 554 for I := 0 to 1 do begin 555 NewTile := FillRandomTile(0); 556 SetLength(InitialTilesPos, Length(InitialTilesPos) + 1); 557 InitialTilesPos[Length(InitialTilesPos) - 1] := NewTile.Index; 558 end; 559 end; 379 560 DoChange; 380 561 end; … … 484 665 end; 485 666 486 function TGame.CanMergeDirection(Direction: T Direction): Boolean;667 function TGame.CanMergeDirection(Direction: TMoveDirection): Boolean; 487 668 var 488 669 P: TPoint; … … 495 676 for I := 0 to Max(Board.Size.X, Board.Size.Y) - 1 do begin 496 677 P := Area.P1; 497 while P.Y <> Area.P2.Y do begin678 while P.Y <> Area.P2.Y + Area.Increment.Y do begin 498 679 P.X := Area.P1.X; 499 while P.X <> Area.P2.X do begin680 while P.X <> Area.P2.X + Area.Increment.X do begin 500 681 PNew := P + DirectionDiff[Direction]; 501 682 if IsValidPos(PNew) then begin … … 519 700 end; 520 701 521 function TGame.CanMoveDirection(Direction: T Direction): Boolean;702 function TGame.CanMoveDirection(Direction: TMoveDirection): Boolean; 522 703 var 523 704 P: TPoint; … … 548 729 end; 549 730 550 procedure TGame.MoveAll(Direction: T Direction);731 procedure TGame.MoveAll(Direction: TMoveDirection); 551 732 var 552 733 P: TPoint; … … 560 741 Area: TArea; 561 742 begin 743 if Direction = drNone then Exit; 562 744 if not CanMoveDirection(Direction) then Exit; 563 745 FMoving := True; … … 634 816 end; 635 817 636 procedure TGame.MoveAllAndUpdate(Direction: T Direction);818 procedure TGame.MoveAllAndUpdate(Direction: TMoveDirection); 637 819 var 638 820 HighestValue: Integer; 821 HistoryMove: THistoryMove; 822 NewTile: TTile; 639 823 begin 640 824 HighestValue := Board.GetHighestTileValue; 641 825 MoveAll(Direction); 642 FillRandomTile; 826 827 NewTile := FillRandomTile; 828 HistoryMove := THistoryMove.Create; 829 HistoryMove.Direction := Direction; 830 HistoryMove.NewItemPos := NewTile.Index; 831 HistoryMove.NewItemValue := NewTile.Value; 832 History.Moves.Add(HistoryMove); 833 643 834 if not CanMove and (Board.GetEmptyTilesCount = 0) then 644 835 GameOver; … … 678 869 FBoardUndo.SaveToRegistry(TRegistryContext.Create(RegContext.RootKey, RegContext.Key + '\BoardUndo')); 679 870 Board.SaveToRegistry(TRegistryContext.Create(RegContext.RootKey, RegContext.Key + '\Board')); 871 History.SaveToRegistry(TRegistryContext.Create(RegContext.RootKey, RegContext.Key + '\History')); 680 872 end; 681 873 … … 696 888 FBoardUndo.LoadFromRegistry(TRegistryContext.Create(RegContext.RootKey, RegContext.Key + '\BoardUndo')); 697 889 Board.LoadFromRegistry(TRegistryContext.Create(RegContext.RootKey, RegContext.Key + '\Board')); 890 History.LoadFromRegistry(TRegistryContext.Create(RegContext.RootKey, RegContext.Key + '\History')); 698 891 DoChange; 699 892 end; … … 705 898 Board := TBoard.Create; 706 899 FBoardUndo := TBoard.Create; 900 History := THistory.Create; 901 History.Game := Self; 707 902 end; 708 903 709 904 destructor TGame.Destroy; 710 905 begin 906 FreeAndNil(History); 711 907 FreeAndNil(FBoardUndo); 712 908 FreeAndNil(Board);
Note:
See TracChangeset
for help on using the changeset viewer.