Форум программистов, компьютерный форум, киберфорум
Delphi для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
Результаты опроса: Можно ли построить беспроигрышный алгоритм для игры "Сапер"?
Да. 9 20.45%
Нет. 20 45.45%
Зависит от отношения количества бомб к количеству клеток поля. 15 34.09%
Голосовавшие: 44. Вы ещё не голосовали в этом опросе

 
 
Рейтинг 4.67/168: Рейтинг темы: голосов - 168, средняя оценка - 4.67
Пробующий
 Аватар для galileopro
185 / 98 / 10
Регистрация: 28.04.2009
Сообщений: 1,101

Сапер на Delphi

13.08.2009, 22:00. Показов 32347. Ответов 127
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Хочу написать сапера на делфи. Принимаю любую помощь и предложения.
1
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
13.08.2009, 22:00
Ответы с готовыми решениями:

Сапер
Кто подскажет как сделать в сапере чтобы он выводил в конце игры время за которое ты прошел, и чтобы записывал таблицу рекордов, как в...

Сапер
Ребят не пойму как правильно сделать рекурсию, мой алгоритм не правильный. Бывает просто 0 откроет и все, бывает нули еще рядом не открытые...

Сапер
Добрый День. Пишу сапера и столкнулся с проблемами. Компилируется удачно и запускается тоже,но вот при нажатии кнопки ошибки так и сыпятся....

127
Пробующий
 Аватар для galileopro
185 / 98 / 10
Регистрация: 28.04.2009
Сообщений: 1,101
15.08.2009, 20:01  [ТС]
Студворк — интернет-сервис помощи студентам
Так я ж пытаюсь новое сделать)

Добавлено через 4 минуты 12 секунд
Кстати надо звуки найти.

