Как сделать морской бой из лего

Добавил пользователь Alex
Обновлено: 02.09.2024

LEGO Pirates of the Caribbean: The Video Game - компьютерная игра, основанная на серии игрушек LEGO по мотивам .

В этом видео показан морской бой с привлечением вертолета. Смешное видео для детей. Познавательное видео для .

Всем привет! С вами Обзорщик и сегодня мы будем обозривать настольную игру Морской бой! Моя группа в .

Привееет! Меня зовут Никита, и я рад что вы зашли на мой канал. В этом видео я расскажу вам о подарках, которые мне .

Hi, my name is Ilya! Welcome to my blog ) Привет, меня зовут Илья, мне 5 Я люблю игры с машинками Hot Wheels, мне .

Великое сражение зомби; скелета; эндерменов; адских героев; свинозомби на драконе; Стива, жителей и голема; .

Новый Лего Ниндзяго 14 сезон называется Остров. Давайте смотреть все наборы LEGO Ninjago 2021 The Island: 71745 .

4000 и НОВАЯ СЕРИЯ. Игра Ravenfield обзор и прохождение с Воблером. Сражайтесь в ревенфилд вместе со своими .

Детальный взгляд на Lego Ninjago 71748 Катамаран Морской бой один из новых наборов для Ninjago Season 14: The Island .

Лего War Thunder (Лего Вар Тандер) в Brick Rigs! Лего Война и Лего Битвы Кораблей! Лего Вторая Мировая Война в Брик .

В этом видео мы покажем игрушку морской бой. В детстве мы играли на тетрадных листах в клетках. Сейчас есть даже .

Ознакомиться с полным кодом приложения и запустить прямо в браузере можно как всегда в конце статьи по ссылке.

Вот предыдущая статья про спички если кому-то интересно:

Прошлое приложение заняло 130 строк кода и я таки умудрился расписать его целиком в рамках поста, а вот морской бой уже получился на все 470+ строк. Всё расписать не получится. Будут расширеные комментарии внутри самого кода по ссылке. Как всегда начнём с самого морского боя, а ИИ (я буду называть это ИИ) оставим на вторую половину.

Сама игра не такая уж и сложная, но в ней хватает нюансов и если писать всё более-менее аккуратно, то получается много кода. В основном это связано с различными проверками при расстановке кораблей, доступности хода, проверками целости кораблей и прочее.

Начнём пожалуй с описания основных классов, которые нам понадобятся для реализации:

Game - сама игра. Этот класс будет группировать и манипулировать остальными классами.

Player — игрок. Будет иметь своё поле, будет совершать ходы.

Field - поле. Будет состоять из двух частей: основная карта и радар. Поле будет проверять возможность расположения кораблей, расставлять корабли, уничтожать их.

Ship - корабль. Можно было обойтись без него на самом деле, но с ним проще. В основном корабль будет хранить координаты и свои HP.

Кроме основных классов так же были написаны вспомогательные FieldPart — чтобы было проще обращаться к конкретной части поля (карта/радар). Color — чтобы было проще и нагляднее задавать цвет элементам. Cell — чтобы описать все возможные состояния клетки поля в одном месте (пустая, сыграная, корабль, уничтоженый корабль, поврежденный корабль).

Игра будет хранить игроков в cписке players. Но зачем мучиться с коэффициентами при обращении к игрокам, если можно завести две переменные current_player и next_player,которые ссылаются на элементы списка players. Так мы всегда понимает как обратиться к текущему и следующему игроку. А в конце хода мы просто меняем значения этих переменных местами. Ну и я решил добавить такое понятие как status. У игры не то чтобы много статусов, но таким образом можно организовать более наглядный переход из одного состояния в другое в самом игровом цикле. Статусы будут примерно такие: prepare, in_game, game_over.

Функции у игры следующие:

start_game - просто объявляем текущего игрока и следующего.

status_check - игра каждый ход проверяет статусы и меняет их при достижении условий.

add_player - функция используется когда у игры статус prepare для добавления игроков и назначени им полей.

