Minesweeper
Материал из Department of Theoretical and Applied Mechanics
Описание[править]
Реализация компьютерной игры "Сапер" на языке JavaScript.
Сапер — это игра головоломка, где игроку нужно разминировать минное поле, помечая флажками ячейки, на которых могут быть мины, для их обнаружения на соседних пустых клетках есть подсказки в виде чисел.
Исполнитель: Северюхина Анастасия
Группа 3630103/90003 Высшая школа Теоретической механики
Визуализация[править]
Код программы[править]
Код программы на языке JavaScript:
1 $(document).ready(function() {
2 // 'Возвращает случайное целое число между min (включительно) и max (не включая max)
3 function getRandomInt(min, max) {
4 return Math.floor(Math.random() * (max - min)) + min;
5 }
6
7 var table_main = document.getElementById('sapper_table_main');
8 var count_bomb = 90;
9 var count_tr = 10;//ВЫСОТА
10 var count_tr_td = 10;//ШИРИНА
11 var count_td = count_tr * count_tr_td;//ОБЩЕЕ КОЛ-ВО ЯЧЕЕК
12 var count_cell_close = count_td;//КОЛ-ВО ОТКРЫТЫХ ЯЧЕЕК
13 var end_game = false;
14 var arr_count_td = [];
15 var obj_all_td = {};
16 var span_minutes = $('span#sapper_minutes');
17 var span_seconds = $('span#sapper_seconds');
18 var sapper_timer;
19
20 document.querySelector('input[name="radioOptions"]:checked').value;
21
22
23 function fill_obj_all_td() { //даем свойства ячейкам
24 for (var i = 0; i < count_td; i++) {
25 arr_count_td.push(i);
26 obj_all_td[i] = {}
27 obj_all_td[i]['bomb'] = false;
28 obj_all_td[i]['numeric'] = false
29 obj_all_td[i]['open'] = false
30 obj_all_td[i]['flag'] = false
31 if (i % count_tr_td == 0 || i == 0) {
32 obj_all_td[i]['edge'] = 'left';
33 } else if ((i + 1) % count_tr_td == 0) {
34 obj_all_td[i]['edge'] = 'right';
35 } else {
36 obj_all_td[i]['edge'] = false;
37 }
38 }
39 }
40
41 function add_bomb_obj_all_td() { //создаем бомбы
42 var number_bomb;
43 for (var i = 0; i < count_bomb; i++) {
44 number_bomb = Math.round(getRandomInt(0, arr_count_td.length));
45 number_bomb = arr_count_td.splice(number_bomb, 1)[0];
46 obj_all_td[number_bomb]['bomb'] = true;
47 }
48 }
49
50
51 function add_siblings_and_numeric() { //создаем циферки
52 for (var td_i in obj_all_td) {
53 var td_i_num = Number(td_i); //индекс рассматриваемого элемента
54 //индексы соседних элементов
55 var arr_sibling_number_td = [td_i_num - 1, td_i_num + 1, td_i_num - count_tr_td, td_i_num - count_tr_td - 1, td_i_num - count_tr_td + 1, td_i_num + count_tr_td, td_i_num + count_tr_td - 1, td_i_num + count_tr_td + 1];
56 var arr_sibling_td = [];
57 for (var j = 0; j < arr_sibling_number_td.length; j++) {
58 if (arr_sibling_number_td[j] >= 0 && arr_sibling_number_td[j] < count_td) {
59 if (!obj_all_td[td_i]['edge']) { //если не крайний
60 arr_sibling_td.push(arr_sibling_number_td[j]); //добавляем номер соседа
61 if (obj_all_td[td_i]['bomb'] && !obj_all_td[arr_sibling_number_td[j]]['bomb']) { //элемент бомба, а сосед не бомба
62 obj_all_td[arr_sibling_number_td[j]]['numeric'] = true //тогда сосед число
63 }
64 } else if (obj_all_td[td_i]['edge'] === 'left' && obj_all_td[arr_sibling_number_td[j]]['edge'] !== 'right') { //если край левый и сосед не на правом краю
65 arr_sibling_td.push(arr_sibling_number_td[j]); //добавляем номер соседа
66 if (obj_all_td[td_i]['bomb'] && !obj_all_td[arr_sibling_number_td[j]]['bomb']) {
67 obj_all_td[arr_sibling_number_td[j]]['numeric'] = true
68 }
69 } else if (obj_all_td[td_i]['edge'] === 'right' && obj_all_td[arr_sibling_number_td[j]]['edge'] !== 'left') {
70 arr_sibling_td.push(arr_sibling_number_td[j]);
71 if (obj_all_td[td_i]['bomb'] && !obj_all_td[arr_sibling_number_td[j]]['bomb']) {
72 obj_all_td[arr_sibling_number_td[j]]['numeric'] = true
73 }
74 }
75
76 }
77 }
78 obj_all_td[td_i]['siblings'] = arr_sibling_td; //все соседи
79
80 var arr_sibling_direct_num_td = [td_i_num - 1, td_i_num + 1, td_i_num - count_tr_td, td_i_num + count_tr_td];
81 var arr_sibling_direct_td = [];
82 for (var j = 0; j < arr_sibling_direct_num_td.length; j++) {
83 if (arr_sibling_direct_num_td[j] >= 0 && arr_sibling_direct_num_td[j] < count_td) {
84 if (!obj_all_td[td_i]['edge']) { //если элемент не край
85 arr_sibling_direct_td.push(arr_sibling_direct_num_td[j]); //добавляем номер соседа
86 } else if (obj_all_td[td_i]['edge'] === 'left' && obj_all_td[arr_sibling_direct_num_td[j]]['edge'] !== 'right') {
87 arr_sibling_direct_td.push(arr_sibling_direct_num_td[j]);
88 } else if (obj_all_td[td_i]['edge'] === 'right' && obj_all_td[arr_sibling_direct_num_td[j]]['edge'] !== 'left') {
89 arr_sibling_direct_td.push(arr_sibling_direct_num_td[j]);
90 }
91 }
92 }
93 obj_all_td[td_i]['siblings_direct'] = arr_sibling_direct_td; //прямые соседи
94 }
95 }
96
97
98 function createTable() { //создали таблицу
99 var n = 0;
100 for (var i = 0; i < count_tr; i++) {
101 var tr = document.createElement('tr');
102 for (var j = 0; j < count_tr_td; j++) {
103 var td = document.createElement('td');
104 if (obj_all_td[n]['bomb']) {
105 obj_all_td[n]['text'] = '<img src="images/bomb.png" />';
106 } else if (obj_all_td[n]['numeric']) {
107 var num_col = 0;
108 for (var m = 0; m < obj_all_td[n]['siblings'].length; m++) {
109 if (obj_all_td[obj_all_td[n]['siblings'][m]]['bomb'])
110 num_col++;
111 }
112 obj_all_td[n]['text'] = num_col; //количество бомб в соседних ячейках
113 }
114
115 if (!obj_all_td[n]['bomb'] && !obj_all_td[n]['numeric']) {
116 obj_all_td[n]['text'] = ''; //это пустая клеточка
117 }
118
119 tr.appendChild(td); //к строке добавили ячейку
120 n++;
121 }
122 table_main.appendChild(tr); //к таблице добавили строку
123 }
124 }
125
126 fill_obj_all_td();
127 add_bomb_obj_all_td();
128 add_siblings_and_numeric();
129 createTable();
130
131 function createNewTable(){
132 span_seconds.text('00'); //обнуляем время
133 span_minutes.text('00');
134 $('.sapper_message').remove(); //убираем сообщение
135 if (document.getElementById('easy').checked) {
136 count_tr = 10;
137 count_tr_td = 10;
138 count_bomb = 10;
139 } else if (document.getElementById('medium').checked) {
140 count_tr = 16;
141 count_tr_td = 16;
142 count_bomb = 40;
143 } else if (document.getElementById('hard').checked) {
144 count_tr = 22;
145 count_tr_td = 22;
146 count_bomb = 99;
147 }
148 count_td = count_tr * count_tr_td;
149 count_cell_close = count_td;
150 end_game = false;
151 arr_count_td = [];
152 obj_all_td = {};
153
154 fill_obj_all_td();
155 add_bomb_obj_all_td();
156 add_siblings_and_numeric();
157
158 $(table_main).empty();
159 createTable();
160 td_all = $(table_main).find('td');
161 }
162
163 ////////////
164
165 var td_all = $(table_main).find('td');
166
167 function openCellRecurs(td, number) {
168 openCellOne(td, number)
169 if (obj_all_td[number]['bomb'] === false && obj_all_td[number]['numeric'] === false) { //если это не бомба и не цифра
170 for (var i = 0; i < obj_all_td[number]['siblings'].length; i++) { //кол-во соседей
171 if (obj_all_td[obj_all_td[number]['siblings'][i]]['bomb'] === false && obj_all_td[obj_all_td[number]['siblings'][i]]['numeric'] === false && obj_all_td[obj_all_td[number]['siblings_direct'][i]]['open'] === false) {
172 openCellRecurs(td_all.eq(obj_all_td[number]['siblings'][i]), obj_all_td[number]['siblings'][i]); //открываем соседей
173 } else if (obj_all_td[obj_all_td[number]['siblings'][i]]['numeric'] === true && obj_all_td[obj_all_td[number]['siblings'][i]]['open'] === false) {
174 openCellOne(td_all.eq(obj_all_td[number]['siblings'][i]), obj_all_td[number]['siblings'][i]); //открываем соседей
175 }
176 }
177 }
178 }
179
180 function openCellOne(td, number) {
181 if (!obj_all_td[number]['open']) {
182 td.css('background', 'none'); //отменяем заливку
183 td.html(obj_all_td[number]['text']); //картинка бомбы, циферка, пусто
184 obj_all_td[number]['open'] = true;
185 count_cell_close--; //уменьшаем количество закрытых ячеек
186 if (count_cell_close == count_bomb && !end_game) {
187 end_game = true;
188 window.clearInterval(sapper_timer);
189 showMessage('Победа!!!<br>�'ремя: ' + $('div#sapper_time').html(), 'green');
190 openAll();
191 }
192 }
193 }
194
195 $(table_main).on('click', 'td', function () {
196 var this_number = $(table_main).find('td').index($(this)); //ищем индекс ячейки которую открываем
197 if (count_cell_close === count_td) {
198 goTimer(); //запускаем таймер
199 }
200 if ((count_cell_close === count_td)&(obj_all_td[this_number]['bomb'])){
201 while (obj_all_td[this_number]['bomb']){
202 createNewTable();
203 }
204 openCellOne(td_all.eq(this_number), this_number)// ссылка на открытую ячейку
205 }
206 if (obj_all_td[this_number]['bomb']) { //если это бомба
207 end_game = true;
208 window.clearInterval(sapper_timer); //останавливаем таймер
209 openAll(); //открываем все ячейки
210 $(this).css('background', 'red'); //меняем заливку
211 showMessage('Вы Проиграли<br>'Время: ' + $('div#sapper_time').html(), 'red')
212 } else {
213 // showMessage('open', 'red')
214 openCellRecurs($(this), this_number); //рекурсивно открываем
215 }
216 })
217
218 $(table_main).on('contextmenu', 'td', function (e) { //если нажимаем правой кнопкой
219 e.preventDefault();
220 var this_number = $(table_main).find('td').index($(this));
221 if (!obj_all_td[this_number]['open']) {
222 if (!obj_all_td[this_number]['flag']) {
223 obj_all_td[this_number]['flag'] = true; //делаем флажок
224 $(this).html('<img src="images/flag.png" />')
225 } else {
226 obj_all_td[this_number]['flag'] = false;
227 $(this).html('') //убираем флажок
228 }
229 }
230
231
232 })
233
234 function openAll() { // открываем все ячейки
235 for (var i = 0; i < count_td; i++) {
236 openCellOne(td_all.eq(i), i);
237 }
238 }
239
240
241 $('#sapper_new_game').on('click', function () { // кнопочка новая игра
242 createNewTable();
243 window.clearInterval(sapper_timer);
244 })
245
246 $('#easy').on('click', function () {
247 createNewTable();
248 window.clearInterval(sapper_timer);
249 })
250 $('#medium').on('click', function () {
251 createNewTable();
252 window.clearInterval(sapper_timer);
253 })
254 $('#hard').on('click', function () {
255 createNewTable();
256 window.clearInterval(sapper_timer);
257 })
258
259
260
261 function showMessage(message, color) { //сообщение
262 var table_main_width = $(table_main).width();
263 var table_main_height = $(table_main).height();
264 var divMessage = $('<div></div>', {'class': 'sapper_message'}).appendTo($('div#sapper_wrapper'));
265 divMessage.css({'width': table_main_width + 'px', 'height': table_main_height + 'px'})
266 var pMessage = $('<p></p>', {'html': message}).appendTo(divMessage);
267 pMessage.css('color', color);
268 }
269
270 function goTimer() { //таймер
271 span_seconds.text('00');
272 span_minutes.text('00');
273 sapper_timer = window.setInterval(function () {
274 var num_seconds = Number(span_seconds.text()) + 1;
275 var num_minutes = Number(span_minutes.text());
276 if (num_seconds < 10) {
277 num_seconds = '0' + num_seconds;
278 } else if (num_seconds > 59) {
279 num_seconds = '00';
280 num_minutes++;
281 }
282
283 if (num_minutes < 10) {
284 num_minutes = '0' + num_minutes;
285 }
286
287 span_seconds.text(num_seconds);
288 span_minutes.text(num_minutes);
289 }, 1000);
290 }
291
292 });