Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Курсовая_Программа «Морской бой».doc
Скачиваний:
24
Добавлен:
23.06.2014
Размер:
153.6 Кб
Скачать
  1. Назначение работы и область ее применения. Постановка задачи

Составить программу, моделирующую игру «Морской бой». Для этого программа должна отобразить на экране два игровых поля, одно из которых должно показывать состояние хода игрока, а другое состояние хода компьютера.

В ходе игры случайным образом для игрока и компьютера на поле (10*10) размещаются корабли в количестве: четыре однопалубных, три двухпалубных, два трехпалубных, один четырехпалубный. В процессе игры фиксируется ход игрока и реакция компьютера в соответствии с размещением кораблей на поле. Компьютер в свою очередь выдает координаты очередного хода с необходимостью подтверждения попадания в координаты размещения корабля игрока.

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

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

Алгоритм программы можно укрупненно записать следующим образом:

Ввод координат хода игрока

Контроль совпадения координат с координатами размещения кораблей игрока на поле.

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

Формирование координат хода компьютера и вывод их на экран для подтверждения их совпадения с координатами размещения кораблей на поле игрока.

Формирование координат хода в случае преведущего совпадения координат размещения кораблей на поле игрока и формирование стратегии обстрела соседних клеток для выяснения направления размещения корабля на поле игрока.

Формирование некоторых переменных для записи состояния хода(количество убитых кораблей, состояние хода)

Вывод на экран состояние хода.

Алгоритм размещения кораблей на игровом поле.

Игровое поле нужно как-то хранить в памяти компьютера. Наиболее простая реализация - в виде матрицы 10x10 клеток (ячеек).

Обусловимся, что пустая ячейка будет иметь значение -1, а ячейка, в которой находится корабль: 0. Перед началом процесса размещения кораблей необходимо очистить поле. Помимо этого надо еще и обновить счетчик случайных чисел, что бы добиться реальной случайности позиций флота компьютера. Все эти действия лучше оформить в виде отдельной процедуры: procedure Init (var Pole: TPole);.

По правилам игры два корабля не могут соприкасаться друг с другом, т.е. между ними должно быть пустое пространство минимум в одну клетку. Нам понадобится вспомогательная функция, которая позволит определить, можно ли поставить однопалубный корабль в указанную ячейку или нет. Для этого необходимо проверить саму эту ячейку и все соседние (их 8 штук). И только если все они не заняты можно дать положительный ответ (True), в противном случае - отрицательный (False): function Freedom (x, y: Integer; Pole: TPole): Boolean;.

Как известно из правил игры, на поле должны находиться следующие корабли: один четырех палубный, два трехпалубных, три двухпалубных и четыре однопалубных. Процедура, расставляющая эти корабли должна выполнять следующие действия: взять случайную свободную ячейку и проверить, можно ли поставить текущий корабль горизонтально или вертикально. Если да, то корабль размещается на игровом поле и обработка переходит к следующему. Понятно, что если нет, то возвращаемся к выбору координат. Порядок действий должен быть от большего корабля к меньшему, что бы не возникла ситуация невозможности размещения ни в одну позицию поля. Это можно достичь с помощью процедуры: procedure Ships (var Pole: TPole);.

Это, собственно, и все, что касается размещения кораблей компьютера. Теперь достаточно сделать вызов: Ships (Pole); и корабли будут случайным образом расставлены по своим местам. Подобным образом помогаем пользователю, что бы он каждый раз не тратил время на эту операцию, вызвав Ship(Pole) .

Стратегия игры компьютера.

Задача заключается в разработке алгоритма, по которому компьютер сможет играть в "Морской бой" с максимальным качеством и при этом не подглядывая расположение флота игрока. Дополнительное и очевидное условие: при каждой новой игре вне зависимости от размещения сил противника компьютер должен играть по-разному, т.е. его ходы должны быть не предсказуемы. Необходимо вспомнить правила игры: участники поединка делают ходы поочередно, причем, если один из игроков попадает по кораблю соперника, то он получает право следующего хода. Если реализовать поиск цели компьютером в виде отдельной процедуры, то надо как-то научить его запоминать исходы прошлых выстрелов, чтобы адекватно произвести следующий. Из этого факта вытекает, что самое простое и рациональное решение данной проблемы можно оформить в виде конечного автомата, наиболее точно описывающего последовательность действий. Можно выделить три состояния:

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