ship_setup - так же используется на старте игры. Передаём в функцию ссылку на игрока и игра просит его расставить корабли или расставляет автоматически. draw — рисует каждый ход поле и доп.инфу. switch_players — просто переключает текущего игрока и следующего, юзается в конце хода. clear_screen — чистит экран.

Кратенько по игроку. name - просто имя. is_ai - является игрок ИИ или нет, в зависимости от этого меняет некоторая логика хода. auto_ship_setup - автоматически расставлять корабли для игрока или вручную. Опция для нетерпеливых. skill - относится к ИИ пока пропустим описание. ships наполняется имеющимися у игрока кораблями. enemy_ships - здесь будем считать какие корабли остались у противника — человек конечно и сам может посчитать, но для ИИ очень полезно. field - поле игрока (поле будет описано ниже)

Функции у игрока: get_input — запросить ввод. здесь мы передаем тип инпута либо 'ship_setup' либо 'shot'. Всё зависит от статуса игры. Много логики внутри, тут лучше почитать код с комментами. make_shot - делаем выстрел по указанному игроку. В этой функции как раз и вызывается get_input с параметром 'shot'. receive_shot - соответственно игрок принимает выстрел по координатам. На самом деле если чётко расписать действия игроков на бумаге и чем они оперируют в ходе игры всё становится гораздо очевиднее. receive_shot возвращает на выходе либо 'miss' (прмах) либо 'get' (ранил) либо ссылку на объект Ship (убил). Если убил логично вернуть весь корабль т.к. тогда проще закрасить на радаре клетки вокруг. Да, это конечно дерзко возвращать данные разных типов, но что поделать.

С полем всё просто: size - размер поля. map - основная карта поля по факту просто список списков изначально заполняемый пустыми клетками (Cell.empty_cell). radar - так же. weight уже по интереснее. Это относится к ИИ, поэтому обсудим чуть ниже.

Функции. draw_field - отрисовка поля. Здесь и далее параемтр element это часть поля с которой необходимо работать. либо Map либо Radar либо Weight. Check_ship_fits - прверяем что корабль помещается на ту или иную позицию. Используется при расстановке кораблей а так же для некоторых манипуляций с ИИ. mark_destroyed_ship - помечаем что корабль уничтожен. Ставим на нем кресты, вокруг — точки. add_ship_to_field - добавление корабля. тут все понятно. get_max_weight_cells и recalculate_weight_map относится к ИИ, это рассмотрим чуть ниже.

class Ship: def __init__(self, size, x, y, rotation): self.size = size self.hp = size self.x = x self.y = y self.rotation = rotation

Тут вообще всё до безобразия просто: x, y — координаты начала корабля. size - размер. rotation — в какую сторону повёрнут (от 0 до 4). hp — текущее хп корабля. Конкретные поврежденные клетки не отслеживаются т.к. по факту за контроль отрисовки поля отвечает класс Field.

Последнее что мы рассмотрим перед написанием ИИ это основной цикл игры:

Если наступает статус 'game over' — выводим основные поля обоих игроков. Пишем кто выиграл, кто проиграл.

Как всегда я сел и стал прикидывать какой логикой оперирует человек при игре в морской бой.

И тут рассуждения увели меня чуть в сторону и стала вырисовываться идея коэффициентов: назначаем клеткам коэффициенты и стреляем по наиболее весомой. Если корабль помещается в какие-то клетки — прибавляем им коэффициенты. Если нет — коэффициент останется нулевым. Функция check_ship_fits уже была готова т.к. использовалась для расстановки кораблей до начала игры. Отлично.

Я начал развивать идею с коэффициентами. Решил так: изначально каждую клетку поля проверяем на возможность начала с нее корабля. Причем в любую из четырёх сторон. Итого клетка за каждый корабль может получить 4 балла. Естественно речь про поле-радар, единственно доступная информация о кораблях противника расположена на нем. Со временем поле будет заполнятья убитыми кораблями и промахами а коэффициенты этих клеток будут автоматически иметь 0.

Далее в систему коэффициентов нужно как-то вписать все пункты алгоритма:

