Программа "Морской бой"

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

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 18.02.2019
Размер файла 817,9 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

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

Размещено на http://www.allbest.ru/

Размещено на http://www.allbest.ru/

Программа «Морской бой»

Введение

игра программа алгоритм онлайн

Язык программирования Си - стандартизированный процедурный язык программирования, разработанный в 1969-1973 годах сотрудниками BellLabs Кеном Томпсоном и Деннисом Ритчи как развитие языка Би. Cи - старейший и наиболее широко используемый язык, на нем строятся другие популярные языки, такие как C#, Java, JavaScript и Python. Cи в основном используется для написания операционных систем и встраиваемых приложений.

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

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

1. Файлы программы

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

types.h - заголовочный файл, содержащий объявления типов и констант, используемых в программе;

main.c - главный файл, в котором собраны функции определения режима игры и запуска процесса игры в соответствии с режимом;

game.c - файл, в котором собраны все функции, отвечающие непосредственно за игровой процесс;

user.c - файл, в котором собраны функции, которые получают данные от пользователя (координаты кораблей при расстановке и координаты выстрела)

computer.c - файл, содержащий функции, необходимые для осуществления расстановки кораблей и генерации выстрелов компьютера;

output.c - файл, содержащий функции вывода (разные функции вывода полей, функции вывода координат и т.д.).

Файл types.h будет приведен в приложении А с подробными комментариями.

Рассмотрим файл main.c. В этом файле происходит подключение всех необходимых файлов и библиотек, таким образом, не будет необходимости в подключении одних и тех же файлов и библиотек в разных файлах.

В файле main.c содержится две функции: функция main(), начинающая игру, и функция AskUser(), которая спрашивает у пользователя режим. В функции main() создаются структуры, хранящие данные об игроках. В зависимости от выбранного режима, эти структуры заполняются по-разному.

В файле game.с содержится три основных функции, управляющие процессом игры: Game(), ControlSettingBoats() и ControlShots(). Функция Game() контролирует общий процесс игры: создает поля, передает их функции ControlSettingBoats() для дальнейшего заполнения полей кораблями, производит поочередно выстрелы игроков с помощью функции ControlShots(), пока один из них не наберет нужное количество очков, объявляет победителя.

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

Функция ControlShots() управляет ходами игрока. Она вызывает функцию получения координат выстрела (разные для пользователя и компьютера), обрабатывает поле, выводит сообщение, завершает свою работу, если ход должен перейти другому игроку, или продолжает запрашивать координаты выстрела текущего игрока.

В файле user.c содержатся две главные функции: MakeShotsByUser() и SetBoatsByUser(), которые запрашивают у пользователя координаты выстрелов и координаты кораблей и переводят их к виду, принятому в программе.

В файле computer.c содержатся две похожие функции MakeShotsByComp() и SetBoatsByComp(), управляющие генерацией выстрела компьютера и генерацией кораблей компьютера. Помимо этих функций, в этом файле реализованы еще девять функций, которые осуществляют игру компьютера.

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

Но поскольку, если располагать корабли по такому алгоритму, пользователь может быстро догадаться о том, где находятся большие корабли и быстро их подбить. Поэтому компьютер генерирует случайные координаты и ориентацию корабля и рассчитывает, какая будет выгода, если его разместить. Если выгода больше (для однопалубных кораблей) или меньше (для больших кораблей) определенных значений, то корабль ставится. Иначе - генерируется заново. Чтобы компьютер не тратил много времени на генерацию кораблей, после проверки определенного (и не выгодного) варианта, компьютер все же ставит его на поле.

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

Если одна из клеток подбита, то она вместе с дальнейшими клетками не считается. Соответственно, вес проверяемой клетки будет меньше. Если рядом есть клетка недобитого корабля, то, чем ближе она, тем больше вес клетки. Так же, чем больше рядом клеток недобитого корабля, тем ценнее клетка. Таким образом, компьютер будет производить добивание кораблей.

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

В файле output.c собраны все функции, которые отвечают за вывод информации. Большинство функций в этом файле были нужны для отладки (функции вывода массива координат, массива кораблей и т.д.).

2. Запуск и ход игры

При запуске игры компьютер просит пользователя ввести число, определяющее режим игры. Это показано на рисунке 1.

Рисунок 1. Начало игры

Рассмотрим игру пользователя с компьютером (режим 1). Для начала пользователю необходимо расставить корабли на своем поле. Для этого необходимо задать координаты начала и ориентацию (буква «г» для горизонтального корабля, буква «в» - для вертикального). Для того чтобы пользователь мог видеть, где он разместил корабли, выводится поле. На рисунке 2 показано, что пользователь видит, когда расставляет первый корабль.