2.Обстрел вокруг подбитой ячейки поля для определения направления корабля (вертикальное или горизонтальное), после очередного попадания - переход в третье состояние;

3.Расстрел корабля в полученном направлении до полного его уничтожения, после чего переход в первое состояние.

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

Компьютеру потребуется еще одно поле, на котором он будет вести игру. Назовем его Play. Помимо этого нужно помнить, какие корабли остались у игрока, а какие уже разбиты.

Перед началом игры надо настроить все значения. Это удобно сделать в отдельной процедуре: procedure Start;.

Предположим, что у нас есть функция, которая выдает истину, если в ячейки (x,y) игрока стоит корабль и ложь в противном случае: function Killed (x, y: Integer): Boolean;. Еще потребуется функция, определяющая длину самого большого корабля игрока: function MaxShip: Integer;.

И функция, определяющая проигрыш игрока: function GameOver: Boolean;.

Для большей наглядности каждое состояние оформим в виде отдельной процедуры.

Прострел. На этом этапе компьютер должен поймать какой-либо из кораблей противника. Для этого он будет стрелять по произвольным незанятым клеткам поля игрока. Гораздо эффективнее сначала разделаться с большими кораблями, поэтому выбирая координаты для выстрела надо проверять, что бы в этой позиции мог разместиться самый большой из оставшихся кораблей. Процесс прекращается, как только произойдет попадание. Обозначим подбитую часть корабля значением 1, а промах -2 соответствующей ячейки поля. Если у игрока остались только однопалубные корабли, то этим попаданием корабль уничтожен полностью и обстреливать его нет смысла. В противном случае надо перейти ко второму состоянию. Это достигается с помощью функции: function State1 (var x, y: Integer): Boolean;.Ее результатом служат координаты выстрела и показатель попадания.

Обстрел. На этом шаге задача заключается в определении направления пойманного корабля. Для этого надо обстрелять четыре ячейки (если они свободны), которые могут служить продолжением. В случае, когда все четыре клетки обстреляны, а попадания не произошло (однопалубный корабль), надо перейти к первому состоянию. Если в какой-то момент удалось подбить еще одну палубу противника, то можно переходит к расстрелу данного корабля, т.к. его направление стало известно. Аналогично первому состоянию, если у игрока остались корабли не более двух палуб, то этим попаданием корабль уничтожен полностью и надо вернуться к прострелу. Вводим отдельную функцию: function State2 (var x, y: Integer): Boolean;.

Расстрел. На предыдущем шаге удалось установить в каком направлении размещен пойманный корабль. Теперь задача заключается в его полном уничтожении. Для этого надо стрелять справа или слева (сверху или снизу) подбитых палуб, пока не добьем его целиком, после чего вернемся в состояние прострела. При этом следует учитывать максимально возможный корабль и стараться попасть по четвертой палубе, когда четырех палубный корабль уничтожен, нет никакого смысла: function State3 (var x, y: Integer): Boolean;.

Процедура, которая будет контролировать результат выстрела и обеспечивать повторный ход при попадании: procedure Comput;.

Можно заметить, что функция Killed вызывается ровно один раз при каждом ходе компьютера. От сюда следует, что компьютер не подглядывает расположение кораблей игрока, т.к. другой возможности узнать о состоянии какой-либо ячейки поля игрока у него нет. В этом можно убедиться на практике, собрав все эти части кода вместе и сделав консольное приложение, в котором функция Killed спрашивала бы у игрока, попал компьютер или промазал. Все это легко с минимальными изменениями реализовать на Turbo Pascal.