Добавлено через 21 час 56 минут 27 секунд
Ребята помогите разобраться с процедурой Open(). Я как можно лучше заполнил программу комментариями, чтобы понятно было, что где происходит. Там проблема такая, что если строки
Delphi
1
2
//Form1.ImageList1.Draw(Form1.Canvas,(row-1)*VarLeft,(col-1)*VarTop,0,true);
//flag:=true;
не коментить, то открываются не все клетки(которые должны были открытьсяч по логике игры)
А если оставить в коментариях, то открываютяс все клетки без бомб(((((
Вот код. Там вроде все ясно что к чему. А ошибку не найду(
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, jpeg, ExtCtrls, Buttons, ImgList;
 
type
  TForm1 = class(TForm)
    BitBtn1: TBitBtn;
    ImageList1: TImageList;
    procedure BitBtn1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
const VarLeft =16;
      VarTop = 16;
      n=10; //øèðèíà ìèííîãî ïîëÿ
      m=10; //âûñîòà ìèííîãî ïîëÿ
      b=10; //êîëè÷åñòâî ìèí
var
  i, j : Integer;
  Pole:array[1..n,1..m] of byte; //èãðîâîå ïîëå
  {åñëè 0 - êëåòêà ïóñòàÿ
  åñëè 1 - êëåòêà ñ åäåíèöåé(âîêðóã íå¸ òîëüêî îäíà áîìáà)
  åñëè 2 - êëåòêà ñ äâîéêîé(âîêðóã äâå áîìáû)
  åñëè 3 - êëåòêà ñ òðîéêîé(âîêðóã íå¸ 3 áîìáû)
  åñëè 4 - êëåòêà ñîäåðæèò áîìáó
  åñëè 5 - êëåòêà íå îòêðûòà(ñåðîãî öâåòà) }
  flag:boolean; //åñëè true, òî èãðà çàâåðøåíà
 
 Procedure Open( row, col : integer);
    begin
    if(flag=false) then
       if ((Mass[row,col]= 0)or(Mass[row,col]= 1)or(Mass[row,col]= 2)or(Mass[row,col]= 3)) then //íåò ìèíû, çíà÷èò ìîæíî îòêðûâàòü êëåòêè
            begin
 Form1.ImageList1.Draw(Form1.Canvas,(row-1)*VarLeft,(col-1)*VarTop,mass[row,col],true);
      mass[row,col]:=10;  //ýòà êëåòêà óæå ïðîâåðåíà
 if(col>1)and(row>1)and(col<m)and(row<n) then begin
               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;
             end           
       else begin
//Form1.ImageList1.Draw(Form1.Canvas,(row-1)*VarLeft,(col-1)*VarTop,0,true);
//flag:=true;
            end;
 
 end;
procedure TForm1.BitBtn1Click(Sender: TObject);
var _i,k,_n,_m:integer;
label h;
begin
for i:=1 to n do
 for j:=1 to m do mass[i,j]:=0;
 
Form1.Refresh;
 
Randomize;
for _i:=1 to b do begin
h: _n:=Random(n);
_m:=Random(m);
 if(mass[_n,_m]<>4)then mass[_n,_m]:=4
                   else goto h;
      end;
 
for i:=2 to n-1 do  //ðàñ÷åò êîëè÷åñòâà áîìá âîêðóã òåêóùåé êëåòêè áåç ó÷åòà ñòîðîí
 for j:=2 to m-1 do
      if (mass[i,j]<>4)then begin
                           k:=0;
                          if (mass[i+1,j]=4) then inc(k);
                          if (mass[i,j+1]=4) then inc(k);
                          if (mass[i+1,j+1]=4) then inc(k);
                          if (mass[i-1,j]=4) then inc(k);
                          if (mass[i,j-1]=4) then inc(k);
                          if (mass[i-1,j-1]=4) then inc(k);
                          if (mass[i+1,j-1]=4) then inc(k);
                          if (mass[i-1,j+1]=4) then inc(k);
                          if(k<3)then
                           mass[i,j]:=k;
                              end;
 
for i:=1 to n do   // ïðîâåðÿåì ñîòîíû ïðÿìîóãîëüíèêà
 if (mass[i,m]<>4)then begin
      k:=0;
     if (mass[i+1,m]=4) then inc(k);
     if (mass[i+1,m-1]=4) then inc(k);
     if (mass[i,m-1]=4) then inc(k);
     if (mass[i-1,m-1]=4) then inc(k);
     if (mass[i-1,m]=4) then inc(k);
      mass[i,m]:=k;
          end;
 
for i:=1 to n do
 if (mass[i,1]<>4)then begin
      k:=0;
     if (mass[i+1,1]=4) then inc(k);
     if (mass[i+1,2]=4) then inc(k);
     if (mass[i,2]=4) then inc(k);
     if (mass[i-1,2]=4) then inc(k);
     if (mass[i-1,1]=4) then inc(k);
      mass[i,1]:=k;
          end;
          
for j:=1 to m do
 if (mass[1,j]<>4)then begin
      k:=0;
     if (mass[1,j+1]=4) then inc(k);
     if (mass[2,j+1]=4) then inc(k);
     if (mass[2,j]=4) then inc(k);
     if (mass[2,j-1]=4) then inc(k);
     if (mass[1,j-1]=4) then inc(k);
      mass[1,j]:=k;
          end;
 
for j:=1 to m do
 if (mass[n,j]<>4)then begin
      k:=0;
     if (mass[n,j+1]=4) then inc(k);
     if (mass[n-1,j+1]=4) then inc(k);
     if (mass[n-1,j]=4) then inc(k);
     if (mass[n-1,j-1]=4) then inc(k);
     if (mass[n,j-1]=4) then inc(k);
      mass[n,j]:=k;
          end;
 
for i:=1 to n do   //çàïîëíÿåì ñåðûìè êíîïî÷êàìè âíà÷àëå
 for j:=1 to m do
    Form1.ImageList1.Draw(Form1.Canvas,(i-1)*VarLeft,(j-1)*VarTop,5,true);
 
end;
 
procedure TForm1.FormCreate(Sender: TObject);
begin
Form1.Width:=300;
Form1.Height:=400;
end;
 
 
 
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
if(Button=mbLeft)and(trunc(X/VarLeft)>-1)and(trunc(X/VarLeft)<10)and(trunc(Y/VarTop)>-1)and(trunc(Y/VarTop)<10)then begin
 flag:=false;
Open(trunc(X/VarLeft)+1,trunc(Y/VarTop)+1);
end;
end;
 
end.
0
Пробующий
 Аватар для galileopro
185 / 98 / 10
Регистрация: 28.04.2009
Сообщений: 1,101
15.08.2009, 20:04  [ТС]
Вот архивчик. Кстати это можно рассматривать как первую демку)7.rar
0
Почетный модератор
 Аватар для Puporev
64320 / 47616 / 32743
Регистрация: 18.05.2008
Сообщений: 115,167
15.08.2009, 20:10
Игры пока никакой нет, да и правая клавиша не задействована.
0
Пробующий
 Аватар для galileopro
185 / 98 / 10
Регистрация: 28.04.2009
Сообщений: 1,101
15.08.2009, 20:16  [ТС]
Да. Но если даже первые клетки как надо не открывает, то смысл двигаться дальше) По логике, ели применять эту рекурсивную процедуру, то она откроет ВСЕ клетки без бомб, так как она будет открывать вокруг КАЖДОЙ клетки, все клетки без бомб, а зачем нам такое? Может там не рекурсией?
0
Человек
 Аватар для mustardandrew
97 / 82 / 7
Регистрация: 16.06.2009
Сообщений: 229
15.08.2009, 21:00
2 galileopro
Там 100% рекурсия. Нужно просто поставить больше мин, и ты увидеш результат.
1
Почетный модератор
 Аватар для Puporev
64320 / 47616 / 32743
Регистрация: 18.05.2008
Сообщений: 115,167
15.08.2009, 21:09
Вот упрощенный вариант без справки, абоута и еще кое-что убрал. Попробуйте все же разобраться в алгоритме, иначе Вы не напишете свою игру. Понажимайте поля, посмотрите все варианты.
Особо процедуру Open. При ее рекурсивном вызове сразу идет проверка на пустая клетка или нет, и все клетки не откроет. Кроме того вокруг поля предусмотрен "забор" из клеток со значением -3, край поля, тоже надо чтоб не писать лишние проверки.
Вложения
Тип файла: rar Сапер упрощенный.rar (165.0 Кб, 119 просмотров)
0
Пробующий
 Аватар для galileopro
185 / 98 / 10
Регистрация: 28.04.2009
Сообщений: 1,101
15.08.2009, 21:14  [ТС]
А вот оно что. Там забор, а как он вычисляется? Ладно щас посмотрю
0
Человек
 Аватар для mustardandrew
97 / 82 / 7
Регистрация: 16.06.2009
Сообщений: 229
15.08.2009, 21:18
Вот мой сапер.
Может не лучший по оптимизации кода и красоте, но может пригодица
Вложения
Тип файла: rar saper.rar (185.4 Кб, 114 просмотров)
1
Пробующий
 Аватар для galileopro
185 / 98 / 10
Регистрация: 28.04.2009
Сообщений: 1,101
16.08.2009, 22:14  [ТС]
Вот я внимательно почитал єту программу, и не могу понять одной вещи: Єта рекурсивна процедура работает по такому принципу:
1) открівает текущую тоочку,
2) если в ней нет мині, то открівает все точки без мин вокруг текущей
3) Вокруг каждой из текущих точек тоже начинают откріваться все без бомб по тому же принципу
4) Так рекурсия продолжается пока не достигается забор из значений -3 вокруг игрового поля.
Так вот я уже сколько анализировал єто, и віходит, что так, постепенно откроются все точки без бомб. Она же останавливается только на краю поля и все. Но на деле открывается определенное к-во точек, никак не все. Вот почему не пойму.
0
Почетный модератор
 Аватар для Puporev