Рисунок 2. Пользователь ставит первый корабль

Для дальнейших пояснений разместим четырехпалубный корабль горизонтально с началом в точке Ж1.

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

На рисунке 4 показано, что увидит пользователь, если будет пытаться установить корабль рядом с другим кораблем или за пределами поля.

После расстановки кораблей начинается игра. Сначала ходит пользователь. На рисунке 5 показано, как изменится поле после выстрела первого выстрела.

Рисунок 3. Обновленное поле

Чтобы пользователь мог сразу определить, куда выстрелил компьютер, после хода компьютера выводятся информация о выстреле и обновленное поле. Только после этого, если компьютер попал мимо, пользователя снова просят ввести координаты выстрела.

Рисунок 4. Сообщения о неправильном вводе данных

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

Рисунок 5. Выстрел первого игрока в клетку Д5

На рисунке 6 показано, что видит пользователь, если он ранил корабль. На рисунке 7 показано, что выводится, если корабль был потоплен. При потоплении корабля, клетки вокруг него (где точно не могут располагаться другие корабли) становятся автоматически подстреленными.

Рисунок 6. Пользователь подбил корабль противника

Во время выполнения ходов игроков ведется счет. За каждую подбитую клетку игроку начисляется одно очко. Когда число очков одного из игроков станет равно 20, игра будет окончена, а игрок с таким количеством очков станет победителем. На рисунке 8 показано сообщение, объявляющее победителя. На этом игра заканчивается.

Рисунок 7. Пользователь потопил двухпалубный корабль

Рисунок 8. Окончание игры

Заключение

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

Основная цель работы была выполнена, т.е. была написана многопользовательская игра «Морской бой» с псевдографическим интерфейсом.

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

В программе реализована возможность игры с компьютером.

В приложении содержится код программы, содержащий все пояснительные комментарии.

Библиографический список

1 Керниган, Б. Язык программирования СИ: издание 3-е, исправленное / Б. Керниган, Д. Ритчи. СПб.: «Невский Диалект», 2001. 352 с.

2 СТП ОмГУПС-1.2-2005. Работы студенческие учебные и выпускные квалификационные

Приложение

Листинг файла types.h

const int FIELD_SIZE = 10; // размер поля

const char LETT[] = {«АБВГДЕЖЗИК»}; // массив букв для вывода координаты x

typedef struct { // информация о поле

int player1 [100]; // поле первого игрока

int player2 [100]; // поле второго игрока

} field;

typedef struct { // координаты

int x;

int y;

} coords;

typedef struct { // информация об одном корабле

int size; // размер

char orient; // ориентация

coords start; // координаты начала

} boat;

typedef struct { // информация об игроках

int score; // счет игрока

void (*SetBoats) (boat* boats); // указатель на функцию расстановки кораблей

coords (*MakeShot) (int* f); // указатель на функцию генерации выстрела

} player;

Листинг А.1

Листинг файла main.c

#include <stdio.h> // подключение необходимых библиотек

#include <string.h>

#include <assert.h>

#include <math.h>

#include <time.h>

#include <stdlib.h>

#include «types.h» // подключение файла с типами и константами для игры

#include «output.c» // подключение игровых файлов

#include «game.c»

#include «computer.c»

#include «user.c»

 // функция спрашивает пользователя и сверяет его ответ с массивом возможноых ответов ans

char AskUser (char quest[30], int n, char* ans) {

assert (n!= 0);

int a = 0, i = 0;

char user[1];

do {

a = 0;

printf («%s\n», quest);

gets(user);

for (i = 0; (i < n) && (user[0]!= ans[i]); i++) {};

if (user[0] == '0') exit(0);

if (i = n && user[0]!= ans[i]) {

a = 1;

printf («Неправильный символ! попробуйте снова \n»);

}

} while(a);

return user[0];

}

int main() {

char z[] = {'0', '1', '2'};

char mode;

mode = AskUser («Введите 0 для выхода из игры; \nвведите 1 для игры с компьютером; \nвведите 2 для игры с другим человеком», 3, z); // спрашиваем пользователя о режиме игры

player pl1, pl2; // создаем двух игроков

pl1.score = pl2.score = 0; // зануляем их счет

if (mode == '1' || mode == '2') { // если первый игрок - пользователь

pl1. SetBoats = SetBoatsByUser;

pl1. MakeShot = MakeShotsByUser;

}

Листинг А.2, лист 1

if (mode == '1') { // если второй игрок - компьютер

pl2. SetBoats = SetBoatsByComp;

pl2. MakeShot = MakeShotsByComp;

srand (time(0));

}

if (mode == '2') { // если второй игрок - пользователь

pl2. SetBoats = SetBoatsByUser;

pl2. MakeShot = MakeShotsByUser;

}

Game (&pl1, &pl2); // сама игра

}

