Skip to Content

Листинги

Листинги

Полный текст программы Сапер 2002 представлен ниже. В листинге 15.9 приведен модуль, соответствующий главной форме, В листинге 15.10 -форме О программе.

Листинг 15.9. Модуль главного окна программы Сапер 2002

  1. unit saper_1;
  2. interface
  3.  
  4. uses
  5. Windows, Messages, SysUtils, Classes,
  6. Graphics, Controls, Forms, Dialogs,
  7. Menus, StdCtrls, OleCtrls, HHOPENLib_TLB;
  8.  
  9. type
  10. TForm1 = class(TForm)
  11. MainMenu1: TMainMenu;
  12. N1: TMenuItem;
  13. N2: TMenuItem;
  14. N3: TMenuItem;
  15. N4: TMenuItem;
  16. Hhopen1: THhopen;
  17.  
  18. procedure Form1Create(Sender: TObject);
  19. procedure Form1Paint(Sender: TObject);
  20. procedure Form1MouseDown(Sender: TObject; Button: TMouseButton;
  21. Shift: TShiftState; X, Y: Integer);
  22. procedure N1Click(Sender: TObject);
  23. procedure N4Click(Sender: TObject);
  24. procedure N3Click(Sender: TObject);
  25.  
  26. private
  27. { Private declarations }
  28. public
  29. { Public declarations }
  30. end;
  31.  
  32. var
  33. Form1: TForm1;
  34.  
  35. implementation
  36. uses saper_2;
  37. {$R *.DFM}
  38.  
  39. const
  40. MR = 10; // кол-во клеток по вертикали
  41. MC = 10; // кол-во клеток по горизонтали
  42. NM = 10; // кол-во мин
  43. W = 40; // ширина клетки поля
  44. H = 40; // высота клетки поля
  45.  
  46. var
  47. Pole: array[0..MR+1, 0.. MC+1] of integer; // минное поле
  48.  
  49. // значение элемента массива:
  50. // 0..8 - количество мин в соседних клетках
  51. // 9 - в клетке мина
  52. // 100..109 - клетка открыта
  53. // 200..209 - в клетку поставлен флаг
  54.  
  55. nMin : integer; // кол-во найденных мин
  56. nFlag : integer; // кол-во поставленных флагов
  57. status : integer; // 0 - начало игры; 1- игра; 2 -результат
  58.  
  59. Procedure NewGame(); forward;
  60.  
  61. // генерирует новое поле
  62.  
  63. Procedure ShowPole(Canvas : TCanvas; status : integer); forward;// Показывает поле
  64. Procedure Kletka(Canvas : TCanvas; row, col, status : integer); forward; // выводит содержимое клетки
  65. Procedure Open( row, col : integer); forward;// открывает текущую и все соседние клетки, в которых нет мин
  66. Procedure Mina(Canvas : TCanvas; x, y : integer); forward; // Рисует мину
  67. Procedure Flag( Canvas : TCanvas; x, y : integer); forward;// Рисует флаг
  68.  
  69. // выводит на экран содержимое клетки
  70.  
  71. Procedure Kletka(Canvas : TCanvas; row, col, status : integer);
  72. var
  73. x,y : integer; // координаты области вывода
  74. begin
  75. x := (col-1)* W + 1;
  76. y := (row-1)* H + 1;
  77.  
  78. if status = 0 then
  79. begin
  80.  
  81. Canvas.Brush.Color := clLtGray;
  82. Canvas.Rectangle(x-1,y-1,x+W,y+H);
  83. exit;
  84.  
  85. end;
  86.  
  87. if Pole[row,col] < 100 then
  88. begin
  89.  
  90. Canvas.Brush.Color := clLtGray; // не открытые - серые
  91. Canvas.Rectangle(x-1,y-1,x+W,y+H);
  92.  
  93. // если игра завершена (status = 2), то показать мины
  94.  
  95. if (status = 2) and (Pole[row,col] = 9) then
  96. Mina(Canvas, x, y);
  97.  
  98. exit;
  99.  
  100. end;
  101.  
  102. // открываем клетку
  103.  
  104. Canvas.Brush.Color := clWhite; // открытые белые
  105. Canvas.Rectangle(x-1,y-1,x+W,y+H);
  106.  
  107. if ( Pole[row,col] = 100 ) then
  108. exit; // клетка открыта, но она пустая
  109.  
  110. if ( Pole[row,col] >= 101) and (Pole[row,col] <= 108 ) then
  111. begin
  112.  
  113. Canvas.Font.Size := 14;
  114. Canvas.Font.Color := clBlue;
  115. Canvas.TextOut(x+3,y+2,IntToStr(Pole[row,col] -100 ));
  116. exit;
  117.  
  118. end;
  119.  
  120. if ( Pole[row,col] >= 200 ) then
  121. Flag(Canvas, x, y);
  122.  
  123. if (Pole[row,col] = 109 ) then // на этой мине подорвались!
  124. begin
  125.  
  126. Canvas.Brush.Color := clRed;
  127. Canvas.Rectangle(x-1,y-1,x+W,y+H);
  128.  
  129. end;
  130.  
  131. if ( (Pole[row,col] mod 10) = 9) and (status = 2) then
  132. Mina(Canvas, x, y);
  133. end;
  134.  
  135. // Показывает поле
  136. Procedure ShowPole(Canvas : TCanvas; status : integer);
  137. var
  138. row,col : integer;
  139. begin
  140. for row := 1 to MR do
  141. for col := 1 to MC do
  142. Kletka(Canvas, row, col, status);
  143. end;
  144.  
  145. // рекурсивная функция открывает текущую и все соседние
  146. // клетки, в которых нет мин
  147. Procedure Open( row, col : integer);
  148. begin
  149. if Pole[row,col] = 0 then
  150. begin
  151. Pole[row,col] := 100;
  152. Kletka(Form1.Canvas, row,col, 1);
  153. Open(row,col-1);
  154. Open(row-1,col);
  155. Open(row,col+1);
  156. Open(row+1,col);
  157. //примыкающие диагонально
  158. Open(row-1,col-1);
  159. Open(row-1,col+1);
  160. Open(row+1,col-1);
  161. Open(row+1,col+1);
  162. end
  163. else
  164. if (Pole[row,col] < 100) and ( Pole[row,col] <> -3 ) then
  165. begin
  166. Pole[row,col] := Pole[row,col] + 100;
  167. Kletka(Form1.Canvas, row, col, 1);
  168. end;
  169. end;
  170.  
  171. // новая игра - генерирует новое поле
  172. procedure NewGame();
  173.  
  174. var
  175. row,col : integer; // координаты клетки
  176. n : integer; // количество поставленных мин
  177. k : integer; // кол-во мин в соседних клетках
  178. begin
  179. // Очистим эл-ты массива, соответствующие клеткам
  180. // игрового поля.
  181. for row :=1 to MR do
  182. for col :=1 to MC do
  183. Pole[row,col] := 0;
  184.  
  185. // расставим мины
  186. Randomize(); // инициализация ГСЧ
  187. n := 0; // кол-во мин
  188. repeat
  189. row := Random(MR) + 1;
  190. col := Random(MC) + 1;
  191. if ( Pole[row,col] <> 9) then
  192. begin
  193. Pole[row,col] := 9;
  194. n := n+1;
  195. end;
  196. until ( n = NM );
  197.  
  198. // для каждой клетки вычислим
  199. // кол-во мин в соседних клетках
  200. for row := 1 to MR do
  201. for col := 1 to MC do
  202. if ( Pole[row,col] <> 9 ) then
  203. begin
  204. k :=0 ;
  205. if Pole[row-1,col-1] = 9 then k := k + 1;
  206. if Pole[row-1,col] = 9 then k := k + 1;
  207. if Pole[row-1,col+1] = 9 then k := k + 1;
  208. if Pole[row,col-1] = 9 then k := k + 1;
  209. if Pole[row,col+1] = 9 then k := k + 1;
  210. if Pole[row+1,col-1] = 9 then k := k + 1;
  211. if Pole[row+1,col] = 9 then k := k + 1;
  212. if Pole[row+1,col+1] = 9 then k := k + 1;
  213. Pole[row,col] := k;
  214. end;
  215. status := 0; // начало игры
  216. nMin := 0; // нет обнаруженных мин
  217. nFlag := 0; // нет флагов
  218.  
  219. end;
  220.  
  221. // Рисует мину
  222. Procedure Mina(Canvas : TCanvas; x, y : integer);
  223. begin
  224. with Canvas do
  225. begin
  226. Brush.Color := clGreen;
  227. Pen.Color := clBlack;
  228. Rectangle(x+16,y+26,x+24,y+30);
  229. Rectangle(x+8,y+30,x+16,y+34);
  230. Rectangle(x+24,y+30,x+32,y+34);
  231. Pie(x+6,y+28,x+34,y+44,x+34,y+36,x+6,y+36);
  232.  
  233. MoveTo(x+12,y+32); LineTo(x+26,y+32);
  234. MoveTo(x+8,y+36); LineTo(x+32,y+36);
  235. MoveTo(x+20,y+22); LineTo(x+20,y+26);
  236. MoveTo(x+8, y+30); LineTo(x+6,y+28);
  237. MoveTo(x+32,y+30); LineTo(x+34,y+28);
  238. end;
  239. end;
  240.  
  241. // Рисует флаг
  242. Procedure Flag( Canvas : TCanvas; x, y : integer);
  243. var
  244. p : array [0..3] of TPoint; // координаты флажка и нижней точки древка
  245. m : array [0..4] of TPoint; // буква М
  246. begin
  247. // зададим координаты точек флажка
  248. p[0].x:=x+4; p[0].y:=y+4;
  249. p[1].x:=x+30; p[1].y:=y+12;
  250. p[2].x:=x+4; p[2].y:=y+20;
  251. p[3].x:=x+4; p[3].y:=y+36; // нижняя точка древка
  252.  
  253. m[0].x:=x+8; m[0].y:=y+14;
  254. m[1].x:=x+8; m[1].y:=y+8;
  255. m[2].x:=x+10; m[2].y:=y+10;
  256. m[3].x:=x+12; m[3].y:=y+8;
  257. m[4].x:=x+12; m[4].y:=y+14;
  258.  
  259. with Canvas do
  260. begin
  261. // установим цвет кисти и карандаша
  262. Brush.Color := clRed;
  263. Pen.Color := clRed;
  264.  
  265. Polygon(p); // флажок
  266.  
  267. // древко
  268. Pen.Color := clBlack;
  269. MoveTo(p[0].x, p[0].y);
  270. LineTo(p[3].x, p[3].y);
  271.  
  272. // буква М
  273. Pen.Color := clWhite;
  274. Polyline(m);
  275.  
  276. Pen.Color := clBlack;
  277. end;
  278. end;
  279.  
  280. // выбор из меню ? команды О программе
  281. procedure TForm1.N4Click(Sender: TObject);
  282. begin
  283. AboutForm.Top := Trunc(Form1.Top + Form1.Height/2 - AboutForm.Height/2);
  284. AboutForm.Left := Trunc(Form1.Left +Form1.Width/2 - AboutForm.Width/2);
  285. AboutForm.ShowModal;
  286. end;
  287.  
  288. procedure TForm1.Form1Create(Sender: TObject);
  289. var
  290. row,col : integer;
  291. begin
  292. // В неотображаемые эл-ты массива, которые соответствуют
  293. // клеткам по границе игрового поля запишем число -3.
  294. // Это значение используется функцией Open для завершения
  295. // рекурсивного процесса открытия соседних пустых клеток.
  296. for row :=0 to MR+1 do
  297. for col :=0 to MC+1 do
  298. Pole[row,col] := -3;
  299.  
  300. NewGame(); // "разбросать" мины
  301. Form1.ClientHeight := H*MR + 1;
  302. Form1.ClientWidth := W*MC + 1;
  303. end;
  304.  
  305.  
  306. // нажатие кнопки мыши на игровом поле
  307. procedure TForm1.Form1MouseDown(Sender: TObject; Button: TMouseButton;
  308. Shift: TShiftState; X, Y: Integer);
  309. var
  310. row, col : integer;
  311. begin
  312. if status = 2 // игра завершена
  313. then exit;
  314.  
  315. if status = 0 then // первый щелчок
  316. status := 1;
  317.  
  318. // преобразуем координаты мыши в индексы
  319. // клетки поля
  320. row := Trunc(y/H) + 1;
  321. col := Trunc(x/W) + 1;
  322.  
  323. if Button = mbLeft then
  324. begin
  325. if Pole[row,col] = 9 then
  326. begin // открыта клетка, в которой есть мина
  327. Pole[row,col] := Pole[row,col] + 100;
  328. status := 2; // игра закончена
  329. ShowPole(Form1.Canvas, status);
  330. end
  331. else if Pole[row,col] < 9 then
  332. Open(row,col);
  333. end
  334. else
  335. if Button = mbRight then
  336. if Pole[row,col] > 200 then
  337. begin
  338. // уберем флаг и закроем клетку
  339. nFlag := nFlag - 1;
  340. Pole[row,col] := Pole[row,col] - 200; // уберем флаг
  341. x := (col-1)* W + 1;
  342. y := (row-1)* H + 1;
  343. Canvas.Brush.Color := clLtGray;
  344. Canvas.Rectangle(x-1,y-1,x+W,y+H);
  345. end
  346. else
  347. begin // поставить в клетку флаг
  348. nFlag := nFlag + 1;
  349. if Pole[row,col] = 9
  350. then nMin := nMin + 1;
  351. Pole[row,col] := Pole[row,col]+ 200; // поставили флаг
  352. if (nMin = NM) and (nFlag = NM) then
  353. begin
  354. status := 2; // игра закончена
  355. ShowPole(Form1.Canvas, status);
  356. end
  357. else Kletka(Form1.Canvas, row, col, status);
  358. end;
  359. end;
  360.  
  361. // Выбор меню Новая игра
  362. procedure TForm1.N1Click(Sender: TObject);
  363. begin
  364. NewGame();
  365. ShowPole(Form1.Canvas,status);
  366. end;
  367.  
  368. // выбор из меню ? команды Справка
  369. procedure TForm1.N3Click(Sender: TObject);
  370.  
  371. var
  372. HelpFile : string; // файл справки
  373. HelpTopic : string; // раздел справки
  374. pwHelpFile : PWideChar; // файл справки (указатель на WideChar строку)
  375. pwHelpTopic : PWideChar; // раздел (указатель на WideChar строку)
  376. begin
  377. HelpFile := 'saper.chm';
  378. HelpTopic := 'saper_02.htm';
  379.  
  380. // выделить память для WideChar строк
  381. GetMem(pwHelpFile, Length(HelpFile) * 2);
  382. GetMem(pwHelpTopic, Length(HelpTopic)*2);
  383.  
  384. // преобразовать Ansi строку в WideString строку
  385. pwHelpFile := StringToWideChar(HelpFile,pwHelpFile,MAX_PATH*2);
  386. pwHelpTopic := StringToWideChar(HelpTopic,pwHelpTopic,32);
  387.  
  388. // вывести справочную информацию
  389. Form1.Hhopen1.OpenHelp(pwHelpFile,pwHelpTopic);
  390.  
  391. end;
  392.  
  393. procedure TForm1.Form1Paint(Sender: TObject);
  394. begin
  395. ShowPole(Form1.Canvas, status);
  396. end;
  397. end.



Delphi Для профессионалов &1   |    Delphi Для профессионалов &2   |    Delphi Для профессионалов &3   |    Иллюстрированный самоучитель &1   |    Иллюстрированный самоучитель &2