Игра Морской бой на JavaScript. Выстрел игрока.
Очередная статья из цикла «Игра Морской бой на чистом JavaScript». В этой статье мы рассмотрим:
- Визуальное отображение клеток, по которым стрелять нет смысла.
- Выстрел игрока.
- Обработка результата выстрела.
- Визуальное отображение попадания и промаха.
Прежде чем приступать к написанию алгоритма выстрела, необходимо вспомнить несколько массивов, о которых писалось в статье Игра Морской бой на JavaScript. Рандомная расстановка кораблей.
matrix это двумерный массив (матрица), в которой содержится информация о местоположении кораблей эскадры. Кроме этого, в матрицу записываются реультаты выстрела (промах или попадание) и места, где кораблей точно не может быть, исходя из правил игры. Изначально, данный массив при создании заполняется нулями, которые соответствуют пустой клетке.
- 0 — пустая клетка;
- 1 — палуба корабля;
- 2 — палубы корабля не может быть по условиям игры (только для экземпляра human);
- 3 — промах;
- 4 — попадание.
Двумерный массив matrix используется, в первую очередь, для визуального отображения хода игры.
Во время игры используются два экземпляра массива matrix :
human.matrix — соответствует игровому полю игрока;
computer.matrix — соответствует игровому полю компьютера.
squadron объект эскадры, в котором храниться полная информация по каждому кораблю. Данные этого объекта используются для:
— определения корабля, в который было попадание;
— уничтожен данный корабль или только повреждён (ранен);
— количество уничтоженных (потопленных) кораблей в эскадре.
Также хочу напомнить, что весь алгоритм игры «Морской бой», реализован в классе Controller . Подробнее о классе Controller и инициализации игры «Морской бой», читайте в статье Игра Морской бой на JavaScript. Редактирование положения корабля и начало игры.
Игра «Морской бой». Блокировка клетки игрового поля и установка маркера.
Прежде чем рассматривать реализацию выстрела игрока, необходимо разобраться с блокировкой клеток игрового поля и установкой маркера на них. Напомню, таким образом отмечаются клетки игрового поля, в которых, согласно правилам игры, не могут располагаться корабли — это соседние с кораблём клетки, как по вертикали и горизонтали, так и по диагонали. У вас может возникнуть вопрос, а зачем их помечать? Это позволяет лучше оценить возможное расположение кораблей противника и облегчает выбор координат для следующего выстрела.
Маркер устанавливается кликом правой кнопки мыши по клетке игрового поля компьютера, при этом клетка не должна содержать отметки попадания или промаха. Снимается маркер повторным кликом правой кнопкой.
Для этой цели, мы в функции init зарегистрировали обработчик события contextmenu :
Источник
Оптимальный алгоритм игры в морской бой
Пару дней назад я с удивлением узнал, что некоторые мои знакомые не умеют играть в морской бой. Т.е. правила они, конечно, знают, но вот играют как-то бессистемно и в итоге часто проигрывают. В этой записи я постараюсь изложить основные идеи, которые помогут повысить уровень вашей игры.
Правила игры
Существует множество вариантов морского боя, но мы с вами рассмотрим наиболее распространённый вариант со следующим набором кораблей:
Все перечисленные корабли должны быть размещены на квадратном поле 10 на 10 клеток, при этом корабли не могут соприкасаться ни углами, ни сторонами. Самое игровое поле нумеруется сверху вниз, а вертикали помечаются русскими буквами от «А» до «К» (при этом буквы «Ё» и «Й» пропускают).
Рядом рисуется вражеское поле аналогичного размера. При удачном выстреле по кораблю противника на соответствующей клетке вражеского поля ставится крестик и производится повторный выстрел, при неудачном выстреле в соответствующей клетке ставится точка, и ход переходит к противнику.
Оптимальная стратегия
В игре морской бой всегда есть элемент случайности, но его можно свести к минимуму. Прежде чем переходить непосредственно к поиску оптимальной стратегии, необходимо озвучить одну очевидную вещь: вероятность попасть по кораблю противника тем выше, чем меньше непроверенных клеток осталось на его поле, аналогично вероятность попадания по вашим кораблям тем ниже, чем больше непровереных клеток осталось на вашем поле. Т.о. для эффективной игры нужно научиться сразу двум вещам: оптимальной стрельбе по противнику и оптимальному своих размещению кораблей.
В дальнейшем объяснении будут использоваться следующие обозначения:
Оптимальная стрельба
Первым и самым очевидным правилом оптимальной стрельбы является следующее правило: не стрелять по клеткам непосредственно окружающим уничтоженный корабль противника.
В соответствии с принятыми выше обозначениями, на рисунке жёлтым отмечены те клетки, по которым уже были произведены безуспешные выстрелы, красным отмечены клетки, выстрелы по которым закончились попаданием, а зелёным отмечены клетки, стрельба по которым не производилась, но можно гарантировано утверждать, что кораблей в них нет (кораблей там быть не может, т.к. по правилам игры корабли не могут соприкасаться).
Из первого правила сразу вытекает второе: если вам удалось подбить вражеский корабль, необходимо сразу же его добить, чтобы как можно раньше получить список гарантировано свободных клеток.
Третье правило вытекает из первых двух: необходимо в первую очередь пытаться подбить самые крупные корабли противника. Возможно, для вас это правило не очевидно, но если немного подумать, то можно легко заметить, что уничтожив вражеский линкор, мы в лучшем случае получим информацию сразу о 14 гарантировано свободных клетках, а уничтожив крейсер, всего о 12.
Т.о. оптимальную стратегию стрельбы можно свести к целенаправленному поиску и уничтожению самых крупных кораблей противника. К сожалению, сформулировать стратегию мало, необходимо предложить способ её реализации.
Для начала давайте рассмотрим участок игрового поля размером 4 на 4 клетки. Если в рассматриваемом участке есть вражеский линкор, то его гарантировано можно подбить не более чем за 4 выстрела. Для этого надо стрелять так, чтобы на каждой горизонтали и вертикали было ровно по одной проверенной клетке. ниже представлены все варианты такой стрельбы (без учёта отражений и поворотов).
Среди всех этих вариантов, оптимальными на поле 10 на 10 клеток являются только первые два варианта, гарантирующие попадание в линкор максимум за 24 выстрела.
После того, как уничтожен вражеский линкор, необходимо начинать поиск крейсеров, а затем и эсминцев. При этом, как вы уже догадались, можно воспользоваться аналогичной методикой. Только теперь необходимо разбивать поле на квадраты со стороной в 3 и 2 клетки соответственно.
Если при поиске линкора вы использовали вторую стратегию, то для поиска крейсеров и эсминцев вам необходимо стрелять по следующим полям (зелёным отмечены поля, по которым вы уже стреляли при поиске линкора):
Для поиска катеров оптимальной стратегии не существует, поэтому в конце игры приходится опираться в основном на удачу.
Оптимальное размещение кораблей
Оптимальная стратегия размещения кораблей в некотором смысле обратна оптимальной стратегии стрельбы. При стрельбе, мы пытались найти самые крупные корабли, чтобы сократить количество клеток, которые нужно проверять, за счёт гарантировано свободных клеток. Значит, при размещении корабли надо ставить таким образом, чтобы в случае их потери минимизировать количество гарантировано свободных клеток. Как вы помните, линкор в центре поля открывает для противника сразу 14 полей, но линкор, стоящий в углу, открывает для противника всего 6 полей:
Аналогично, крейсер, стоящий в углу, вместо 12 полей открывает всего 6. Т.о., разместив крупные корабли вдоль границы поля, вы оставляете больший простор для катеров. Т.к. стратегии для поиска катеров нет, противнику придётся стрелять наугад, и чем больше свободных полей у вас останется к моменту ловли катеров, тем тяжелее будет выиграть противнику.
Ниже представлено три способа размещения крупных кораблей, которые оставляют большой простор для катеров (отмечено синим):
Каждая из приведённых расстановок оставляет для катеров ровно 60 свободных клеток, а это значит, что вероятность случайно попасть в катер составляет 0,066. Для сравнения стоит привести случайную расстановку кораблей:
При такой расстановке для катеров остаётся всего 21 клетка, а это значит, что вероятность попадания по катеру составляет уже 0,19, т.е. почти в 3 раза выше.
В заключение хочу сказать, что не стоит проводить уж слишком много времени, играя в морской бой. Особенно хочу предостеречь вас от игры на лекциях. Когда я сидел в Ваби-Саби и играл в морской бой со своей девушкой, мимо прошла официантка и сказала, что она весьма неплохо играет, т.к. много практиковалась на парах. Кто знает, кем бы она работала, если бы в своё время слушала лекции?
P.S. В комментариях абсолютно верно указывают, что на хабре уже были похожие публикации, было бы неверно не поставить ссылки на них:
Источник