Листинг А.2, лист 2

Листинг файла game.c

 // функция возвращает 0, если координата а принадлежит полю

 // и 1, если координата а неправильная

int CheckCoord (int a) {

if (a >= FIELD_SIZE || a < 0)

return 1;

else return 0;

}

 // функция прибавляет число к координате

int SummCoords (int coord, int a) {

if (coord + a >= FIELD_SIZE) return 9;

if (coord + a < 0) return 0;

return (a+coord);

}

 // функция очерчивает область вокруг корабля в зависимости от размеров и ориентации

void SetCheckingArea (boat* b, int* x0, int* y0, int* x1, int* y1) {

if (b->orient == 'г') {

*y1 = SummCoords (b->start.y, 1);

*x1 = SummCoords (b->start.x, b->size);

} else {

*x1 = SummCoords (b->start.x, 1);

*y1 = SummCoords (b->start.y, b->size);

}

*x0 = SummCoords (b->start.x, -1);

*y0 = SummCoords (b->start.y, -1);

}

 // функция проверяет, может ли корабль располагаться на поле

 // возвращает 0, если все нормально

 // возвращает 1, если этому что-то мешает

int CheckBoats (int* f, boat b) {

int x1, y1, x0, y0;

if (b.orient == 'г') {

if (CheckCoord(b.start.x) || CheckCoord (b.start.y) || CheckCoord (b.start.x + b.size-1))

return 1;

} else {

if (CheckCoord(b.start.x) || CheckCoord (b.start.y) || CheckCoord (b.start.y + b.size-1))

return 1;

}

SetCheckingArea (&b, &x0, &y0, &x1, &y1); // устанавливаем область для проверки

Листинг А.3, лист 1

int i, j;

for (i = y0; i <= y1; i++) // обходим область проверки

for (j = x0; j <= x1; j++) {

if (f[FIELD_SIZE*i + j]) // если встретили ненулевую клетку, то корабль там нельзя расположить

return 1;

}

return 0;

}

 // функция устанавливает корабль на поле

void SetOneBoat (int* f, boat* b) {

assert (b->orient == 'в' || b->orient == 'г');

assert((b->start.x < FIELD_SIZE && b->start.x >= 0) && (b->start.y < FIELD_SIZE && b->start.y >= 0));

int i;

if (b->orient == 'в') { // если корабль вертикальный

for (i = b->start.y; i < (b->start.y + b->size); i++) {

f [FIELD_SIZE*i + b->start.x] = b->size*10;

}

}

if (b->orient == 'г') { // если корабль горизонтальный

for (i = b->start.x; i < (b->start.x + b->size); i++) {

f [FIELD_SIZE*b->start.y + i] = b->size*10;

}

}

}

 // функция заполняет массив координат координатами четырех клеток сверху, снизу и с боков от клетки p

void FillCoordsArray (coords* a, coords p) {

a[1].x = a[3].x = p.x;

a[1].y = p.y-1;

a[0].x = p.x-1;

a[0].y = a[2].y = p.y;

a[2].x = p.x+1;

a[3].y = p.y+1;

}

 // функция обходит вокруг клетки p и возвращает следующую не пустую клетку

coords FindOneMoreCell (int* f, coords p) {

coords a[4];

FillCoordsArray (a, p);

int i;

Листинг А.3, лист 2

for (i=0; i< 4; i++) {

if (! CheckCoord(a[i].x) &&! CheckCoord (a[i].y)) {

if (f[a[i].y*FIELD_SIZE + a[i].x]!= 0 && f [a[i].y*FIELD_SIZE + a[i].x]!= -100)

return a[i];

}

}

coords w;

w.x = -1;

w.y = -1;

return w;

}

 // функция находит максимум и минимум и прибавляет к ним del

int FindExtr (int x0, int x1, int del, int a) {

if (a == 0)

return (x0 > x1? SummCoords (x1, del): SummCoords (x0, del));

else

return (x0 < x1? SummCoords (x1, del): SummCoords (x0, del));

}

 // функция находит корабль, если известна одна его точка