64320 / 47616 / 32743
Регистрация: 18.05.2008
Сообщений: 115,167
16.08.2009, 22:18
2) если в ней нет мині, то открівает все точки без мин вокруг текущей
Это не так. Если она пустая, т.е. в ней нет ни мины ни цифры. Совсем пустая, белая, тогда открывает и проверяет соседние. Если в клетке есть цифра, дальше не проверяет, если край, тоже дальше не проверяет.
0
Человек
 Аватар для mustardandrew
97 / 82 / 7
Регистрация: 16.06.2009
Сообщений: 229
17.08.2009, 12:45
Puporev прав.
Границей для етого алгоритма есть ячейка с цифрой.
0
Пробующий
 Аватар для galileopro
185 / 98 / 10
Регистрация: 28.04.2009
Сообщений: 1,101
17.08.2009, 13:16  [ТС]
Либо край поля

Добавлено через 29 минут 52 секунды
Вот вроде работает. Плиз кто-нибудь потестите, а то я проверял, но я ж не опытный в эотм деле(создании игр), всяких там особых ситуаций не знаю.
И еще: почему у меня, если форму свернуть, а потом развернуть, то все пропадает? И как это исправить?
0
Пробующий
 Аватар для galileopro
185 / 98 / 10
Регистрация: 28.04.2009
Сообщений: 1,101
17.08.2009, 13:19  [ТС]
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, jpeg, ExtCtrls, Buttons, ImgList;
 
