Как сделать морской бой на питоне

Обновлено: 04.07.2024

Онлайн урок “ПК023 - Игра "Морской бой" - Уроки питона на Codecademy на русском” для новичков и профессионалов в сфере программирования. Для удобного самостоятельного обучения в направлении “Языки программирования” на сайте Yalpi можно найти:

  • полноценные образовательные программы, позволяющие разобраться в области программирования с нуля;
  • презентации и короткие видео с ответами на часто задаваемые вопросы от профессионалов в ИТ и ПО - например, автора "IT Propaganda";
  • мастер-классы, помогающие улучшить знания и навыки в выбранной учебной среде - объектно ориентированные.

Все видеоуроки в категории "Python" представлены бесплатно для изучения в любое удобное время. Специалисты маркетплейса практически ежедневно обновляют библиотеку курсов по теме программирования.

Блин, до телепатии через междусетье ещё не додумалист же.
Ты в чём вообще делаешь - в консоли, в гуе каком-нибудь, в pygame или RenPy?

Ну а в общем я бы сделал так:
1) Есть двухмерная матрица поля, где каждая ячейка имеет логический атрибут “простреляна”.
2) Объекты-корабли содержат список занимаемых ячеек(индексов матрицы поля), тоже с атрибутами - секция корабля цела/уничтожена.
3) При попадании секция отмечается уничтоженной и проверяется список секций.
4) Если оказалось что уничтожены все - для каждой секции вызывается функция, ставящая “простреляна” в True её и восемь ячеек вокруг(от (-1,-1) до (+1,+1) к координатам секции в матрице).
Только не забудь поставить условие или перехватчик исключений IndexError чтобы не вылетала при уничтожении кораблей на краю карты.

P.S. Такая структура позволит реализовать и модификацию морского - космический бой.

Морской бой

Eliont
Да я, вроде, примерно так и делаю.
Я начал программировать с начала учебного года, так что словами объяснить трудно еще… =(
Вот код всей программы, если это поможет. Делаю в стандартном GUI

Но интересует именно первая функция (def tst). Иногда, но очень редко, она срабатывает и окрашивает клетки вокруг корабля. Очень редко. Никак не могу понять, где недочет.



Как видно, клетки вокруг 2 кораблей стали оранжевыми, вокруг 3-его криво, вокруг других вообще никак.

Отредактировано (Ноя. 30, 2010 20:28:58)

Морской бой

Такие ошибки вылазят:

File “/home/roman/Desktop/boot.py”, line 21, in tst
square_list.sink()
IndexError: list index out of range

File “/home/roman/Desktop/boot.py”, line 9, in tst
Test=square_list.test_free()
IndexError: list index out of range

Морской бой

romis
Я не сделал еще условие, если корабль находится на краю поля. Но сейчас мне нужна помощь для общего алгоритма. =(

Морской бой

по ходу оно может быть None когда-то

Отредактировано (Дек. 1, 2010 06:22:58)

Морской бой


Посмотрел повнимательнее, покопался…
Вот, держи.

Морской бой

Eliont
Спасибо ;)

Морской бой

Морской бой в т-кинтере - интересная идея. Не менее интересная чем курсовик по имитационному моделированию выполненный на движке визуальных новелл RenPy.

Морской бой

Eliont
Твоя ирония, может, и оправдана, но т-кинтер - это единственная графическая библиотека, которую я знаю :P

У меня есть игра на Морском корабле, настроенная на Python, однако сетка, которую я настроил, находилась в диапазоне от 0 до 5. Это означает, что первая строка и столбцы линкора будут иметь значение (0,0). Однако я не хочу этого, как любой застрявший пользователь будет, вероятно, считать от 1, поэтому они поместят (1,1) или (1,2) значение 0 не будет значением, которое они думают ввести. Как я могу сделать так, чтобы моя программа отражала это так, что 1,1 - это начальный столбец, а строка - не 2-й. Поскольку пользователь может ввести только значение от 0 до 4, 5 представляется как недопустимое значение и говорит, что его нет в сетке.

Таким образом, единственно возможные комбинации:

Строка: 0, 1, 2, 3, 4, столбец: 0, 1, 2, 3, 4

Я хочу, чтобы это было:

Ряд: 1, 2, 3, 4, 5 Колонка 1, 2, 3, 4, 5

3 ответа

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

Сделайте так, чтобы пользователь вводил свои строки и столбцы в диапазоне от 1 до 5, но затем вычтите 1, прежде чем поместить его линкор и т. Д.

Guess_Battleship_Board_Row = int (input ("Угадай координату X:")) - 1 Guess_Battleship_Board_Column = int (input ("Угадай координату Y:")) - 1

Похоже, отличный проект у вас здесь идет!

Есть много способов решить эту проблему, поэтому я подумал, что я просто отстрелюсь.

Итак, все массивы начинаются с "0", но (0, 0) вроде выглядит некрасиво, я согласен. Самый простой способ - создать массив 6, 6 и не использовать часть 0, 0.

Другой способ - добавить +1 к индексу массива перед его отображением или -1 перед доступом к индексу массива.

Поэтому, когда пользователь вводит 4, 5, все, что вам нужно сделать, это (arrayA [user input - 1], array [user input - 1]), эффективно сохраняющее в 3, 4, и пользователь никогда не узнает.

Также, как забавный вызов, используйте вместо букв и цифр строки или столбцы (например, 3, C).

Используя оператор switch или if / else.

(Извините, мой синтаксис Python действительно ржавый, но концепции все еще должны применяться)

Морской бой за 25 мс

2015-01-16 в 8:56, admin , рубрики: python, Алгоритмы, Морской бой, обучение программированию, Программирование

Предисловие

Общая концепция текущей реализации

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

Стратегия расстановки кораблей следующая: 2-3-4 палубные размещаются по краям карты (2 клетки), 1-палубный в центре (квадрат 6х6).



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

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

В игре используются три класса: Game, Player, Ship. Использование класса Game в текущей реализации избыточно, так как используется всего один его экземпляр, но это некоторый задел на будущее (см. список улучшений в конце статьи).

Game отвечает за общую игровую логику, Player — за стратегию ходов, Ship — хранит текущее состояние кораблей и их координаты.

Ссылка проект в GitHub.

Основные сложности, которые возникли входе разработки

1. Проектирование. Писать с использованием классов или функций? Какой набор классов использовать?
Основной проблемой при проектировании оказалось отслеживание различных состояний в игре. Например, кто сейчас ходит, в каком состоянии корабль (подбит, убит), не закончилась ли игра, кто выиграл и т.п.

2. Логика/алгоритмы. Как расставить корабли в соответствии со стратегией, как выбрать координаты для хода?

Обзор наиболее интересных частей кода

return_shoot_state — определяет дальнейшую стратегию в зависимости от результатов текущего хода.

Важные переменные: recomendation_pool — список координат для будущих выстрелов, succ_shoots — последний успешный выстрел.

Если мы попали в корабль, то, во-первых, нужно начислить себе очки за успешный выстрел (scores += 1), а во-вторых, понять, что делать дальше. Мы проверяем recomendation_pool, есть ли там что-то, если нет, то записываем туда 4 близлежащих координаты (предварительно отфильтровав их по границам поля и списку координат, по которым мы уже стреляли).

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

Если текущим выстрелом корабль был потоплен, мы считаем свою задачу выполненной и зачищаем пул рекомендаций и проч. Следующий выстрел будет выполнен случайным образом.

service.gen_cord — генерирует все возможные координаты для каждого типа кораблей. Результатом работы функции будет словарь со следующей структурой: , где S — тип корабля, [[x0,y0],[x1,y2],[xN0,yN1]] — набор координат для корабля.

Важные переменные: all_comb — хранит координаты поля в формате [[x0,y0], [x1,y1], . ]. for_1_ship — тот самый квадрат 6х6 для однопалубных, for_other_ship — набор координат для всех остальных кораблей. cord_comb — словарь, который хранит все комбинации координат.

Расстановка кораблей

В момент инициализации экземпляра класса Player также расставляются и корабли. В классе за это отвечает метод create_ships, где происходит следующее:

3. После чего зачищаем список комбинаций (data_cleaner) из списка который состоит из координат корабля и ореола.

Модуль Logging

Под конец разработки открыл для себя модуль logging из стандартной библиотеки. Поля для вывода настраиваются (logging.basicConfig), а работать с выводом не сложнее, чем с print.

image

Прочее

sevice.rdn_usr_name — генерирует случайные имена игроков из набора букв и цифр от 0 до 999.

Список улучшений (TO DO)

1. Сделать турнир между игроками, скажем, где будет 1000 игроков. По идее, с учётом текущего времени выполнения весь турнир должен занять примерно 30 сек.

3. Оптимизировать механизм поиска комбинаций (service.gen_cord), т.к. очевидно, что он избыточен и отнимает много ресурсов.

4. Реализовать различные стратегии размещения кораблей и потом сравнить какая из них наиболее успешна.

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