Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | daniel-mar | 1 | unit LightGameMain; |
2 | |||
3 | (* |
||
4 | TODO for the future: |
||
5 | Predefined Levels... |
||
6 | Undo... |
||
7 | *) |
||
8 | |||
9 | interface |
||
10 | |||
11 | uses |
||
12 | Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, |
||
3 | daniel-mar | 13 | Dialogs, ExtCtrls, StdCtrls, Menus, System.UITypes; |
2 | daniel-mar | 14 | |
15 | type |
||
16 | TMainForm = class(TForm) |
||
17 | Panel1: TPanel; |
||
18 | Panel2: TPanel; |
||
19 | Panel3: TPanel; |
||
20 | Panel4: TPanel; |
||
21 | Panel5: TPanel; |
||
22 | Panel6: TPanel; |
||
23 | Panel7: TPanel; |
||
24 | Panel8: TPanel; |
||
25 | Panel9: TPanel; |
||
26 | Panel10: TPanel; |
||
27 | Panel11: TPanel; |
||
28 | Panel12: TPanel; |
||
29 | Panel13: TPanel; |
||
30 | Panel14: TPanel; |
||
31 | Panel15: TPanel; |
||
32 | Panel16: TPanel; |
||
33 | Panel17: TPanel; |
||
34 | Panel18: TPanel; |
||
35 | Panel19: TPanel; |
||
36 | Panel20: TPanel; |
||
37 | Panel21: TPanel; |
||
38 | Panel22: TPanel; |
||
39 | Panel23: TPanel; |
||
40 | Panel24: TPanel; |
||
41 | Panel25: TPanel; |
||
42 | Image1: TImage; |
||
43 | MainMenu1: TMainMenu; |
||
44 | Game1: TMenuItem; |
||
45 | Exit1: TMenuItem; |
||
46 | N1: TMenuItem; |
||
47 | Newgame1: TMenuItem; |
||
48 | Help1: TMenuItem; |
||
49 | About1: TMenuItem; |
||
50 | Cleargrid1: TMenuItem; |
||
51 | Designmode1: TMenuItem; |
||
52 | N2: TMenuItem; |
||
53 | Save1: TMenuItem; |
||
54 | Loadgrid1: TMenuItem; |
||
55 | N3: TMenuItem; |
||
56 | SaveDialog1: TSaveDialog; |
||
57 | OpenDialog1: TOpenDialog; |
||
58 | Label1: TLabel; |
||
59 | Label2: TLabel; |
||
60 | Timer1: TTimer; |
||
61 | procedure Panel1Click(Sender: TObject); |
||
62 | procedure FormCreate(Sender: TObject); |
||
63 | procedure Exit1Click(Sender: TObject); |
||
64 | procedure About1Click(Sender: TObject); |
||
65 | procedure Newgame1Click(Sender: TObject); |
||
66 | procedure Cleargrid1Click(Sender: TObject); |
||
67 | procedure Loadgrid1Click(Sender: TObject); |
||
68 | procedure Save1Click(Sender: TObject); |
||
69 | procedure Designmode1Click(Sender: TObject); |
||
70 | procedure Timer1Timer(Sender: TObject); |
||
71 | protected const |
||
72 | SIZE_X = 5; |
||
73 | SIZE_Y = 5; |
||
74 | RANDOM_STEPS = 1000; |
||
75 | ONCOLOR = clYellow; |
||
76 | OFFCOLOR = clSilver; |
||
77 | private |
||
78 | FStartTime: TDateTime; |
||
79 | FMoves: integer; |
||
80 | function GetDesignMode: boolean; |
||
81 | procedure SetDesignMode(const Value: boolean); |
||
82 | protected |
||
83 | GameGrid: array[0..SIZE_X-1, 0..SIZE_Y-1] of boolean; |
||
84 | property DesignMode: boolean read GetDesignMode write SetDesignMode; |
||
85 | procedure ResetCounter; |
||
86 | procedure IncCounter; |
||
87 | procedure ToggleSingle(x, y: integer); |
||
88 | procedure RedrawGrid; |
||
89 | procedure RandomMove(PreferLights: boolean=true; redraw: boolean=true); |
||
90 | procedure Draw(x, y: integer; redraw: boolean=true); |
||
91 | procedure ClearGrid(redraw: boolean=true); |
||
92 | function LightsOut: boolean; |
||
93 | procedure LoadGame(FileName: string); |
||
94 | procedure SaveGame(FileName: string); |
||
95 | end; |
||
96 | |||
97 | var |
||
98 | MainForm: TMainForm; |
||
99 | |||
100 | implementation |
||
101 | |||
102 | {$R *.dfm} |
||
103 | |||
104 | uses |
||
105 | LightGameAbout, IniFiles, DateUtils; |
||
106 | |||
107 | { TMainForm } |
||
108 | |||
109 | procedure TMainForm.About1Click(Sender: TObject); |
||
110 | begin |
||
111 | AboutBox.ShowModal; |
||
112 | end; |
||
113 | |||
114 | procedure TMainForm.ClearGrid(redraw: boolean=true); |
||
115 | var |
||
116 | x, y: integer; |
||
117 | begin |
||
118 | for x := 0 to SIZE_X - 1 do |
||
119 | for y := 0 to SIZE_Y - 1 do |
||
120 | GameGrid[x][y] := false; |
||
121 | if redraw then RedrawGrid; |
||
122 | end; |
||
123 | |||
124 | procedure TMainForm.Cleargrid1Click(Sender: TObject); |
||
125 | begin |
||
126 | ClearGrid; |
||
127 | ResetCounter; |
||
128 | end; |
||
129 | |||
130 | procedure TMainForm.Designmode1Click(Sender: TObject); |
||
131 | resourcestring |
||
132 | LNG_CLEARGRID = 'Clear grid?'; |
||
133 | begin |
||
134 | if DesignMode then |
||
135 | begin |
||
136 | if MessageDlg(LNG_CLEARGRID, mtConfirmation, mbYesNoCancel, 0) = mrYes then |
||
137 | begin |
||
138 | ClearGrid; |
||
139 | end; |
||
140 | end; |
||
141 | ResetCounter; |
||
142 | end; |
||
143 | |||
144 | procedure TMainForm.Draw(x, y: integer; redraw: boolean=true); |
||
145 | begin |
||
146 | ToggleSingle(x, y); |
||
147 | |||
148 | if not DesignMode then |
||
149 | begin |
||
150 | ToggleSingle(x-1, y); |
||
151 | ToggleSingle(x+1, y); |
||
152 | ToggleSingle(x, y-1); |
||
153 | ToggleSingle(x, y+1); |
||
154 | end; |
||
155 | |||
156 | if redraw then RedrawGrid; |
||
157 | end; |
||
158 | |||
159 | procedure TMainForm.Exit1Click(Sender: TObject); |
||
160 | begin |
||
161 | Close; |
||
162 | end; |
||
163 | |||
164 | procedure TMainForm.FormCreate(Sender: TObject); |
||
165 | begin |
||
166 | Randomize; |
||
167 | |||
168 | ClientWidth := Image1.Width; |
||
169 | ClientHeight := Image1.Height; |
||
170 | |||
171 | ClearGrid; |
||
172 | end; |
||
173 | |||
174 | function TMainForm.GetDesignMode: boolean; |
||
175 | begin |
||
176 | result := Designmode1.Checked; |
||
177 | end; |
||
178 | |||
179 | procedure TMainForm.IncCounter; |
||
180 | begin |
||
181 | Inc(FMoves); |
||
182 | if FMoves = 1 then FStartTime := Now; |
||
183 | Timer1Timer(Timer1); |
||
184 | end; |
||
185 | |||
186 | function TMainForm.LightsOut: boolean; |
||
187 | var |
||
188 | x, y: integer; |
||
189 | begin |
||
190 | result := true; |
||
191 | for x := 0 to SIZE_X - 1 do |
||
192 | begin |
||
193 | for y := 0 to SIZE_Y - 1 do |
||
194 | begin |
||
195 | if GameGrid[x][y] then |
||
196 | begin |
||
197 | result := false; |
||
198 | Exit; |
||
199 | end; |
||
200 | end; |
||
201 | end; |
||
202 | end; |
||
203 | |||
204 | procedure TMainForm.Loadgrid1Click(Sender: TObject); |
||
205 | begin |
||
206 | if OpenDialog1.Execute then |
||
207 | begin |
||
208 | LoadGame(OpenDialog1.FileName); |
||
209 | end; |
||
210 | ResetCounter; |
||
211 | end; |
||
212 | |||
213 | procedure TMainForm.Newgame1Click(Sender: TObject); |
||
214 | var |
||
215 | i, RandomSteps: integer; |
||
216 | begin |
||
217 | DesignMode := false; |
||
218 | RandomSteps := Random(RANDOM_STEPS); |
||
219 | for i := 0 to RandomSteps - 1 do |
||
220 | begin |
||
221 | RandomMove(true, false); |
||
222 | end; |
||
223 | RedrawGrid; |
||
224 | ResetCounter; |
||
225 | end; |
||
226 | |||
227 | procedure TMainForm.Panel1Click(Sender: TObject); |
||
228 | resourcestring |
||
229 | LNG_WIN = 'Congratulations! You solved the puzzle in %d moves in %.2d:%.2d min.'; |
||
230 | var |
||
231 | x, y, idx: integer; |
||
232 | secs: integer; |
||
233 | begin |
||
234 | idx := TPanel(Sender).Tag-1; |
||
235 | |||
236 | x := idx div SIZE_X; |
||
237 | y := idx mod SIZE_Y; |
||
238 | |||
239 | Draw(x, y); |
||
240 | |||
241 | if not DesignMode then IncCounter; |
||
242 | |||
243 | RedrawGrid; |
||
244 | |||
245 | if LightsOut and not DesignMode then |
||
246 | begin |
||
247 | secs := SecondsBetween(Now, FStartTime); |
||
248 | ShowMessageFmt(LNG_WIN, [FMoves, secs div 60, secs mod 60]); |
||
249 | end; |
||
250 | end; |
||
251 | |||
252 | procedure TMainForm.RandomMove(PreferLights: boolean=true; redraw: boolean=true); |
||
253 | var |
||
254 | x, y: integer; |
||
255 | begin |
||
256 | if not PreferLights then |
||
257 | begin |
||
258 | x := Random(SIZE_X); |
||
259 | y := Random(SIZE_Y); |
||
260 | Draw(x, y, redraw); |
||
261 | end |
||
262 | else |
||
263 | begin |
||
264 | if LightsOut then |
||
265 | begin |
||
266 | x := Random(SIZE_X); |
||
267 | y := Random(SIZE_Y); |
||
268 | Draw(x, y, redraw); |
||
269 | end |
||
270 | else |
||
271 | begin |
||
272 | repeat |
||
273 | x := Random(SIZE_X); |
||
274 | y := Random(SIZE_Y); |
||
275 | until GameGrid[x][y]; |
||
276 | Draw(x, y, redraw); |
||
277 | end; |
||
278 | end; |
||
279 | end; |
||
280 | |||
281 | procedure TMainForm.RedrawGrid; |
||
282 | var |
||
283 | x, y, idx, c: integer; |
||
284 | p: TPanel; |
||
285 | comp: TComponent; |
||
286 | begin |
||
287 | idx := 0; |
||
288 | for x := Low(GameGrid) to High(GameGrid) do |
||
289 | begin |
||
290 | for y := Low(GameGrid[x]) to High(GameGrid[x]) do |
||
291 | begin |
||
292 | Inc(idx); |
||
293 | |||
294 | p := nil; |
||
295 | for c := 0 to ComponentCount - 1 do |
||
296 | begin |
||
297 | comp := Components[c]; |
||
298 | if (comp is TPanel) and (comp.Tag = idx) then |
||
299 | begin |
||
300 | p := TPanel(comp); |
||
301 | end; |
||
302 | end; |
||
303 | |||
304 | if Assigned(p) then |
||
305 | begin |
||
306 | if GameGrid[x][y] then |
||
307 | begin |
||
308 | p.Color := ONCOLOR; |
||
309 | end |
||
310 | else |
||
311 | begin |
||
312 | p.Color := OFFCOLOR; |
||
313 | end; |
||
314 | end; |
||
315 | end; |
||
316 | end; |
||
317 | end; |
||
318 | |||
319 | procedure TMainForm.ResetCounter; |
||
320 | begin |
||
321 | FStartTime := 0; |
||
322 | FMoves := 0; |
||
323 | Timer1Timer(Timer1); |
||
324 | end; |
||
325 | |||
326 | procedure TMainForm.Save1Click(Sender: TObject); |
||
327 | begin |
||
328 | if SaveDialog1.Execute then |
||
329 | begin |
||
330 | SaveGame(SaveDialog1.FileName); |
||
331 | end; |
||
332 | end; |
||
333 | |||
334 | procedure TMainForm.LoadGame(FileName: string); |
||
335 | var |
||
336 | ini: TMemIniFile; |
||
337 | x, y: integer; |
||
338 | s: string; |
||
339 | begin |
||
340 | ini := TMemIniFile.Create(FileName); |
||
341 | try |
||
342 | for x := 0 to SIZE_X - 1 do |
||
343 | begin |
||
344 | for y := 0 to SIZE_Y - 1 do |
||
345 | begin |
||
346 | begin |
||
347 | s := IntToStr(x) + ',' + IntToStr(y); { do not localize } |
||
348 | GameGrid[x][y] := ini.ReadBool('Grid', s, false); { do not localize } |
||
349 | end; |
||
350 | end; |
||
351 | end; |
||
352 | finally |
||
353 | ini.Free; |
||
354 | end; |
||
355 | RedrawGrid; |
||
356 | end; |
||
357 | |||
358 | procedure TMainForm.SaveGame(FileName: string); |
||
359 | var |
||
360 | ini: TMemIniFile; |
||
361 | x, y: integer; |
||
362 | s: string; |
||
363 | begin |
||
364 | ini := TMemIniFile.Create(FileName); |
||
365 | try |
||
366 | for x := 0 to SIZE_X - 1 do |
||
367 | begin |
||
368 | for y := 0 to SIZE_Y - 1 do |
||
369 | begin |
||
370 | begin |
||
371 | s := IntToStr(x) + ',' + IntToStr(y); { do not localize } |
||
372 | ini.WriteBool('Grid', s, GameGrid[x][y]); { do not localize } |
||
373 | end; |
||
374 | end; |
||
375 | end; |
||
376 | ini.UpdateFile; |
||
377 | finally |
||
378 | ini.Free; |
||
379 | end; |
||
380 | end; |
||
381 | |||
382 | procedure TMainForm.SetDesignMode(const Value: boolean); |
||
383 | begin |
||
384 | Designmode1.Checked := Value; |
||
385 | Designmode1Click(Designmode1); |
||
386 | end; |
||
387 | |||
388 | procedure TMainForm.Timer1Timer(Sender: TObject); |
||
389 | resourcestring |
||
390 | LNG_MOVES = '%d moves'; |
||
391 | var |
||
392 | secs: integer; |
||
393 | begin |
||
394 | label1.Visible := FMoves > 0; |
||
395 | Label2.Visible := FMoves > 0; |
||
396 | |||
397 | Label1.Caption := Format(LNG_MOVES, [FMoves]); |
||
398 | |||
399 | secs := SecondsBetween(Now, FStartTime); |
||
400 | Label2.Caption := Format('%.2d:%.2d', [secs div 60, secs mod 60]); |
||
401 | end; |
||
402 | |||
403 | procedure TMainForm.ToggleSingle(x, y: integer); |
||
404 | begin |
||
405 | if (x < 0) or (x >= SIZE_X) then exit; |
||
406 | if (y < 0) or (y >= SIZE_Y) then exit; |
||
407 | |||
408 | GameGrid[x][y] := not GameGrid[x][y]; |
||
409 | end; |
||
410 | |||
411 | end. |