type
  TForm1 = class(TForm)
    BitBtn1: TBitBtn;
    ImageList1: TImageList;
    procedure BitBtn1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
const VarLeft =16;
      VarTop = 16;
      n=10; //ширина минного поля
      m=10; //высота минного поля
      b=10; //количество мин
var
  i, j : Integer;
  Pole:array[1..n,1..m] of byte; //игровое поле
  {если 0 - клетка пустая
  если 1 - клетка с еденицей(вокруг неё только одна бомба)
  если 2 - клетка с двойкой(вокруг две бомбы)
  если 3 - клетка с тройкой(вокруг неё 3 бомбы)
  если 4 - клетка содержит бомбу
  если 5 - клетка не открыта(серого цвета)
  если 6 - клетка содержит флаг
  если 7 - клетка образует "забор"
  если 8 - клетка уже открыта }
  flag:integer; //флаг состояния игры
  {-1 - игра не начата
  1- игра в процессе
  2- выигрыш
  3 - проигрыш
  }
  b_o:integer;//к-во открытых бомб
  Pole_flags:array[1..n,1..m] of byte; //поле для флажков
 
 function Open_pole():integer;
 var i,j:integer;
     kol:integer;
  begin
  kol:=0;
   for i:=1 to n do
    for j:=1 to m do
if(Pole[i,j]=8)then inc(kol);
  Open_pole:=kol;
  end;
 
 Procedure Open( row, col : integer);
    begin
    if(flag=1)then begin
    case Pole[row,col] of
    0:if(Pole[row,col]<>8) then
            begin
 Form1.ImageList1.Draw(Form1.Canvas,(row-1)*VarLeft,(col-1)*VarTop,Pole[row,col],true);
      Pole[row,col]:=8;  //эта клетка уже проверена и открыта
 if(col>1)and(row>1)and(col<m)and(row<n) then begin
           if(col<>1)then Open(row,col-1);
           if(row<>1)then Open(row-1,col);
           if(col<>m)then Open(row,col+1);
           if(row<>n)then Open(row+1,col);
               //примыкающие диагонально
          if(row<>1)and(col<>1)then  Open(row-1,col-1);
          if(row<>1)and(col<>m)then  Open(row-1,col+1);
          if(row<>n)and(col<>1)then  Open(row+1,col-1);
          if(row<>n)and(col<>m)then  Open(row+1,col+1);
               end;
             end;
    1..3:begin
    Form1.ImageList1.Draw(Form1.Canvas,(row-1)*VarLeft,(col-1)*VarTop,Pole[row,col],true);
    Pole[row,col]:=8;  //эта клетка уже проверена и открыта
    end;
 
    4:begin
    Form1.ImageList1.Draw(Form1.Canvas,(row-1)*VarLeft,(col-1)*VarTop,Pole[row,col],true);
    flag:=3;
    Form1.Caption:='Lyise';
    Pole[row,col]:=8;  //эта клетка уже проверена и открыта
      end;
      end;
      end;
      if(n*m-open_pole=b)then begin
                    flag:=2; //ура выигрыш
                    Form1.Caption:='Win';
                              end;
 end;  
 
 procedure DrawPole(MyCanvas:TCanvas; index:integer; i,j:integer);
 begin
    Form1.ImageList1.Draw(MyCanvas,(i-1)*VarLeft,(j-1)*VarTop,index,true);
 end;
 
 procedure NewGame();
 var _i,k,_n,_m:integer;
 
 begin
for i:=1 to n do  //заполним игровое поле серыми кнопочками
 for j:=1 to m do Pole[i,j]:=5;
 
for i:=1 to n do  //заполним игровое поле серыми кнопочками
 for j:=1 to m do Pole_flags[i,j]:=0;
 
