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 });