Листинги
Полный текст программы Сапер 2002 представлен ниже. В листинге 15.9 приведен модуль, соответствующий главной форме, В листинге 15.10 -форме О программе.
Листинг 15.9. Модуль главного окна программы Сапер 2002
unit saper_1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Menus, StdCtrls, OleCtrls, HHOPENLib_TLB; type TForm1 = class(TForm) MainMenu1: TMainMenu; N1: TMenuItem; N2: TMenuItem; N3: TMenuItem; N4: TMenuItem; Hhopen1: THhopen; procedure Form1Create(Sender: TObject); procedure Form1Paint(Sender: TObject); procedure Form1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure N1Click(Sender: TObject); procedure N4Click(Sender: TObject); procedure N3Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation uses saper_2; {$R *.DFM} const MR = 10; // кол-во клеток по вертикали MC = 10; // кол-во клеток по горизонтали NM = 10; // кол-во мин W = 40; // ширина клетки поля H = 40; // высота клетки поля var Pole: array[0..MR+1, 0.. MC+1] of integer; // минное поле // значение элемента массива: // 0..8 - количество мин в соседних клетках // 9 - в клетке мина // 100..109 - клетка открыта // 200..209 - в клетку поставлен флаг nMin : integer; // кол-во найденных мин nFlag : integer; // кол-во поставленных флагов status : integer; // 0 - начало игры; 1- игра; 2 -результат Procedure NewGame(); forward; // генерирует новое поле Procedure ShowPole(Canvas : TCanvas; status : integer); forward;// Показывает поле Procedure Kletka(Canvas : TCanvas; row, col, status : integer); forward; // выводит содержимое клетки Procedure Open( row, col : integer); forward;// открывает текущую и все соседние клетки, в которых нет мин Procedure Mina(Canvas : TCanvas; x, y : integer); forward; // Рисует мину Procedure Flag( Canvas : TCanvas; x, y : integer); forward;// Рисует флаг // выводит на экран содержимое клетки Procedure Kletka(Canvas : TCanvas; row, col, status : integer); var x,y : integer; // координаты области вывода begin x := (col-1)* W + 1; y := (row-1)* H + 1; if status = 0 then begin Canvas.Brush.Color := clLtGray; Canvas.Rectangle(x-1,y-1,x+W,y+H); exit; end; if Pole[row,col] < 100 then begin Canvas.Brush.Color := clLtGray; // не открытые - серые Canvas.Rectangle(x-1,y-1,x+W,y+H); // если игра завершена (status = 2), то показать мины if (status = 2) and (Pole[row,col] = 9) then Mina(Canvas, x, y); exit; end; // открываем клетку Canvas.Brush.Color := clWhite; // открытые белые Canvas.Rectangle(x-1,y-1,x+W,y+H); if ( Pole[row,col] = 100 ) then exit; // клетка открыта, но она пустая if ( Pole[row,col] >= 101) and (Pole[row,col] <= 108 ) then begin Canvas.Font.Size := 14; Canvas.Font.Color := clBlue; Canvas.TextOut(x+3,y+2,IntToStr(Pole[row,col] -100 )); exit; end; if ( Pole[row,col] >= 200 ) then Flag(Canvas, x, y); if (Pole[row,col] = 109 ) then // на этой мине подорвались! begin Canvas.Brush.Color := clRed; Canvas.Rectangle(x-1,y-1,x+W,y+H); end; if ( (Pole[row,col] mod 10) = 9) and (status = 2) then Mina(Canvas, x, y); end; // Показывает поле Procedure ShowPole(Canvas : TCanvas; status : integer); var row,col : integer; begin for row := 1 to MR do for col := 1 to MC do Kletka(Canvas, row, col, status); end; // рекурсивная функция открывает текущую и все соседние // клетки, в которых нет мин Procedure Open( row, col : integer); begin if Pole[row,col] = 0 then begin Pole[row,col] := 100; Kletka(Form1.Canvas, row,col, 1); Open(row,col-1); Open(row-1,col); Open(row,col+1); Open(row+1,col); //примыкающие диагонально Open(row-1,col-1); Open(row-1,col+1); Open(row+1,col-1); Open(row+1,col+1); end else if (Pole[row,col] < 100) and ( Pole[row,col] <> -3 ) then begin Pole[row,col] := Pole[row,col] + 100; Kletka(Form1.Canvas, row, col, 1); end; end; // новая игра - генерирует новое поле procedure NewGame(); var row,col : integer; // координаты клетки n : integer; // количество поставленных мин k : integer; // кол-во мин в соседних клетках begin // Очистим эл-ты массива, соответствующие клеткам // игрового поля. for row :=1 to MR do for col :=1 to MC do Pole[row,col] := 0; // расставим мины Randomize(); // инициализация ГСЧ n := 0; // кол-во мин repeat row := Random(MR) + 1; col := Random(MC) + 1; if ( Pole[row,col] <> 9) then begin Pole[row,col] := 9; n := n+1; end; until ( n = NM ); // для каждой клетки вычислим // кол-во мин в соседних клетках for row := 1 to MR do for col := 1 to MC do if ( Pole[row,col] <> 9 ) then begin k :=0 ; if Pole[row-1,col-1] = 9 then k := k + 1; if Pole[row-1,col] = 9 then k := k + 1; if Pole[row-1,col+1] = 9 then k := k + 1; if Pole[row,col-1] = 9 then k := k + 1; if Pole[row,col+1] = 9 then k := k + 1; if Pole[row+1,col-1] = 9 then k := k + 1; if Pole[row+1,col] = 9 then k := k + 1; if Pole[row+1,col+1] = 9 then k := k + 1; Pole[row,col] := k; end; status := 0; // начало игры nMin := 0; // нет обнаруженных мин nFlag := 0; // нет флагов end; // Рисует мину Procedure Mina(Canvas : TCanvas; x, y : integer); begin with Canvas do begin Brush.Color := clGreen; Pen.Color := clBlack; Rectangle(x+16,y+26,x+24,y+30); Rectangle(x+8,y+30,x+16,y+34); Rectangle(x+24,y+30,x+32,y+34); Pie(x+6,y+28,x+34,y+44,x+34,y+36,x+6,y+36); MoveTo(x+12,y+32); LineTo(x+26,y+32); MoveTo(x+8,y+36); LineTo(x+32,y+36); MoveTo(x+20,y+22); LineTo(x+20,y+26); MoveTo(x+8, y+30); LineTo(x+6,y+28); MoveTo(x+32,y+30); LineTo(x+34,y+28); end; end; // Рисует флаг Procedure Flag( Canvas : TCanvas; x, y : integer); var p : array [0..3] of TPoint; // координаты флажка и нижней точки древка m : array [0..4] of TPoint; // буква М begin // зададим координаты точек флажка p[0].x:=x+4; p[0].y:=y+4; p[1].x:=x+30; p[1].y:=y+12; p[2].x:=x+4; p[2].y:=y+20; p[3].x:=x+4; p[3].y:=y+36; // нижняя точка древка m[0].x:=x+8; m[0].y:=y+14; m[1].x:=x+8; m[1].y:=y+8; m[2].x:=x+10; m[2].y:=y+10; m[3].x:=x+12; m[3].y:=y+8; m[4].x:=x+12; m[4].y:=y+14; with Canvas do begin // установим цвет кисти и карандаша Brush.Color := clRed; Pen.Color := clRed; Polygon(p); // флажок // древко Pen.Color := clBlack; MoveTo(p[0].x, p[0].y); LineTo(p[3].x, p[3].y); // буква М Pen.Color := clWhite; Polyline(m); Pen.Color := clBlack; end; end; // выбор из меню ? команды О программе procedure TForm1.N4Click(Sender: TObject); begin AboutForm.Top := Trunc(Form1.Top + Form1.Height/2 - AboutForm.Height/2); AboutForm.Left := Trunc(Form1.Left +Form1.Width/2 - AboutForm.Width/2); AboutForm.ShowModal; end; procedure TForm1.Form1Create(Sender: TObject); var row,col : integer; begin // В неотображаемые эл-ты массива, которые соответствуют // клеткам по границе игрового поля запишем число -3. // Это значение используется функцией Open для завершения // рекурсивного процесса открытия соседних пустых клеток. for row :=0 to MR+1 do for col :=0 to MC+1 do Pole[row,col] := -3; NewGame(); // "разбросать" мины Form1.ClientHeight := H*MR + 1; Form1.ClientWidth := W*MC + 1; end; // нажатие кнопки мыши на игровом поле procedure TForm1.Form1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var row, col : integer; begin if status = 2 // игра завершена then exit; if status = 0 then // первый щелчок status := 1; // преобразуем координаты мыши в индексы // клетки поля row := Trunc(y/H) + 1; col := Trunc(x/W) + 1; if Button = mbLeft then begin if Pole[row,col] = 9 then begin // открыта клетка, в которой есть мина Pole[row,col] := Pole[row,col] + 100; status := 2; // игра закончена ShowPole(Form1.Canvas, status); end else if Pole[row,col] < 9 then Open(row,col); end else if Button = mbRight then if Pole[row,col] > 200 then begin // уберем флаг и закроем клетку nFlag := nFlag - 1; Pole[row,col] := Pole[row,col] - 200; // уберем флаг x := (col-1)* W + 1; y := (row-1)* H + 1; Canvas.Brush.Color := clLtGray; Canvas.Rectangle(x-1,y-1,x+W,y+H); end else begin // поставить в клетку флаг nFlag := nFlag + 1; if Pole[row,col] = 9 then nMin := nMin + 1; Pole[row,col] := Pole[row,col]+ 200; // поставили флаг if (nMin = NM) and (nFlag = NM) then begin status := 2; // игра закончена ShowPole(Form1.Canvas, status); end else Kletka(Form1.Canvas, row, col, status); end; end; // Выбор меню Новая игра procedure TForm1.N1Click(Sender: TObject); begin NewGame(); ShowPole(Form1.Canvas,status); end; // выбор из меню ? команды Справка procedure TForm1.N3Click(Sender: TObject); var HelpFile : string; // файл справки HelpTopic : string; // раздел справки pwHelpFile : PWideChar; // файл справки (указатель на WideChar строку) pwHelpTopic : PWideChar; // раздел (указатель на WideChar строку) begin HelpFile := 'saper.chm'; HelpTopic := 'saper_02.htm'; // выделить память для WideChar строк GetMem(pwHelpFile, Length(HelpFile) * 2); GetMem(pwHelpTopic, Length(HelpTopic)*2); // преобразовать Ansi строку в WideString строку pwHelpFile := StringToWideChar(HelpFile,pwHelpFile,MAX_PATH*2); pwHelpTopic := StringToWideChar(HelpTopic,pwHelpTopic,32); // вывести справочную информацию Form1.Hhopen1.OpenHelp(pwHelpFile,pwHelpTopic); end; procedure TForm1.Form1Paint(Sender: TObject); begin ShowPole(Form1.Canvas, status); end; end.
Последние комментарии
5 дней 9 часов назад
1 неделя 1 день назад
2 недели 3 дня назад
4 недели 1 день назад
5 недель 3 дня назад
7 недель 4 дня назад
10 недель 2 дня назад
10 недель 6 дней назад
11 недель 2 дня назад
12 недель 47 минут назад