boat FindBoat (int* f, coords p0) {

boat res;

res.size = fabs (f[p0.y*FIELD_SIZE+p0.x])/10;

if (res.size == 1) { // если корабль однопалубный, то он уже найден

res.orient = 'г';

res.start.x = p0.x;

res.start.y = p0.y;

} else { // иначе

coords b = FindOneMoreCell (f, p0); // находим следующую не пустую клетку

int delta = res.size - 2; // delta очерчивает область возле двух точек, в которой может располагаться корабль

int i, min;

if (b.x == p0.x) {

res.orient = 'в'; // в зависимости от ориентации, обходим область с кораблем по-разному

min = FindExtr (b.y, p0.y, - delta, 0); // находим минимальную точку в области с кораблем

for (i = min; f [i*FIELD_SIZE+p0.x] == 0 || f [i*FIELD_SIZE+p0.x] == -100; i++) { // и идем до тех пор, пока не встретится первая клетка корабля

}

Листинг А.3, лист 3

res.start.x = p0.x; // сохраняем ее координаты

res.start.y = i;

} else {

res.orient = 'г';

min = FindExtr (b.x, p0.x, - delta, 0);

for (i = min; f [b.y*FIELD_SIZE+i] == 0 || f [b.y*FIELD_SIZE+i] == -100; i++) {

}

res.start.x = i;

res.start.y = p0.y;

}

}

return res;

}

 // функция проверяет, был ли корабль потоплен

 // возвращает 0, если был

 // возвращает 1, если нет

int CheckIfDrown (int* f, coords p) {

if (f[p.y*FIELD_SIZE+p.x]/10 == 1) // если это однопалубный корабль, то

return 0; // он точно потоплен

boat c = FindBoat (f, p); // находим корабль

int i;

if (c.orient == 'в') { // в зависимости от ориентации, по-разному обходим область

for (i = c.start.y; i < c.start.y + c.size; i++)

if (f[i*FIELD_SIZE + c.start.x]%10 == 0) return 1; // если встретили положительную клетку - корабль не потоплен

} else {

for (i = c.start.x; i <c.start.x + c.size; i++)

if (f[c.start.y*FIELD_SIZE + i]%10 == 0) return 1;

}

return 0; // если не встретили ни одной положительной клетки, то корабль потоплен

}

 // функция обрабатыва поле после того, как корабль потопили

void EditField (int* f, coords p0) {

int x, y, x0, y0, x1, y1;

boat u = FindBoat (f, p0); // находим потопленный корабль

SetCheckingArea (&u, &x0, &y0, &x1, &y1); // находим координаты области вокруг него

for (y = y0; y <= y1; y++) // помечаем их подбитыми

for (x = x0; x <= x1; x++)

f [y*FIELD_SIZE + x] = -100;

if (u.orient == 'г')

Листинг А.3, лист 4

for (x = u.start.x; x < u.start.x+u.size; x++)

f [u.start.y*FIELD_SIZE + x] = -10;

else

for (y = u.start.y; y < u.start.y+u.size; y++)

f [y*FIELD_SIZE + u.start.x] = -10;

}

 // функция заполняет половину поля нулями

void FillField (int* f) {

int i;

for (i = 0; i < 100; i++) {

f[i] = 0;

}

}

 // функция управляет расстановкой кораблей на поле

void ControlSettingBoats (int* f, void (*SetBoats) (boat* boats)) {

boat boats[10]; // массив кораблей

boats[0].size = 4; // заполняем размеры кораблей

boats[1].size = boats[2]. size = 3;

boats[3].size = boats[4]. size = boats[5]. size = 2;

boats[6].size = boats[7]. size = boats[8]. size = boats[9]. size = 1;

int i;

(*SetBoats) (boats); // дае массив кораблей функции по расстановке кораблей

for (i = 0; i< 10; i++) // проверяем и ставим, если все в порядке.

if (CheckBoats(f, boats[i]) == 0) {

SetOneBoat (f, &boats[i]);

} else { // иначе очищаем поле и заново расставляем корабли.

i = 0;

FillField(f);

(*SetBoats) (boats);

}

}

void MakeCopy (int* a, int* b, int n) {

int i;

for (i = 0; i< n; i++)

if (a[i] <= 0 || a[i]%10 == 5)

b[i] = a[i];

else b[i] = 0;

}

Листинг А.3, лист 5

 // функция управляет выстрелами игрока

