首页 > 编程语言 >Delphi 经典游戏程序设计40例 的学习 例36 增加格子线便于观察改进

Delphi 经典游戏程序设计40例 的学习 例36 增加格子线便于观察改进

时间:2022-11-06 22:05:42浏览次数:38  
标签:Box 10 begin end Delphi Random 36 40 Tline

 

  1 unit R36;
  2 
  3 interface
  4 
  5 uses
  6   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7   Dialogs, ExtCtrls, StdCtrls;
  8 
  9 type
 10   TRoom = record       //房间记录类型
 11     Used : Byte;
 12     Xpos : Byte;       //区块位置
 13     Ypos : Byte;
 14     Xsiz : Byte;       //区块大小
 15     Ysiz : Byte;
 16     UX : Byte;         //上侧出入口位置
 17     UY : Byte;
 18     DX : Byte;         //下侧
 19     DY : Byte;
 20     LX : Byte;         //左侧
 21     LY : Byte;
 22     RX : Byte;         //右侧
 23     RY : Byte;
 24   end;
 25 
 26 
 27   TRei36 = class(TForm)
 28     Button1: TButton;
 29     Timer1: TTimer;
 30     Button2: TButton;
 31     procedure FormCreate(Sender: TObject);
 32     procedure Button1Click(Sender: TObject);
 33     procedure FormClose(Sender: TObject; var Action: TCloseAction);
 34     procedure Timer1Timer(Sender: TObject);
 35     procedure Button2Click(Sender: TObject);
 36   private
 37     { Private declarations }
 38     procedure MkRoom;
 39     procedure MkMaze;
 40     procedure Tline(a,b:Byte);
 41     procedure Lway;
 42     procedure Mway;
 43     procedure Rway;
 44     procedure DiMaze;
 45     procedure LineRed;
 46   public
 47     { Public declarations }
 48   end;
 49 const
 50   Mwidth = 50 * 10 + 20;     //迷宫宽度
 51   Mheight = 30 * 10 + 20;    //迷宫高度
 52 var
 53   Rei36: TRei36;
 54   MakeBmap,LineBmap : TBitmap;
 55   RectD : TRect;
 56   St,m,max : Byte;
 57   StLine : Byte;
 58 
 59   Mdata : array[0..49,0..29] of Byte;      //迷宫数组50*30点
 60   Box : array[0..14] of TRoom;             //房间数组 15房间 ,记录数组类型
 61   
 62 implementation
 63 
 64 {$R *.dfm}
 65 
 66 procedure TRei36.FormCreate(Sender: TObject);
 67 begin
 68   Rei36.Canvas.CopyMode := cmSrcCopy;
 69   MakeBmap := TBitmap.Create;
 70   MakeBmap.Width := Mwidth;
 71   MakeBmap.Height := Mheight;
 72 
 73   LineBmap := TBitmap.Create;
 74   LineBmap.Width := Mwidth;
 75   LineBmap.Height := Mheight;
 76 
 77   St := 1;       //初始迷宫制作指令
 78   StLine := 0;
 79   Randomize;
 80 
 81 end;
 82 
 83 procedure TRei36.MkRoom;       //制作房间参数
 84 var
 85   n : byte;
 86 begin
 87   for n := 0 to 14 do
 88     Box[n].Used := 0;     //房间清零
 89   max := 5 + Random(5);   //最大5+5个房间?
 90   m := 0;
 91   repeat
 92     n := Random(15);
 93     if (Odd(n) = False) and (Box[n].Used = 0) then     //保证偶数块有房间3个
 94     begin
 95       Box[n].Used := 1;
 96       m := m + 1;
 97     end;
 98   until m = 4;
 99 