Ещё задолго до появления компьютеров в СССР выпускали настольные игры морской бой. К сожалению фотографии самой игры не осталось, а вот схемка сохранилась.

Игра была небольших размеров, примерно 30х30 см. и толщиной 4 см. На игровом поле напротив было 10 кораблей, перед вами ручка управления вращающейся пушки и кнопка "огонь". Проплывающие мимо корабли нужно было сбивать, скорость кораблей можно регулировать. При нажатии на кнопку "огонь" по водному пространству "летел" снаряд прямо в цель. Рядом с ручками управления был счетчик сбитых кораблей. Схема игры довольно простая и не содержит дорогостоящих деталей.


Как сделать корабль из "Лего"?

Итак, чтобы собрать морское судно, нужно запастись конструктором и включить свое воображение. В этом материале собраны источники для вдохновения, которые помогут начать интересную стройку как можно скорее.

Военный корабль Лего

Создание корабля из "Лего" может происходить как из стандартных деталей конструктора, так и при использовании специальных моделей тематических серий.

Например, линейка "Пираты" предлагает пуститься в захватывающие приключения в водной стихии, собрав для этой цели лодку капитана Крюка, адмиральское судно или трехмачтовый фрегат. Во всех конструкторах данной серии есть подробные инструкции, которые помогают собрать соответствующий корабль.

Как сделать из "Лего" военный корабль?

Это видео поможет собрать из конструктора Lego самый простой военный корабль всего за 3 минуты.


А изучив эту видеоинструкцию, можно соорудить более внушительное судно.


Самый большой корабль из "Лего"

Конструктор настолько захватил население разных стран, что в Интернете" можно найти множество настоящих шедевров, выполненных из его деталей. В том числе для любителей моря интерес представляет самый большой корабль, который был создан в 2012 году. Он изображен на фото ниже.

Самая большая модель корабля, собранная из Лего

Чтобы создать это чудо, рыболову Джиму Мак-Доно понадобилось порядка трех лет. С момента начала работы над моделью военного линкора США и до 2015 года Джим практически не покидал собственного гаража, все свободное время отдавая любимому занятию.

В итоге получившийся корабль достиг длины в 7,32 м. Мак-Доно мечтал построить модель линкора, которая станет самой большой на планете. Но, к сожалению, ему это не удалось, поскольку рыбак потратил слишком много времени на реализацию идеи.

Житель штата Миннеаполис, фанатевший по лего, успел опередить Джима. Поэтому на сегодняшний день самым большим кораблем считается работа Дэна Сискинда, длина которой 7,78 м.

Вывод прост: для того, чтобы из "Лего" получился большой и красивый корабль, напоминающий настоящий, помимо самого конструктора потребуются терпение и усидчивость. И тогда при создании военного судна не возникнет никаких проблем.

Пару дней назад я с удивлением узнал, что некоторые мои знакомые не умеют играть в морской бой. Т.е. правила они, конечно, знают, но вот играют как-то бессистемно и в итоге часто проигрывают. В этой записи я постараюсь изложить основные идеи, которые помогут повысить уровень вашей игры.

Правила игры

Существует множество вариантов морского боя, но мы с вами рассмотрим наиболее распространённый вариант со следующим набором кораблей:


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

Оптимальная стратегия

В игре морской бой всегда есть элемент случайности, но его можно свести к минимуму. Прежде чем переходить непосредственно к поиску оптимальной стратегии, необходимо озвучить одну очевидную вещь: вероятность попасть по кораблю противника тем выше, чем меньше непроверенных клеток осталось на его поле, аналогично вероятность попадания по вашим кораблям тем ниже, чем больше непровереных клеток осталось на вашем поле. Т.о. для эффективной игры нужно научиться сразу двум вещам: оптимальной стрельбе по противнику и оптимальному своих размещению кораблей.

В дальнейшем объяснении будут использоваться следующие обозначения:


Оптимальная стрельба

Первым и самым очевидным правилом оптимальной стрельбы является следующее правило: не стрелять по клеткам непосредственно окружающим уничтоженный корабль противника.