void ControlShots (int b, int* score, coords (*MakeShot) (int* f), field* fi) {

coords point;

int c = 3; // попытки стрельбы в уже подстреленную клетку

int a; // указывает, когда игрок перестает стрелять

int drown; // указывает, был ли потоплен корабль

int ff[100], * enemyField; // копия поля, которая передается функциям, генерирующим выстрелы

if (b == 1) enemyField = fi->player2; // в зависимости от того, какой игрок ходит,

else enemyField = fi->player1; // вражеское поле будет разным

do {

system(«cls»);

printf («\n Ходит игрок % i \n \n\n», b);

PrintField(fi);

MakeCopy (enemyField, ff, FIELD_SIZE*FIELD_SIZE); // делаем копию поля

point = (*MakeShot) (ff); // генерируем выстрел

system («cls»);

printf («\n Игрок % i выстрелил в клетку», b);

PrintCoords(point);

if (! enemyField[point.y* FIELD_SIZE + point.x]) { // если подстреленная клетка пустая

enemyField [point.y* FIELD_SIZE + point.x] = -100; // ставим -100

printf («\n Подстреленная клетка оказалась пустой \n»);

a = drown = 1;

} else {

if (enemyField[point.y* FIELD_SIZE + point.x] < 0 || enemyField [point.y* FIELD_SIZE + point.x]%10!= 0) {

c -= drown =1;

printf (» \n По этой клетке уже стреляли. Можно попытаться еще % i раз. \n», c);

a = 0;

} else {

enemyField [point.y* FIELD_SIZE + point.x] += 5;

drown = CheckIfDrown (enemyField, point);

if (drown == 0) {

PrintDrown (enemyField[point.y* FIELD_SIZE + point.x]/10);

EditField (enemyField, point);

Листинг А.3, лист 6

} else

printf («\n!!! Была подбита часть корабля противника!!! \n»);

(*score) ++; // увеличиваем счет

a = 0;

}

}

PrintField(fi);

system («pause»);

} while (a == 0 && *score!= 20 && c > 0);

system («cls»);

PrintField(fi);

}

 // главная игровая функция

void Game (player* p1, player* p2) {

const int MAX_SCORE = 1*4 + 2*3 + 3*2 + 4*1;

field f;

FillField (f.player1); // заполняем поля нулями

FillField (f.player2);

ControlSettingBoats (f.player2, p2->SetBoats);

ControlSettingBoats (f.player1, p1->SetBoats); // расставляем корабли

while (p1->score < MAX_SCORE && p2->score < MAX_SCORE) { // цикл бежит, пока один из игроков не потопит все корабли другого

ControlShots (1, &p1->score, p1->MakeShot, &f);

if (p1->score < MAX_SCORE)

ControlShots (2, &p2->score, p2->MakeShot, &f);

}

printf («\n Игра окончена.»);

if (p1->score == MAX_SCORE)

printf («\n * * * * * * Игрок 1 победил! * * * * * * \n»);

if (p2->score == MAX_SCORE)

printf («\n * * * * * * Игрок 2 победил! * * * * * * \n»);

}

Листинг А.3, лист 7

Листинг файла user.c

int GetXFromUser (char x) {

int i;

for (i = 0; i < 20 && LETT[i]!= x; i++){}

return i;

}

 // Функция получает у польхователя координаты корабля

void GetBoatFromUser (boat* b, int* f) {

char str[10];

int x, y;

char o;

gets(str);

if (str[0] == '0' && str[1] == '\0') exit(0);

if (b->size == 1) {

o = 'г';

x = GetXFromUser (str[0]);

y = atoi (&str[1]) - 1;

} else {

o = str[0];

x = GetXFromUser (str[2]);

y = atoi (&str[3]) - 1;

}

if((CheckCoord(x) || CheckCoord(y)) || (o!= 'г' && o!= 'в')) {

printf («Что-то пошло не так! Попробуйте снова\n»);

b->orient = 'x';

} else {

b->orient = o;

b->start.x = x; b->start.y = y;

}

}

 // функция управляет расстановкой кораблей пользователя

void SetBoatsByUser (boat* boats) {

int i, a;

char str4_2 [] = {» и ориентацию»};

char str1 [] = {«»};

char *out = str4_2;

int f[100];

FillField(f);

for (i = 0; i < 10; i++) {

if (boats[i].size == 1)

out = str1;

system («cls»);

printf («Игрок расставляет корабли \n»);

printhalf0 (f);

do {

Листинг А.4, лист 1

do {

printf(«\nПожалуйста, введите координаты % s % i-палубного корабля \n», out, boats[i].size);

printf(«(например: г А3 установит ваш корабль горизонтально в точке А3) \n»);

printf («Вы можете ввести 0 для выхода из игры\n»);

GetBoatFromUser (&boats[i], f); // получаем данные о корабле заданного размера

} while (boats[i].orient!= 'в' && boats[i].orient!= 'г');

a = CheckBoats (f, boats[i]); // проверяем, можно ли разместить корабль

if(a) printf («Что-то пошло не так… попробуйте снова \n»);

} while(a);

printf («Корабль был успешно установлен! \n»);

SetOneBoat (f, &boats[i]);

system («pause»);

}

}

 // функция, управляющая выстрелами пользователя

coords MakeShotsByUser (int* f) {

char str[10];

int x, y;

int a;

coords res;

do {

printf(«Пожалуйста, введите координаты выстрела \n (например, И4) \n»);

printf («Вы можете ввести 0 для выхода из игры \n»);

if (gets(str) == NULL || str[0] == '0') exit(0);

x = GetXFromUser (str[0]);

y = atoi (&str[1]) - 1;

if((CheckCoord(x) || CheckCoord(y))) {

printf («Что-то пошло не так! попробуйте снова\n»);

a = 1;

} else {

res.x = x;

res.y = y;

return res;

a = 0;

}

} while (a == 1);

}

Листинг А.4, лист 2

Листинг файла computer.c

 // функция генерирует рандомное число от 0 до (size-1)

int RandC (int size) {

int a = rand()%size;

return a;

}

/* - функции, занимающиеся расстановкой кораблей компьютера -*/

 // функция считает выгоду при расстановке кораблей из массива boats

int CountProfit (boat* boats, int n) {

int i, x, y, x0, y0, x1, y1, profit = 0;

int ff[100];

FillField(ff);

for (i = 0; i< n; i++) {

SetCheckingArea (&boats[i], &x0, &y0, &x1, &y1);

for (x = x0; x <= x1; x++)

for (y = y0; y <= y1; y++)

ff [y*FIELD_SIZE+x] = 1;

}

for (i = 0; i< 100; i++)

if (ff[i]!= 0) profit++;

return profit;

}

 // функция считает выгоду при установке последнего корабля

 // возвращает 1, если корабль занимает невыгодное положение

 // и 0, если положение выгодное

int CheckProfit (boat* boats, int n) {

int prof;

int i = n-1;

if (boats[i].size == 4) prof = CountProfit (boats, n);

else prof= CountProfit (boats, n) - CountProfit (boats, i);

if (boats[i].size == 1) // выгода расстановки однопалубного корабля

if (prof < 6) // нужно, чтоб однопалубные располагались далеко от других кораблей

return 1;

else return 0;

if (prof > boats[i].size*3+2) // выгода для больших кораблей

return 1; // плохо, если находятся рядом

else

return 0; // хорошо - если находятся близко друг к другу или к краям поля

}

Листинг А.5, лист 1

 // компьютер генерирует корабль размером s

boat GetBoatFromComp (int s) {

boat result;

result.size = s;

int a = RandC (FIELD_SIZE);

if (a% 2 == 0) {

result.orient = 'г';

result.start.x = RandC (FIELD_SIZE-s);

result.start.y = RandC (FIELD_SIZE);

} else {

result.orient = 'в';

result.start.y = RandC (FIELD_SIZE-s);

result.start.x = RandC (FIELD_SIZE);

}

return result;

}

 // функция управляет расстановкой кораблей

void SetBoatsByComp (boat* boats) {

int f[100];

FillField(f);

int i;

int c = 0;

for (i = 0; i < 10; i++) {

c = 0;

int a1, a2;

do {

c++;

boats[i] = GetBoatFromComp (boats[i].size);

a1 = CheckBoats (f, boats[i]);

if (c < 10)

a2 = CheckProfit (boats, i+1); // если сгенерированный корабль выгоден и его можно поставить,

else a2 = 0;

} while (a1 || a2);

SetOneBoat (f, &boats[i]);

}

}

/* - функции управляющие стрельбой компьютера -*/

 // функция заполняет массивы с координатами для точки a

void FillAround (coords* array, coords* diagonals, coords a) {

int i, j;

int dx[] = {0, 1, 0, -1}, dy[] = {-1, 0, 1, 0};

int x, y;

Листинг А.5, лист 2

for (i = 0; i < 4; i++) {

x = a.x

y = a.y;

for (j = 0; j < 3; j++) {

array [i*3+j].x = x += dx[i];

array [i*3+j].y = y += dy[i];

}

}

dx[0] = -1;

dy[1] = 1;

for (i = 0; i< 2; i++)

for (j = 0; j<2; j++) {

diagonals [i*2+j].x = a.x + dx[j];

diagonals [i*2+j].y = a.y + dy[i];

}

}

 // функция помечает на поле f клетку a числом с

int MarkPoint (int* f, coords a, int c) {

if(! (CheckCoord (a.y) || CheckCoord (a.x))) {

f [a.y*FIELD_SIZE + a.x] = c;

return 0;

} else

return 1;

}

 // функция проверяет клетку поля и указывает, какой вес прибавляет данная клетка

int CheckCoordForWeight (int* f, coords a) {

if (CheckCoord (a.x) || CheckCoord (a.y)) return 1;

if (f [a.y*10+a.x] == -100) return 0;

if (f [a.y*10+a.x]%10 == 5) return 2;

else return 1;

}

 // функция составляет матрицу весов, основываясь на переданной копии поля