flag:=-1; // игровой процесс не начат
b_o:=0;
 end;
 
procedure TForm1.BitBtn1Click(Sender: TObject);
var i,j:integer;
begin
Form1.Caption:='NewGame';
NewGame();
Form1.Refresh;
  for i:=1 to n do
 for j:=1 to m do
DrawPole(Form1.Canvas,Pole[i,j],i,j);
 
end;
 
procedure TForm1.FormCreate(Sender: TObject);
begin
Form1.Width:=300;
Form1.Height:=400;
end;
 
 
 
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
  var _i,_n,_m,_x,_y,k:byte;
  label h;
begin
_x:=trunc(X/VarLeft);
_y:=trunc(Y/VarTop);
if(Button=mbLeft)and(_x>-1)and(_x<10)and(_y>-1)and(_y<10)then begin
 if(flag=-1)then begin // если игровой процесс еще не начат
      flag:=1;// игровой процесс начат
 
  for i:=1 to n do  //заполним игровое поле нулями
 for j:=1 to m do Pole[i,j]:=0;
 
 randSeed:=_x*_y;  //инициализация ГСЧ
  for _i:=1 to b do begin
  h: _n:=Random(n)+1;
   _m:=Random(m)+1;
   if(Pole[_n,_m]<>4)then Pole[_n,_m]:=4
                   else goto h;
                    end;
 
for i:=1 to n do  //расчет количества бомб вокруг текущей клетки без учета сторон
 for j:=1 to m do
      if (Pole[i,j]<>4)then begin
      k:=0;
  if (Pole[i+1,j]=4)then inc(k);
  if (Pole[i,j+1]=4)then inc(k);
  if (Pole[i+1,j+1]=4)then inc(k);
  if (Pole[i-1,j]=4)then inc(k);
  if (Pole[i,j-1]=4)then inc(k);
  if (Pole[i-1,j-1]=4)then inc(k);
  if (Pole[i+1,j-1]=4)then inc(k);
  if (Pole[i-1,j+1]=4)then inc(k);
 Pole[i,j]:=k;
           end;
           end;
              Open(_x+1,_y+1);
 
end;
if(Button=mbRight)then begin
if(Pole[_x+1,_y+1]<>8)then begin
                     if(Pole_flags[_x+1,_y+1]=0)then begin
                                      Pole_flags[_x+1,_y+1]:=1;
                                      DrawPole(Form1.Canvas,6,_x+1,_y+1);
                                      end
                                      else begin
                                      Pole_flags[_x+1,_y+1]:=0;
                                      DrawPole(Form1.Canvas,5,_x+1,_y+1);
                                      end;
 
                       end;
         end;
end;
 
end.
Вложения
Тип файла: rar 7.rar (357.9 Кб, 117 просмотров)
0
Пробующий
 Аватар для galileopro
185 / 98 / 10
Регистрация: 28.04.2009
Сообщений: 1,101
17.08.2009, 13:20  [ТС]
Типа канвас перерисовывается? При сворачивании\разворачивании.
0
 Аватар для Jazon_deenAlt
4117 / 999 / 191
Регистрация: 09.04.2009
Сообщений: 4,223
17.08.2009, 13:41
из какой-то книги...
Вы создали неплохое приложение для просмотра графических файлов. Но теперь давайте попробуем увидеть его крупный недостаток. Не закрывая своего приложения, перейдите в какую-нибудь другую программу, например, вернитесь в Delphi. Затем, ничего там не делая, опять перейдите в свое выполняющееся приложение. Если окно программы, в которую вы уходили, целиком перекрыло окно вашего приложения, то вернувшись в него вы увидите, что картинка в окне исчезла. Если же окно вашего приложения перекрывалось только частично, то вернувшись в свое приложение вы, возможно, увидите результат, подобный представленному на рис. 4.2 б.

Вы видите, что если окно какого-то другого приложения перекрывает на время окно вашего приложения, то изображение, нарисованное на канве формы, портится. Посмотрим, как можно устранить этот недостаток.

Если окно было перекрыто и изображение испортилось, операционная система сообщает приложению, что в окружении что-то изменилось и что приложение должно предпринять соответствующие действия. Как только требуется обновление окна, для него генерируется событие OnPaint. В обработчике этого события (в нашем случае события формы) нужно перерисовать изображение.