В соответствии с принятыми выше обозначениями, на рисунке жёлтым отмечены те клетки, по которым уже были произведены безуспешные выстрелы, красным отмечены клетки, выстрелы по которым закончились попаданием, а зелёным отмечены клетки, стрельба по которым не производилась, но можно гарантировано утверждать, что кораблей в них нет (кораблей там быть не может, т.к. по правилам игры корабли не могут соприкасаться).

Из первого правила сразу вытекает второе: если вам удалось подбить вражеский корабль, необходимо сразу же его добить, чтобы как можно раньше получить список гарантировано свободных клеток.

Третье правило вытекает из первых двух: необходимо в первую очередь пытаться подбить самые крупные корабли противника. Возможно, для вас это правило не очевидно, но если немного подумать, то можно легко заметить, что уничтожив вражеский линкор, мы в лучшем случае получим информацию сразу о 14 гарантировано свободных клетках, а уничтожив крейсер, всего о 12.


Т.о. оптимальную стратегию стрельбы можно свести к целенаправленному поиску и уничтожению самых крупных кораблей противника. К сожалению, сформулировать стратегию мало, необходимо предложить способ её реализации.

Для начала давайте рассмотрим участок игрового поля размером 4 на 4 клетки. Если в рассматриваемом участке есть вражеский линкор, то его гарантировано можно подбить не более чем за 4 выстрела. Для этого надо стрелять так, чтобы на каждой горизонтали и вертикали было ровно по одной проверенной клетке. ниже представлены все варианты такой стрельбы (без учёта отражений и поворотов).


Среди всех этих вариантов, оптимальными на поле 10 на 10 клеток являются только первые два варианта, гарантирующие попадание в линкор максимум за 24 выстрела.


После того, как уничтожен вражеский линкор, необходимо начинать поиск крейсеров, а затем и эсминцев. При этом, как вы уже догадались, можно воспользоваться аналогичной методикой. Только теперь необходимо разбивать поле на квадраты со стороной в 3 и 2 клетки соответственно.


Если при поиске линкора вы использовали вторую стратегию, то для поиска крейсеров и эсминцев вам необходимо стрелять по следующим полям (зелёным отмечены поля, по которым вы уже стреляли при поиске линкора):


Для поиска катеров оптимальной стратегии не существует, поэтому в конце игры приходится опираться в основном на удачу.

Оптимальное размещение кораблей

Оптимальная стратегия размещения кораблей в некотором смысле обратна оптимальной стратегии стрельбы. При стрельбе, мы пытались найти самые крупные корабли, чтобы сократить количество клеток, которые нужно проверять, за счёт гарантировано свободных клеток. Значит, при размещении корабли надо ставить таким образом, чтобы в случае их потери минимизировать количество гарантировано свободных клеток. Как вы помните, линкор в центре поля открывает для противника сразу 14 полей, но линкор, стоящий в углу, открывает для противника всего 6 полей:


Аналогично, крейсер, стоящий в углу, вместо 12 полей открывает всего 6. Т.о., разместив крупные корабли вдоль границы поля, вы оставляете больший простор для катеров. Т.к. стратегии для поиска катеров нет, противнику придётся стрелять наугад, и чем больше свободных полей у вас останется к моменту ловли катеров, тем тяжелее будет выиграть противнику.

Ниже представлено три способа размещения крупных кораблей, которые оставляют большой простор для катеров (отмечено синим):


Каждая из приведённых расстановок оставляет для катеров ровно 60 свободных клеток, а это значит, что вероятность случайно попасть в катер составляет 0,066. Для сравнения стоит привести случайную расстановку кораблей:


При такой расстановке для катеров остаётся всего 21 клетка, а это значит, что вероятность попадания по катеру составляет уже 0,19, т.е. почти в 3 раза выше.

В заключение хочу сказать, что не стоит проводить уж слишком много времени, играя в морской бой. Особенно хочу предостеречь вас от игры на лекциях. Когда я сидел в Ваби-Саби и играл в морской бой со своей девушкой, мимо прошла официантка и сказала, что она весьма неплохо играет, т.к. много практиковалась на парах. Кто знает, кем бы она работала, если бы в своё время слушала лекции?

Читайте также: