Генерируем Сапера на PHP

Результат генерации стандартного поля (9х9, 10 мин):

Генерируем Сапера на PHP


Исправив первые 3 строчки скрипта, можно генерировать поля любого размера.

Прокомментировал код, чтобы было хоть что-то понятно. Но так как статья из одного кода — не статья, то один кусок, а точнее самый сложный момент — поиск мин вокруг клетки — я вынес на объяснение сюда.

Если вам понятно, что скрывается за строками:


        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. $y — ордината, $x — абсцисса.
Нам необходимо определить, сколько мин находится вокруг клетки, чтобы поставить это число в текущую клетку.
Каждый раз мы проверяем клетку [$x, $y]. Как определить что находится в клетке справа снизу? Все это можно сделать с помощью манипуляций над $x и $y. Для большей наглядности, вставлю картинку:

Генерируем Сапера на PHP


По этой табличке сразу видно, что правый нижний угол это [$x+1, $y+1].

Полный код:

$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) ? '&nbsp;&nbsp;' : $mCounter;
 
		// выводим клетку с классом
        echo '<span class="i' . $mCounter . '">' . $minefield[$x][$y] . '</span></td>
        ';
    }
    echo '</tr>
    ';
}
echo '</table></tt></pre >
</body>
</html>';



Просмотров: 2599
10.02.2015, 10:09 -

Категория: Статьи » Программирование » PHP