100   repeat                             //随机房间数量到MAX
101     n := Random(15);
102     if (n <> 7) and (Box[n].Used = 0) then
103     begin
104       Box[n].Used := 1;
105       m := m + 1;
106     end;
107   until m > max;
108 
109   for n := 0 to 14 do
110     with Box[n] do
111     begin
112       if Used = 1 then
113       begin                //设置房间大小,最小4+0+0=4,最大4+2+3=9
114         Xsiz := 4 + ((n + 1) mod 2) * 2 + Random(4);   //这里为什么要引入n?
115         Ysiz := 4 + ((n + 1) mod 2) * 2 + Random(4);   //实际是为了控制奇区4-7,偶区6-9
116       end
117       else begin          //非房间大小
118         Xsiz := 4;
119         Ysiz := 4;
120       end;
121       //设置房间位置,注意非房间也有位置的。放中间
122       Xpos := (n mod 5) * 10 + (10 - Xsiz) div 2; //5列,取余得到X块
123       Ypos := (n div 5) * 10 + (10 - Ysiz) div 2; //取商得到Y块
124 
125       if Used = 1 then
126       begin
127         UX := Xpos + 1 + Random(Xsiz - 2);   //上出口
128         UY := Ypos;
129         DX := Xpos + 1 + Random(Xsiz - 2);   //下出口
130         DY := Ypos + Ysiz - 1;
131         LX := Xpos;                          //左出口
132         LY := Ypos + 1 + Random(Ysiz - 2);
133         RX := Xpos + Xsiz - 1;               //右出口
134         RY := Ypos + 1 + Random(Ysiz - 2);
135       end
136       else begin
137         UX := Xpos;
138         UY := Ypos;
139         DX := UX;
140         DY := UY;
141         LX := UX;
142         LY := UY;
143         RX := UX;
144         RY := UY;
145       end;
146     end;
147 
148     for n := 0 to 3 do           //左右间隙小于3则修改成直连  ?
149       if Box[n + 1].LX - Box[n].RX <= 3 then
150       begin
151         Box[n].RY := 4 + Random(2);
152         Box[n + 1].LY := Box[n].RY;
153       end;
154     for n:= 5 to 8 do
155       if Box[n + 1].LX - Box[n].RX <= 3 then
156       begin
157         Box[n].RY := 14 + Random(2);
158         Box[n + 1].LY := Box[n].RY;
159       end;
160 
161     for n := 10 to 13 do
162       if Box[n + 1].LX - Box[n].RX <= 3 then
163       begin
164         Box[n].RY := 24 + Random(2);
165         Box[n + 1].LY := Box[n].RY;
166       end;
167 
168     for n := 0 to 4 do              //上下间隙间隙小于3则修改成直连
169     begin
170       if Box[n + 5].UY - Box[n].DY <= 3 then
171       begin
172         Box[n].DX := 4 + Random(2) + n * 10;
173         Box[n + 5].UX := Box[n].DX;
174       end;
175       if Box[n + 10].UY - Box[n + 5].DY <= 3 then
176       begin
177         Box[n + 5].DX := 4 + Random(2) + n * 10;
178         Box[n + 10].UX := Box[n].DX;
179       end;
180     end;
181 
182 end;
183 
184 
185 procedure TRei36.MkMaze;
186 var
187   x,y,n : Byte;
188 begin
189   for x := 0 to 49 do
190     for y := 0 to 29 do
191       Mdata[x,y] := 1;    //全设置为墙
192   for n := 0 to 14 do
193     if Box[n].Used = 1 then
194       for x := Box[n].LX to Box[n].RX do
195         for y := Box[n].UY to Box[n].DY do
196           Mdata[x,y] := 2;   //设置为房间
197   Lway;
198   Mway;
199   Rway;
200 
201 end;
202 
203 
204 procedure TRei36.Tline(a,b:Byte);  //制作通道
205 var
206   nn,mx,my : Byte;
207 begin
208   if (b-a) = 1 then        //房间相邻
209   begin     //横向连接
210     mx := Box[b].LX - (Box[b].LX - Box[a].Xpos - Box[a].Xsiz + 2) div 2; //取得一个中间点
211     for nn := Box[a].RX to mx do
212       Mdata[nn,Box[a].RY] := Mdata[nn,Box[a].RY] and 2; //通道穿过房间还是10B,穿过墙则是00B
213     for nn := mx to Box[b].LX do
214       Mdata[nn,Box[b].LY] := Mdata[nn,Box[b].LY] and 2;
215 
216     if Box[a].RY > Box[b].LY then        //从中间点开始连接
217       for nn := Box[b].LY to Box[a].RY do
218         Mdata[mx,nn] := Mdata[mx,nn] and 2
219     else if Box[a].RY < Box[b].LY  then  //这里为什么要重复判断?
220       for nn := Box[a].RY to Box[b].LY  do
221         Mdata[mx,nn] := Mdata[mx,nn] and 2;
222   end
223   else begin     //不相邻则纵向连接?
224     my := Box[b].UY - (Box[b].UY - Box[a].Ypos- Box[a].Ysiz + 2) div 2;
225     for nn := Box[a].DY  to my do
226       Mdata[Box[a].DX,nn] := Mdata[Box[a].DX,nn] and 2;
227     for nn := my to Box[b].UY do
228       Mdata[Box[b].UX,nn] := Mdata[Box[b].UX,nn] and 2;
229     if Box[a].DX > Box[b].UX then
230       for nn := Box[b].UX to Box[a].DX do
231         Mdata[nn,my] := Mdata[nn,my] and 2
232     else  if Box[a].DX < Box[b].UX then
233       for nn := Box[a].DX to Box[b].UX do
234         Mdata[nn,my] := Mdata[nn,my] and 2;
235   end;
236 
237 end;
238 
239 
240 procedure TRei36.Lway;         //0 1 5 6 10 11 左侧房间连接规则
241 begin
242   if Random(2) = 0 then
243   begin
244     Tline(0,1);
245     Tline(0,5);
246     Tline(1,6);
247     if (Box[5].Used and Box[6].Used = 0) or (Random(2) = 0) then
248       Tline(5,6);
249     if Box[10].Used = 1 then
250     begin
251       Tline(5,10);
252       if Random(2) = 0 then
253         Tline(10,11)
254       else
255         Tline(6,11);
256 
257     end
258     else if Random(2) =0 then
259     begin
260       Tline(5,10);
261       Tline(10,11);
262     end
263     else
264       Tline(6,11);
265 
266   end
267   else begin
268     Tline(10,11);
269     Tline(5,10);
270     Tline(6,11);
271     if (Box[5].Used and Box[6].Used = 0) or (Random(2) = 0) then
272       Tline(5,6);
273     if Box[0].Used = 1 then
274     begin
275       Tline(0,5);
276       if Random(2) = 0 then
277         Tline(0,1)
278       else
279         Tline(1,6);
280     end
281     else if  Random(2) = 0 then
282     begin
283       Tline(0,5);
284       Tline(0,1);
285 
286     end
287     else
288       Tline(1,6);
289   end;
290 end;
291 
292 
293 procedure TRei36.Mway;   //1 2 3 11 12 13 的中侧房间连接规则
294 begin
295   case Random(4) of
296     0: begin
297       Tline(1,2);
298       Tline(2,3);
299       Tline(11,12);
300       if Random(2) = 0 then
301         Tline(12,13);
302     end;
303     1: begin
304       Tline(1,2);
305       Tline(2,3);
306       Tline(12,13);
307       if Random(2) = 0 then
308         Tline(11,12);
309     end;
310     2: begin
311       Tline(11,12);
312       Tline(12,13);
313       Tline(1,2);
314       if Random(2) = 0 then
315         Tline(2,3);
316     end;
317     3: begin
318       Tline(11,12);
319       Tline(12,13);
320       Tline(2,3);
321       if Random(2) = 0 then
322        Tline(1,2);
323     end;
324   end;
325 end;
326 
327 
328 procedure TRei36.Rway;   // 3 4 8 9 13 14  右侧房间连接规则
329 begin
330   if Random(2) = 0 then        // 随机
331   begin
332     Tline(3,4);     //将3,4 3,8 4,9 房间连接起来
333     Tline(3,8);
334     Tline(4,9);
335     if (Box[8].Used and Box[9].Used = 0) or (Random(2) = 0) then
336       Tline(8,9);   //当8与9的其中之一不是房间时,以随机数将8,9连接起来
337     if Box[14].Used = 1 then     //若14是房间
338     begin
339       Tline(9,14);              //连接9,14
340       if Random(2) = 0 then     //再将13,14 或 8,13连接
341         Tline(13,14)
342       else
343         Tline(8,13);
344     end
345     else if Random(2) = 0 then   //14不是房间
346     begin                        // 连接9,14 13 14 或 8,13
347       Tline(9,14);
348       Tline(13,14);
349     end
350     else
351       Tline(8,13);
352   end
353   else begin                 //随机另一规则
354     Tline(13,14);
355     Tline(8,13);
356     Tline(9,14);
357     if (Box[8].Used and Box[9].Used = 0) or (Random(2) = 0) then
358       Tline(8,9);
359     if Box[4].Used = 1 then
360     begin
361       Tline(4,9);
362       if Random(2) = 0 then
363         Tline(3,4)
364       else
365         Tline(3,8);
366     end
367     else if  Random(2) = 0 then
368     begin
369       Tline(3,4);
370       Tline(4,9);
371     end
372     else
373       Tline(3,8);
374   end;
375 
376 end;
377 procedure TRei36.DiMaze;      //在制作画板上以10*10 的块显示Mdata数组
378 var
379   x,y : Byte;
380 begin
381   for x := 0 to 49 do
382     for y := 0 to 29 do
383       begin
384         case Mdata[x,y] of
385           0: MakeBmap.Canvas.Brush.Color := clBlack;
386           1: MakeBmap.Canvas.Brush.Color := clOlive;
387           2: MakeBmap.Canvas.Brush.Color := clNavy;
388         end;
389         RectD := Rect(x * 10 + 10,y * 10 + 10,x * 10 + 20,y * 10 + 20);
390        // RectD := Rect(x + 10,y + 10,x + 10 + 1,y + 10 + 1); //缩小比例
391         MakeBmap.Canvas.FillRect(RectD);
392       end;
393 end;
394 
395 procedure TRei36.Button1Click(Sender: TObject);
396 begin
397   St := 2;
398 end;
399 
400 procedure TRei36.FormClose(Sender: TObject; var Action: TCloseAction);
401 begin
402   MakeBmap.Free;
403   LineBmap.Free;
404 end;
405 
406 procedure TRei36.Timer1Timer(Sender: TObject);
407 begin
408   case St of
409     1: begin          //绘制外框
410       RectD := Rect(0,0,Mwidth,Mheight);
411       MakeBmap.Canvas.Brush.Color := clOlive;
412       MakeBmap.Canvas.FillRect(RectD);
413       RectD := Rect(10,10,Mwidth - 20,Mheight - 20);
414       MakeBmap.Canvas.Brush.Color := clBlack;
415       MakeBmap.Canvas.FillRect(RectD);
416       Rei36.Canvas.Draw(0,0,MakeBmap);
417       St := 2;
418     end;
419     2: begin       //制作新的迷宫显示出来,按钮控制
420       MkRoom;      //制作房间参数
421       MkMaze;
422       DiMaze;
423       LineBmap.canvas.Draw(0,0,MakeBmap);
424       LineRed;
425 
426       St := 3;
427     end;
428     3:begin
429       if StLine = 0 then
430         Rei36.Canvas.Draw(0,0,MakeBmap)
431       else
432         Rei36.Canvas.Draw(0,0,LineBmap);
433 
434     end;
435 
436 
437   end;
438 end;
439 
440 procedure TRei36.LineRed;
441 var
442   x,y : Byte;
443 begin
444   LineBmap.Canvas.Pen.Width := 1;
445   LineBmap.Canvas.Pen.Color := clRed;
446   for y := 0 to 3 do
447     begin
448       LineBmap.Canvas.MoveTo(10,y * 100 + 10);
449       LineBmap.Canvas.LineTo(Mwidth -10,y * 100 + 10);
450 
451     end;
452   for x := 0 to 5 do
453     begin
454       LineBmap.Canvas.MoveTo(x * 100 + 10,10);
455       LineBmap.Canvas.LineTo(x * 100 + 10,Mheight - 10);
456     end;
457 
458 
459 end;
460 procedure TRei36.Button2Click(Sender: TObject);
461 begin
462   StLine := StLine xor 1;
463 end;
464 
465 end.

增加了一个画板,用来存放画了线的图片

通过按钮 ,增加一个状态,来显示 有线格和无线格的图片

 

标签:Box,10,begin,end,Delphi,Random,36,40,Tline
From: https://www.cnblogs.com/D7mir/p/16864264.html

相关文章