Сапёр (Minesweeper) на PHP
Классическая игра "Сапёр", думаю, известна всем, а ниже показан её несложный исходник, сделанный на PHP, проверено на локальном сервере XAMPP с версией PHP 8.0.
Исходник публикуется на момент написания и может измениться в работающей игре. Предполагается, что он размещается как файл типа .php в кодировке Юникода UTF-8.
Немного комментариев в исходнике есть, он достаточно понятен, чтобы расширить игру, например, введя уровни сложности, изменяемые размеры поля, сохранение данных и т.п. На самом деле, нет никакой необходимости писать подобные вещи с использованием server-side языка, достаточно клиентского Javascript, но просто, чтоб не выкидывать код :)
Посмотреть Сапёр (Minesweeper) на PHP в работе
<?php define('FIELD_WIDTH', 9); define('FIELD_HEIGHT', 9); //размерности сетки define('NOT_EXPLORED', -1); define('MINE', -2); define('FLAGGED', -3); define('FLAGGED_MINE', -4); define('ACTIVATED_MINE',-5); //состояния поля function check_mine ($field, $index) { if ($index < 1 or $index > FIELD_WIDTH * FIELD_HEIGHT) return false; return $field[$index] === MINE || $field[$index] === FLAGGED_MINE ? true : false; } function explore_field ($field) { if (!isset($_SESSION['minesweeper'][$field]) or !in_array($_SESSION['minesweeper'][$field], array(NOT_EXPLORED, FLAGGED))) { return; } $mines = 0; $fields = &$_SESSION['minesweeper']; //ссылка на длинное имя //слева: if ($field % FIELD_WIDTH !== 1) { $mines += check_mine($fields,$field - FIELD_WIDTH - 1); $mines += check_mine($fields,$field - 1); $mines += check_mine($fields,$field + FIELD_WIDTH - 1); } //снизу и сверху: $mines += check_mine($fields,$field - FIELD_WIDTH); $mines += check_mine($fields,$field + FIELD_WIDTH); //справа: if ($field % FIELD_WIDTH !== 0) { $mines += check_mine($fields,$field - FIELD_WIDTH + 1); $mines += check_mine($fields,$field + 1); $mines += check_mine($fields,$field + FIELD_WIDTH + 1); } $fields[$field] = $mines; if ($mines === 0) { if ($field % FIELD_WIDTH !== 1) { explore_field($field - FIELD_WIDTH - 1); explore_field($field - 1); explore_field($field + FIELD_WIDTH - 1); } explore_field($field - FIELD_WIDTH); explore_field($field + FIELD_WIDTH); if ($field % FIELD_WIDTH !== 0) { explore_field($field - FIELD_WIDTH + 1); explore_field($field + 1); explore_field($field + FIELD_WIDTH + 1); } } } session_start(); //начать сессию для сохранения данных if (!isset($_SESSION['minesweeper'])) { //создать сетку, если нету $_SESSION['minesweeper'] = array_fill(1, FIELD_WIDTH * FIELD_HEIGHT, NOT_EXPLORED); $number_of_mines = (int) mt_rand (0.1 * FIELD_WIDTH * FIELD_HEIGHT, 0.2 * FIELD_WIDTH * FIELD_HEIGHT); //заполнить минами от 10 до 20% поля $random_keys = array_rand ($_SESSION['minesweeper'], $number_of_mines); foreach ($random_keys as $key) { $_SESSION['minesweeper'][$key] = MINE; } $_SESSION['numberofmines'] = $number_of_mines; } if (isset($_GET['explore'])) { if (isset($_SESSION['minesweeper'][$_GET['explore']])) { switch ($_SESSION['minesweeper'][$_GET['explore']]) { case NOT_EXPLORED: explore_field($_GET['explore']); break; case MINE: $lost = 1; $_SESSION['minesweeper'][$_GET['explore']] = ACTIVATED_MINE; break; default: break; } } else { die ('Недопустимый вызов с аргументом '.$_GET['explore']); } } elseif (isset($_GET['flag'])) { if (isset($_SESSION['minesweeper'][$_GET['flag']])) { $tile = &$_SESSION['minesweeper'][$_GET['flag']]; switch ($tile) { case NOT_EXPLORED: $tile = FLAGGED; break; case MINE: $tile = FLAGGED_MINE; break; case FLAGGED: $tile = NOT_EXPLORED; break; case FLAGGED_MINE: $tile = MINE; break; default: break; } } else { die ('Недопустимый вызов с аргументом '.$_GET['flag']); } } if (!in_array(NOT_EXPLORED, $_SESSION['minesweeper']) and !in_array(FLAGGED, $_SESSION['minesweeper'])) { $won = true; } ?> <!DOCTYPE html> <html lang="ru"> <head> <meta charset="utf-8"> <title>Сапёр (Minesweeper) на PHP</title> <style> #minesweeperGame { width: 80%; margin: auto; } #minesweeperGame table { border-collapse: collapse; border: 1px solid black; } #minesweeperGame td { border-collapse: collapse; border: 1px solid black; } #minesweeperGame td, #minesweeperGame a { text-align: center; width: 1.5em; height: 1.5em; margin: 0; padding: 0; } #minesweeperGame a { display: block; color: black; text-decoration: none; font-size: 1.5em; } </style> </head> <body> <div id="minesweeperGame"> <script> function flag (number, e) { if (e.which === 2 || e.which === 3) { location = '?flag=' + number; return false; } } function showRools () { let div=document.getElementById('mineInstructionBox'); div.style.display = div.style.display == "none" ? "block" : "none"; document.getElementById('mineRools').innerHTML = (div.style.display == "block" ? 'Убрать правила' : 'Правила'); return false; } </script> <noscript> <p>Для работы приложения нужен включённый Javascript!</p> </noscript> <?php echo '<p>Всего мин: ',$_SESSION['numberofmines'],'; <span id="mineRools" onclick="showRools();">Правила</span></p> <div id="mineInstructionBox" style="display: none;"> <p>Левая кнопка мыши - открываем поля, правая - ставим флажок "мина". <br>Чтобы выиграть, нужно открыть все поля, при этом правильно указав положение всех мин. <br>Цифры внутри полей показывают, сколько мин на восьми соседних клетках.</p> </div>'."\n"; $mine_copy = $_SESSION['minesweeper']; echo '<table>'."\n"; for ($x = 1; $x <= FIELD_HEIGHT; $x++) { echo '<tr>'."\n"; for ($y = 1; $y <= FIELD_WIDTH; $y++) { echo '<td>'; $number = array_shift ($mine_copy); switch ($number) { case FLAGGED: case FLAGGED_MINE: if (!empty($lost) or !empty($won)) { echo '<a>'.($number === FLAGGED_MINE ? '*' : '.').'</a>'; } else { echo '<a href="#" onmousedown="return flag(',($x - 1) * FIELD_WIDTH + $y,',event);"'. ' oncontextmenu="return false;">?</a>'."\n"; } break; case ACTIVATED_MINE: echo '<a>:(</a>'; break; case MINE: case NOT_EXPLORED: if (!empty($lost)) { echo '<a>'.($number === MINE ? '*' : '.').'</a>'; } elseif (!empty($won)) { echo '<a>*</a>'; } else { echo '<a href="?explore=', ($x - 1) * FIELD_WIDTH + $y, '" onmousedown="return flag(', ($x - 1) * FIELD_WIDTH + $y, ',event);"'. ' oncontextmenu="return false;">.</a>'; } break; case 0: echo '<a></a>'; break; default: echo '<a>', $number, '</a>'; break; } echo '</td>'."\n"; } echo '</tr>'."\n"; } echo '</table>'."\n"; if (!empty($lost)) { unset ($_SESSION['minesweeper']); echo '<p>К сожалению, Вы проиграли :(</p> <a href="?">Заново?</a>'; } elseif (!empty($won)) { unset($_SESSION['minesweeper']); echo '<p>Поздравяю, Вы выиграли :)</p> <a href="?">Заново?</a>'; } ?> </div> </body> </html>
30.01.2021, 18:51; рейтинг: 59