Автор работы: Пользователь скрыл имя, 24 Ноября 2013 в 15:02, курсовая работа
Целью данной работы является разработка сервера для одной из самых известных и популярных в России и мире игр – Морской бой. «Морской бой» — игра для двух участников, в которой игроки по очереди называют координаты на неизвестной им карте соперника. Если у соперника по этим координатам имеется корабль (координаты заняты), то корабль или его часть «топится», а попавший получает право сделать ещё один ход. Цель игрока — первым поразить все корабли противника. Игра впервые была выпущена в виде настольной игры компанией Milton Bradley Company в 1931-ом году.
Введение 3
Теоретический анализ и проектирование 4
Архитектура системы. 4
Протокол прикладного уровня. 4
Команды протокола прикладного уровня 5
Протокол транспортного уровня. 6
Сетевой алгоритм работы: 6
Программная реализация 7
Исходный код 7
Внешний вид приложения и порядок работы 12
Тестирование 13
Выводы 14
Список литературы 15
Министерство образования и науки Российской Федерации
ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ ОБРАЗОВАТЕЛЬНОЕ УЧРЕЖДЕНИЕ
ВЫСШЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ
«СИБИРСКИЙ ГОСУДАРСТВЕННЫЙ ИНДУСТРИАЛЬНЫЙ УНИВЕРСИТЕТ»
Кафедра информационных технологий в металлургии
Курсовая работа
по дисциплине: «Информационные сети»
тема: «Сервер игры “Морской бой”»
Выполнил:
ст. группы ИВТ-10
Серафиновский М.Ю.
Научный руководитель:
ст. преподаватель
Малинов М.Б.
Новокузнецк
2013
Содержание
Компьютерные игры – одна из самых бурно развивающихся областей ПО. Если (еще полвека назад) первые компьютерные игры были штучным продуктом из-за, того что компьютеры тогда были редкостью и позволить их себе могли лишь крупные организации и научные центры, а во вторых написание игр было очень сложным занятием и сделать это могли лишь опытные программисты, то сейчас рынок компьютерных игр заполнен и играми написанными профессиональными разработчиками и начинающими программистами. Это возможно во многом благодаря специальным программам-конструкторам, это позволяет создавать игры максимально быстро, правда вследсвии этого значительно страдает производительность, но быстродействие современных компьютеров постоянно растет, и возможно за этими программами бедующее, ведь когда-то также никто не верил в успех языков программирования высокого уровня.
Целью данной работы является разработка сервера для одной из самых известных и популярных в России и мире игр – Морской бой.
«Морской бой» — игра для двух участников, в которой игроки по очереди называют координаты на неизвестной им карте соперника. Если у соперника по этим координатам имеется корабль (координаты заняты), то корабль или его часть «топится», а попавший получает право сделать ещё один ход. Цель игрока — первым поразить все корабли противника.
Игра впервые была выпущена в виде настольной игры компанией Milton Bradley Company в 1931-ом году.
Целью данной работы является создание простого сервера предоставляющего услуги для подключившихся клиентов. Сервер будет соединять первых двух подключившихся клиентов, для игры, и посредством команд будет осуществлять сетевое взаимодействие.
Была выбрана клиент-серверная архитектура, т.к. данная архитектура обладает следующими преимуществами:
Для функционирования игры необходимо чтобы были запущенны, и верно настроены 3 приложения: сервер и два клиента
Будет создан простой сервер, предоставляющий лишь услуги лишь двум первым присоединившимся игрокам, но возможно дальнейшее развитие, и добавление дополнительных режимов, таких как режим ожидания, режим приглашения, режим сохранения, режим результатов (рейтинга), и т.д. которые более полно раскрывают необходимость создания клиент-серверного приложения, а не однорангового.
Для приложения будет разработан протокол, удовлетворяющий всем потребностям простого серверного приложения для игры морской бой. В этом протоколе будут использоваться двоичный (бинарный) протокол, несмотря на то что в большинстве случаев, ему предпочитают текстовый протокол из-за более легкой расширяемости и восприятия для анализа, это было сделано по следующим причинам:
В протокол будут включены следующие команды:
В качестве протокола транспортного уровня был выбран протокол TCP, т.к.:
Алгоритм подключения следующий:
Компонентами для реализации сервера игры морской бой, был выбран компонент IdTCPServer – этот компонент инкапсулирует полный многопоточный TCP сервер, и избавляет от необходимости низкоуровнего программирования с использованием API функций. Еще одним несомненным преимуществом данного компонента является простота программирования, она осуществляется так же просто как запись и чтение обычного файла, это достигается за счет использования режима блокирующих сокетов, но платой за это становится “замораживание” программы. Но в данной работе с этим не возникнет проблем, т.к. каждого подключения создается свой поток, слушающий и пишущий независимо от основного потока.
Остановимся более подробно на исходном коде отвечающем за сетевое взаимодействие.
Процедура вызываемая при подключении нового клиента
procedure TServerFrmMain.ServerConnect(
var
NewClient: PClient;
begin
new(NewClient);
NewClient.DNS := AThread.Connection.Socket.
NewClient.Connected := Now;
NewClient.LastAction := NewClient.Connected;
NewClient.Thread := AThread;
AThread.Data := TObject(NewClient);
try
Clients.LockList.Add(
finally
Clients.UnlockList;
end;
Protocol.Lines.Add(TimeToStr(
end;
Это процедура возникающая при присоединении нового клиента, она сохраняет в структуре типа PClient, который следующую информацию:
NewClient.DNS := AThread.Connection.Socket.
{Сохраняет IP подключившегося клиента.}
NewClient.Connected := Now;
{Сохраняет дату подключения.}
NewClient.LastAction := NewClient.Connected;
{Сохраняет дату последнего действия}
NewClient.Thread := AThread;
{Сохраняет указатель на вызвавший поток.}
AThread.Data := TObject(NewClient);
{Сохраняет заполненную структуру с информацией о вызвавшем потоке, в свойстве Data этого же потока, для дальнеишего доступа к полям струтуры NewClient по мере надобности.}
Событие OnExecute возникает после подключения клиента к серверу.
procedure TServerFrmMain.ServerExecute(
var
ActClient, RecClient: PClient;
CommBlock, NewCommBlock: TCommBlock;
{струтура
содержащая информацию о
RecThread: TIdPeerThread;
{поток в
который будет производится
i: Integer;
begin
if not AThread.Terminated and AThread.Connection.Connected then
{проверка
активности потока и
begin
AThread.Connection.ReadBuffer(
ActClient := PClient(AThread.Data);
{информация о потоке с которого произошло чтение}
if ((CommBlock.Command = 'START') and (not Player1)) then
{если считана команда START и это первый присоединившийся игрок}
begin
Player1 := True;
Protocol.Lines.Add(TimeToStr(
NewCommBlock.Command := 'FIRST';
AThread.Connection.
{отправка ответа игроку делающему 1 ход}
end
else
if ((CommBlock.Command = 'START') and (not Player2)) then
{если считана команда START и это второй присоединившийся игрок}
begin
Player2 := True;
Protocol.Lines.Add(TimeToStr(
NewCommBlock.Command := 'SECOND';
AThread.Connection.
{отправка
ответа игроку делающему
with Clients.LockList do
try
for i := 0 to Count-1 do
begin
RecClient := Items[i];
RecThread := RecClient.Thread;
NewCommBlock.Command := 'GO';
RecThread.Connection.
{отправка команды игрокам о начале игры}
end;
finally
Clients.UnlockList;
end;
end
else
if (CommBlock.Command = 'SHOT') then
{если считана команда SHOT - вычтрел }
begin
NewCommBlock := CommBlock;
Protocol.Lines.Add(TimeToStr(
with Clients.LockList do
try
RecClient:=Items[0];
if RecClient.Thread <> AThread then
begin
RecThread:=RecClient.Thread;
RecThread.Connection.
end
else
begin
RecClient:=Items[1];
RecThread:=RecClient.Thread;
RecThread.Connection.
end;
finally
Clients.UnlockList;
end;
end
else
if (CommBlock.Command = 'SLIP') then
{если считана команда SLIP - промах }
begin
NewCommBlock := CommBlock;
Protocol.Lines.Add(TimeToStr(
with Clients.LockList do
try
RecClient:=Items[0];
if RecClient.Thread <> AThread then
begin
RecThread:=RecClient.Thread;
RecThread.Connection.
end
else
begin
RecClient:=Items[1];
RecThread:=RecClient.Thread;
RecThread.Connection.
end;
finally
Clients.UnlockList;
end;
end
else
if (CommBlock.Command = 'HIT') then
{если считана команда HIT - попадание }
begin
NewCommBlock := CommBlock;
Protocol.Lines.Add(TimeToStr(
with Clients.LockList do
try
RecClient:=Items[0];
if RecClient.Thread <> AThread then
begin
RecThread:=RecClient.Thread;
RecThread.Connection.
end
else
begin
RecClient:=Items[1];
RecThread:=RecClient.Thread;
RecThread.Connection.
end;
finally
Clients.UnlockList;
end;
end