void MakeFalseField (int* weight, int* f) {

int i, j, k, l, c, a;

coords around[12];

coords cur;

coords diag[4];

for (cur.y = 0; cur.y < FIELD_SIZE; cur.y++) {

for (cur.x = 0; cur.x < FIELD_SIZE; cur.x++) {

c = 0;

if (f[cur.y*FIELD_SIZE+cur.x] >= 0 && f [cur.y*FIELD_SIZE+cur.x]%10 ==0) {

Листинг А.5, лист 3

FillAround (around, diag, cur);

for (k = 0; k < 4; k++) {

a = 1;

for (l = 0; l < 3 && a; l++) {

a = CheckCoordForWeight (f, around [k*3+l]);

if (a == 2) c+=(3-l)*20;

if (a == 1) c+=l+1;

}

}

if (CheckCoordForWeight(f, diag[k])!= 0) c++;

} else c = -20;

MarkPoint (weight, cur, c);

}

}

}

 // Функция находит в матрице весов клетки с максимальным индексом

 // заполняет их индексами массив ind

 // и возвращает количество таких клеток

int FindMaxCells (int* f, int* ind) {

int i, max = 0, iMax = 0;

for (i = 0; i< 100; i++) {

if (f[i] == max) {

ind[iMax] = i;

iMax++;

}

if (f[i] > max) {

max = f[i];

iMax = 1;

ind[0] = i;

}

}

return iMax;

}

 // функция управляет выстрелами компьютера

coords MakeShotsByComp (int* f) {

int falseField[100]; // мнимое поле, на котором будет определяться вес каждой клетки

MakeCopy (f, falseField, 100);

MakeFalseField (falseField, f); // составляем поле, исходя из которого будем стрелять

int index[100], n; // index - массив с индексами элементов, имеющих максимальный вес на мнимом поле

n = FindMaxCells (falseField, index); // находим все клетки с максимальным весом

int a = RandC(n); // берем из них случайную клетку

Листинг А.5, лист 4

coords res;

res.x = index[a]%FIELD_SIZE;

res.y = index[a]/FIELD_SIZE;

return res;

}

Листинг А.5, лист 5

Листинг файла output.c

 // Функция печатает сообщение о том, что был потоплен корабль

void PrintDrown (int s) {

printf («!!! Ура!!!!%d-палубный корабль был потоплен!!! \n \n», s);

}

 // функция печатает для пользователей одну клетку поля

void PrintOneCell (int a) {

char c;

if (a >= 0 && a % 10 == 0) // если клетка пустая

c = 126;

else if (a == -100) // если она пустая и подбитая

c = 15;

else // если она подбитая и на ней есть корабль

c = 254;

printf («%2c», c);

}

 // функция печатает половину поля для того, чтобы посмотреть расстановку кораблей

void printhalf0 (int* f) {

int i, j;

printf («\n % 4c», ' ');

for (j = 0; j < FIELD_SIZE; j++) // печатаем шапку с буквами

printf («%4c», LETT[j]);

printf («\n»);

for (i = 0; i < FIELD_SIZE; i++) { // печатаем само поле

printf («%-4i|», i+1);

for (j = 0; j < FIELD_SIZE; j++) {

printf («%4i», f [i * FIELD_SIZE + j]/10);

}

printf («\n»);

}

}

 // функция печатает поле для игроков

void PrintField (field* f) {

int i, j;

printf («\n % 2c», ' ');

for (j = 0; j < FIELD_SIZE; j++)

printf («%2c», LETT[j]);

printf (» %3c», ' ');

for (j = 0; j < FIELD_SIZE; j++)

printf («%2c», LETT[j]);

printf («\n»);

Листинг А.6, лист 1

for (i = 0; i < FIELD_SIZE; i++) {

printf («%-2i|», i+1);

for (j = 0; j < FIELD_SIZE; j++) {

PrintOneCell (f->player1 [i * FIELD_SIZE + j]);

}

printf (» %-2i|», i+1);

for (j = 0; j < FIELD_SIZE; j++) {

PrintOneCell (f->player2 [i * FIELD_SIZE + j]);

}

printf («\n»);

}

}

 // функция выводит координаты

void PrintCoords (coords point) {

printf («%c % i\n», LETT [point.x], point.y + 1);

}

Листинг А.6, лист 2

Размещено на Allbest.ru

...

Подобные документы

  • Описание алгоритма хода ЭВМ в режиме "пользователь-компьютер" в игре "Морской бой". Описание совокупности классов, их полей и методов. Разработка интерфейса и руководства пользователя по проведению игры. Листинг программы, написанной на языке Java.

    курсовая работа [645,0 K], добавлен 26.03.2014

  • Обоснование необходимости разработки программы для игры "Тетрис". Математическая и графическая части алгоритма. Выбор языка и среды программирования. Отладка текста программы, разработка интерфейса пользователя. Тестирование, руководство пользователя.

    курсовая работа [1,5 M], добавлен 17.01.2011

  • Особенности разработки программы и выбор методов решения задачи. Составление алгоритма, распределение регистров программы и формирование файлов. Описание процедуры очистки памяти, сложения, вычитания, умножения. Тестирование и листинг программы.

    лабораторная работа [51,2 K], добавлен 14.05.2011

  • Приемы программирования в Delphi. Алгоритм поиска альфа-бета отсечения, преимущества. Описание программного средства. Разработка программы, реализующая алгоритм игры "реверси". Руководство пользователя. Листинг программы. Навыки реализации алгоритмов.

    курсовая работа [357,1 K], добавлен 28.02.2011

  • Описание правил игры "Морской бой". Особенности современных компьютеров и искусственного интеллекта. Создание общей блок-схемы программы, ее внешний вид. Необходимые переменные, процедуры и функции. Характеристика объектов, используемых в приложении.

    курсовая работа [950,1 K], добавлен 05.11.2012

  • Методика разработки алгоритма, по которому компьютер сможет играть в "Морской бой" с максимальным качеством, и при этом не подглядывая расположение флота игрока. Математические и алгоритмические основы решения задачи, составление программы решения.

    курсовая работа [365,4 K], добавлен 20.01.2010

  • Проектирование игры "Морской бой" путем составления диаграмм UML, IDEF0, DFD, моделирующих требования к программе. Разработка программы с использованием языка C# и фреймворка.NETFramework 3.5. Тестирование белого ящика и альфа-тестирование продукта.

    курсовая работа [3,9 M], добавлен 24.10.2013

  • Описание принципа развивающей игры в слова "Виселица". Разработка программы, реализующей задачу данной игры на языке Delphi. Обоснование выбора среды программирования, листинг файла, результаты отладки и тестирования, руководство для пользователя.

    курсовая работа [572,7 K], добавлен 14.07.2012

  • Технические и пользовательские характеристики игры, требования к программному обеспечению и среде разработки C#. Составление блок-схемы алгоритма, uml-диаграммы и текста программы, тестирование корректности компьютерного кода и результатов его работы.

    курсовая работа [1,8 M], добавлен 05.03.2013

  • Применение программного обеспечения для разработки игры "Быки и коровы". Описание алгоритма и интерфейса пользователя программы. Назначение и область применения и описание возможностей программы. Рассмотрение списка сообщений об ошибках программы.

    курсовая работа [799,2 K], добавлен 26.04.2021

  • Порядок разработки программы, реализующей игру "Морской бой" в режиме пользователь – компьютер. Основные свойства объектно-ориентированного программирования. Создание нескольких классов, которые будут взаимодействовать между собой, другие свойства ООП.

    курсовая работа [570,3 K], добавлен 11.06.2010

  • Программная реализация игры, необходимость наличия файла Arcanoid.exe. Список файлов, технические требования, состав программы. Алгоритм игры. Основные достоинства данного программного продукта, системные требования и руководство пользователя.

    курсовая работа [753,6 K], добавлен 28.12.2011

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

    курсовая работа [2,5 M], добавлен 22.12.2012

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

    курсовая работа [196,2 K], добавлен 26.03.2009

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

    курсовая работа [1,7 M], добавлен 08.06.2009

  • Разработка эскизного и технического проекта программы игры "Собери картинку". Назначение и область применения, основные технические характеристики. Разработка рабочего проекта, разработка и спецификация программы игры. Описание и тестирование программы.

    курсовая работа [22,6 K], добавлен 10.06.2010

  • Знакомство с интерфейсом пользователя и сценарием использования программы игры в крестики и нолики. Функциональные и нефункциональные требования для персонального компьютера. Исключительные ситуации и реакция программы. Пример кода игры и комментарии.

    курсовая работа [236,5 K], добавлен 27.01.2014

  • Написание программы, формирующей текстовый файл и выводящую на экран таблицу согласно заданному условию. Реализация принципа формирования текстовых файлов, разработка отдельных модулей (процедур) выбора информации из файла. Листинг полученной программы.

    курсовая работа [769,1 K], добавлен 29.12.2011

  • Разработка программы логической игры в "крестики-нолики" пять в ряд на поле размера 15х15 клеток с применением графики на языке Pascal с использованием объектно-ориентированного программирования. Структура алгоритма программы и описание ее работы.

    курсовая работа [821,5 K], добавлен 13.02.2012

  • Разработка и реализация компьютерной игры "Змейка" с помощью языка программирования Pascal и модуля CRT. Составление общего алгоритма программы, выделение ее функциональных частей. Разработка тестовых примеров. Использование типизированных файлов.

    курсовая работа [2,1 M], добавлен 23.02.2011

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.