Перерисовка может производиться разными способами в зависимости от приложения. В нашем примере можно было бы вынести объявление переменной BitMap (оператор var BitMap: TBitMap) за пределы приведенной выше процедуры, т.е. сделать эту переменную глобальной, разместив непосредственно в разделе implementation. Оператор BitMap.Free можно было бы перенести в обработчик события формы OnDestroy, происходящего в момент закрытия приложения. Тогда в течение всего времени выполнения вашего приложения вы будете иметь копию картинки в компоненте BitMap и вам достаточно ввести в обработчик события OnPaint формы всего один оператор:

Canvas.Draw(10, 10, BitMap);

Сделайте это, и увидите, что изображение на форме не портится при любых перекрытиях окон.

Помимо рассмотренного метода Draw канва имеет еще метод копирования CopyRect:

procedure CopyRect(Dest: TRect; Canvas: TCanvas; Source: TRect);

Метод копирует указанную параметром Source область изображения в канве источника изображения Canvas в указанную параметром Dest область данной канвы. Тип TRect, характеризующий прямоугольные области Source и Dest, уже описывался в разделе 3.2. Например, оператор

Canvas.CopyRect(MyRect2, Bitmap.Canvas, MyRect1);

копирует на канву формы в область MyRect2 изображение из области MyRect1 канвы компонента Bitmap.
Копирование методом CopyRect производится в режиме, установленном свойством CopyMode. По умолчанию это свойство имеет значение cmSrcCopy, что означает просто замену изображения, содержащегося ранее в области Dest, на копируемое изображение. Другие возможные значения CopyMode позволяют комбинировать изображения, но их рассмотрение выходит за рамки данной книги.

и естче...
4.3 Компоненты Image и PaintBox
Компоненты Image и PaintBox представляют собой некоторую ограниченную поверхность с канвой, на которую можно заносить изображения, как это описано в разделе 4.2. При этом компонент PaintBox, собственно говоря, не дает ничего нового по сравнению с рисованием на канве формы. Рисование на PaintBox вместо формы не имеет никаких преимуществ, кроме, может быть, некоторого облегчения в расположении одного или нескольких рисунков в площади окна.

Компонент Image много богаче по своим возможностям и удобнее, чем PaintBox. Даже при использовании описанных в разделе 4.2 приемов рисования на канве компонент Image имеет существенное преимущество: в нем не приходится думать о перерисовке изображения, испорченного из-за перекрытия данного окна другими. Все, связанное с обработкой событий OnPaint, рассмотренных в разделе 4.2, в Image осуществляется автоматически. Кроме того с помощью Image проще, чем при непосредственном рисовании на канве формы, расположить в окне приложения несколько изображений и управлять ими. При этом отпадает необходимость сложных и нудных расчетов координат канвы формы, обеспечивающих требуемое взаимное расположение изображений, т.е. в полной мере проявляются преимущества визуального программирования. Так что, вероятно, во всех случаях лучше работать с канвой Image, чем с канвой формы.
0
Пробующий
 Аватар для galileopro
185 / 98 / 10
Регистрация: 28.04.2009
Сообщений: 1,101
17.08.2009, 13:47  [ТС]
А как в
Delphi
1
MyBitmap:TBitmap
скопировать канвас?
0
Почетный модератор
 Аватар для Puporev
64320 / 47616 / 32743
Регистрация: 18.05.2008
Сообщений: 115,167
17.08.2009, 13:51
Типа канвас перерисовывается? При сворачивании\разворачивании.
У Вас в процедуре FormCreate кроме размеров формы ничего не прописано, ничего кроме самой формы и не будет. Сравните такое описание этой процедуры.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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;
Добавлено через 3 минуты 5 секунд
Или попробуйте не на канве формы рисовать а в
procedure Form1Paint(Sender: TObject);
как в предложенной мной программе.
0
Пробующий
 Аватар для galileopro
185 / 98 / 10
Регистрация: 28.04.2009
Сообщений: 1,101
17.08.2009, 14:17  [ТС]
Спасибо. просто я когда-то пятнашки делал, так там все на канве рисовалось, и вроде как-то из положения я вышел(всмысле перерисовки).

