Генерируем Сапера на PHP Всем привет. Вчера было нечем заняться и в голову пришла идея — почему бы не написать генератор поля для игры в сапер? (мысль может показаться ненормальной, просто люблю генерировать что нибудь, будь это поле для игры, или что-нибудь другое). Также было поставлено четкое условие – I will not use Google. Я уверен что все дописано до меня, но это писалось для саморазвития, а не для продакшена. Спустя 20 минут первый сапер был сгенерирован, еще спустя 20 — был оформлен, с возможностью настройки поля. Результат генерации стандартного поля (9х9, 10 мин): Исправив первые 3 строчки скрипта, можно генерировать поля любого размера. Прокомментировал код, чтобы было хоть что-то понятно. Но так как статья из одного кода – не статья, то один кусок, а точнее самый сложный момент — поиск мин вокруг клетки — я вынес на объяснение сюда. Если вам понятно, что скрывается за строками: Code: if ($minefield[$x - 1][$y - 1] === 'X') $mCounter++; if ($minefield[$x][$y - 1] === 'X') $mCounter++; if ($minefield[$x + 1][$y - 1] === 'X') $mCounter++; if ($minefield[$x - 1][$y] === 'X') $mCounter++; if ($minefield[$x + 1][$y] === 'X') $mCounter++; if ($minefield[$x - 1][$y + 1] === 'X') $mCounter++; if ($minefield[$x][$y + 1] === 'X') $mCounter++; if ($minefield[$x + 1][$y + 1] === 'X') $mCounter++; , то дальше можете не читать, я думаю вы без труда сделали бы такой же скрипт. Для тех кто не понял — объясню. Все поле у нас выполнено в виде матрицы, каждая клетка имеет свои координаты $x и $y. $x — ордината (длина), $y — ось (высота). Нам необходимо определить, сколько мин находится вокруг клетки, чтобы поставить это число в текущую клетку. Каждый раз мы проверяем клетку [$x, $y]. Как определить что находится в клетке справа снизу? Все это можно сделать с помощью манипуляций над $x и $y. Для большей наглядности, вставлю картинку: По этой табличке сразу видно, что правый нижний угол это [$x+1, $y+1]. А теперь посмотрите на кусок кода выше, я думаю все стало понятно. Если все-таки нет, и очень хочется разобраться — можете написать мне в личку. Ну и то, для чего все сюда пришли: полный код. Code: <?php // Minesweeper by bafoed // http://bafoed.net $mines = 10; // количество мин на поле $fx = 9; // ширина поля (в клетках) $fy = 9; // высота поля (в клетках) #### // заполнение начального поля нулями for ($y = 1; $y <= $fy; $y++) { for ($x = 1; $x <= $fx; $x++) { $minefield[$x][$y] = '0'; } } // заполнение поля минами for ($i = 0; $i < $mines; $i++) { $randx = rand(1, $fx); // генерируем случайные координаты $randy = rand(1, $fy); // if ($minefield[$randx][$randy] == 'X') { // координаты совпали и мина уже есть $i--; // тогда не ставим мину, а скажем попробовать лишний раз } else { $minefield[$randx][$randy] = 'X'; // ставим мину } } echo <<<HEAD <DOCTYPE !html> <html> <head> <title>Minesweeper ($fx x $fy) by bafoed</title> <style type="text/css"> table,tr { background: #C4C4C4; border: 1px solid #808080; border-collapse: collapse; font-weight: bold; font-size: 14px; text-align: center; } td { border: 1px solid #808080; padding: 0.5px; width:16px; height:16px; } .i1 { color: #0000ff; } .i2 { color: #1D751F; } .i3 { color: #ff0000; } .i4 { color: #0D0485; } .i5 { color: #520E0F; } .i6 { color: #0F877E; } </style> </head> <body> HEAD; echo '<pre><tt> <table> '; for ($y = 1; $y <= $fy; $y++) { echo '<tr> '; for ($x = 1; $x <= $fx; $x++) { echo '<td>'; $mCounter = 0; // счетчик мин для клетки if ($minefield[$x][$y] == 'X') { // если текущая клетка -- мина echo '<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABUElEQVR42pWSS26CUBRAH6ho0jqijBpHdkhIjCtgDXbGzI7ZBVOURPegMagYmZAwFZdh0iWwgfb0vYZQYNKbYO7n3J/vivP5nCTJ4XA4Ho+JFJSVlLoHAAVYXC4X7DzP0zRF2e12RVG8SkHBxEkIQOULUjF8399ut1mW3W63IAiepKBg4iQEABbHseC7Xq+bzcZ13fV6PZ/Px+OxrutCiNFoNJvNcBICADudTkKNSJkoikBFS3ASAvgdiY9Bae04DuHp29TzvMX7QjXp9/v82rYNAPaTQN79fmdcy7KILT+WX1IMw1Ader2eaZoAYMAiDMPJZKIqIdQuy/Lx+RgMBvXBAMD2+/2fBE3TmGQ4HFblOxKqkehL9/bSzZGqpdms2rJeuLn0v//WxsPxUryXQrsfrvM0nqV0n0b7+FjuRQpKx/Gp88agXf2Y6wdPSOnA3/AoQ71G5naTAAAAAElFTkSuQmCC" /></td> '; // выведем и перейдем на следущую клетку continue; } // тут магия, ищем мины вокруг клетки // распишу в статье if ($minefield[$x - 1][$y - 1] === 'X') $mCounter++; if ($minefield[$x][$y - 1] === 'X') $mCounter++; if ($minefield[$x + 1][$y - 1] === 'X') $mCounter++; if ($minefield[$x - 1][$y] === 'X') $mCounter++; if ($minefield[$x + 1][$y] === 'X') $mCounter++; if ($minefield[$x - 1][$y + 1] === 'X') $mCounter++; if ($minefield[$x][$y + 1] === 'X') $mCounter++; if ($minefield[$x + 1][$y + 1] === 'X') $mCounter++; // если нет мин вокруг глетки -- выводим пустую, а не с цифрой 0 $minefield[$x][$y] = ($mCounter == 0) ? ' ' : $mCounter; // выводим клетку с классом echo '<span class="i' . $mCounter . '">' . $minefield[$x][$y] . '</span></td> '; } echo '</tr> '; } echo '</table></tt></pre > </body> </html>'; ?> bafoed.net http://bafoed.net/blog/post2126