Добавлено через 19 минут 55 секунд
Вот придумал так, но не работает. Может кто скажет почему?
Delphi
1
2
3
4
MyBitMap:=TBitMap.Create;
Form1.Canvas.CopyRect(Bounds(0,0,100,100), MyBitMap.Canvas, Bounds(0, 0, 100, 100));
Form1.Canvas.Draw(10,10,MyBitMap);
MyBitMap.Free;
0
 Аватар для Jazon_deenAlt
4117 / 999 / 191
Регистрация: 09.04.2009
Сообщений: 4,223
17.08.2009, 14:32
galileopro, рисуйте на имедже и не морочте себе голову) канвас тот же но мороки меньше)
0
Пробующий
 Аватар для galileopro
185 / 98 / 10
Регистрация: 28.04.2009
Сообщений: 1,101
17.08.2009, 14:56  [ТС]
Спасиибо. Теперь все окей) Просто хотелось повыделываться и сделать что-то непохоже на предыдущее. А как мне сделать чтобы первая клетка, на которую пользователь нажимает была без бомбы?
вот мой код генерации
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const VarLeft =16;
      VarTop = 16;
      n=10; //ширина минного поля
      m=10; //высота минного поля
      b=10; //количество мин
...
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
  var _i,_n,_m,_x,_y,k:byte;
  label h;
begin
_x:=trunc(X/VarLeft);
_y:=trunc(Y/VarTop);
if(Button=mbLeft)and(_x>-1)and(_x<10)and(_y>-1)and(_y<10)then begin
 if(flag=-1)then begin // если игровой процесс еще не начат
      flag:=1;// игровой процесс начат
 
  for i:=1 to n do  //заполним игровое поле нулями
 for j:=1 to m do Pole[i,j]:=0;
 
 randSeed:=_x*_y;  //инициализация ГСЧ
  for _i:=1 to b do begin
  h: _n:=Random(n)+1;
   _m:=Random(m)+1;
   if(Pole[_n,_m]<>4)then Pole[_n,_m]:=4
                   else goto h;
                    end;
...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
17.08.2009, 14:56

Сапер
Пишу игру &quot;сапер&quot; на C++. Появилась небольшая проблемка. Всё поле храню в массиве. Бомбы разбрасываю случайно по полю, а после этого...

Сапер
Доброго времени суток! Подскажите пожалуйста, где я налажал в коде? Я запутался:( Ругается на константу двумерного массива... #include...

Сапер
package myminesapper; public class myminesapper { public static void main(String args) { int m=5; //m*n (p) int n=5; ...

Сапер на С++
Помогите написать программу. Вводим размерность поля,задаем координаты мин и соответственно их количество и программа высчитывает...

Сапер на С++
помогите пожалуйста переделать игру сапер, программа работает, осталось оформить ее с классом &quot;Field&quot;, помогите пожалуйста, а то...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Саморегулирующийся социальный контракт для сервера cross-section.
Hrethgir 14.08.2026
С кодом конечно таких глубоких размышлений пока не было, впрочем я уже привык к алгоритмизации. Суть предмета записи: снова в диалоге с нейросетью (я взял пока себе ник для учётки админа - Rector). . . .
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет: 1. Использовать системное время и дату, 2. Есть возможность вводить время и дату вручную. 3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
Часы с будильником на основе класса QLCDNumber
Uhbif79 12.08.2026
Всем добрый день, выкладываю программу часов с будильником на основе класса QLCDNumber. Здесь я пробовал самостоятельно создавал классы, впервые столкнулся с видимостью переменной одного класса из. . .
Установка MinGW GCC 16.2 и CMake
8Observer8 10.08.2026
VK Видео: https:/ / vkvideo. ru/ video-240781534_456239017 YouTube: eY5-5PyI9NM Текстовая версия
Неделя из жизни имитационной модели склада: мои кривые руки растут, откуда надо
anaschu 10.08.2026
Неделя из жизни имитационной модели склада: как я почти написал неправильную логику и что с этим делать Работаю сейчас над учебно-рабочим проектом: строю в AnyLogic имитационную модель процессов. . .
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства. Родственных связей существует 8 ступеней, такие как: p - отец P - мать q - муж Q - жена b - брат B - сестра s - сын S - дочь
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru