Программ-игра «Морской бой», с использованием анимированных графических объектов и возможностью управлять их движением с помощью клавиатуры

Домашняя работа

по программированию

за второй семестр

Игра «Морской Бой»

Выполнил: Макаров В. А.

группа: С-26

Игра «Морской Бой»

Требуется:

Разработать программу-игру «Морской бой», с использованием анимированных графических объектов и возможностью управлять их движением с помощью клавиатуры.

Эскиз:

Аномалии:

Аномалия

Действие программы

1) Произошла ошибка инициализации графики

Вывод сообщения:

«InitGraph ERROR!»

2) При игре было допущено более пяти промахов. Проигрыш.

Вывод сообщения

«GAME OVER»

Внешняя спецификация:

Вход:

Vipolnil: Makarov Vladimir

Group: C-26

Press <Enter> to start play game!

Выход при проигрыше:

GAME OVER

Метод:

Описание:

Во время игры на экране изображена водная поверхность и две скалы по бокам. Время от времени из-за скал выплывают различные корабли, которые движутся вдоль горизонта к противоположенной скале. Существует три типа кораблей: маленький, средний и большой. Тип корабля всегда выбирается случайным образом. Скорость каждого корабля зависит от размера самого корабля: маленький самый быстрый, остальные соответственно обладают более низкой скоростью. Цель игрока состоит в том, чтобы с помощью пушки и прицела подбить как можно большое количество кораблей и не промахиваться. Количество подбитых кораблей (scope) показывается в нижнем левом углу экрана. Игрок должен нацеливать пушку влево или вправо и стрелять по возможности на опережение, так как снаряд вылетающий из пушки обладает относительно малой скоростью. В случае промаха игрока, корабль разворачивается и уплывает в обратную сторону. Если игрок совершил более пяти промахов, то он проигрывает и выходит из игры.

Прицеливание осуществляется с помощью стрелок (вправо и влево) на клавиатуре, пробел – стрельба и escape – выход.

Основной метод:

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

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

Рисование всех двигающихся объектов производится для удобства в отдельных процедурах. В качестве параметров туда передаётся координата по оси или x или y, так же туда передаётся флаг, указывающий на то – рисовать объект или стирать. Под стиранием объекта понимается его рисование цветом фона.

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

Скорости всех двигающихся в программе объектов различны:

V>снаряда> > V>корабля №1> > V>корабля №2 >> V>корабля №3>

Временная задержка во всей программе постоянная и используется один раз за цикл. Если один проход цикла назвать тактом, то разность скоростей объектов реализована за счёт того, что каждый объект перемещается на единицу расстояния не за каждый такт, а за каждый n-ный такт, а n определено для каждого объекта по-разному. Чем меньше n, тем быстрее скорость. В данной программе все скорости постоянны.

Алгоритм:

Procedure target (ix: integer; bb: boolean)

Входные данные: ix:цел bb:лог

Внутренние постоянные переменные: iy=200

начало

если bb то {Отображение}

Установить цвет(green)

Установить тип заливки(SolidFill,green)

Нарисовать закрашенный эллипс(ix,430,26,100)

Выбрать цвет(lightgreen)

Нарисовать линию(ix-10,iy,ix+10,iy)

Нарисовать линию(ix,iy-10,ix,iy+10)

иначе {Стирание}

Установить тип заливки(SolidFill,blue)

Установить цвет(blue)

Нарисовать закрашенный эллипс( (ix,430,26,100)

Установить цвет(blue)

Нарисовать линию(ix-10,iy,ix+10,iy)

Нарисовать линию(ix,iy-10,ix,iy+10)

всё

конец

Часть 2: Поиск в тексте единиц и вставка после них нулей

Входные данные: var st:мас:стр r:цел var one:лог

Выходные данные: rez:масс:стр iz:цел

Внутренние переменные: k,l:цел

начало

one:=ложь

цикл для k:=1 до r делать

l:=1

цикл пока l<=длина(st[k]) делать

если st[k][l]='1' то

insert('0',st[k],l+1) {Вставить после нуля единицу}

one:=истина {Значит, в тексте есть единицы}

всё

inc(l) {l:=l+1}

кцикл

кцикл

всё

Вспомогательная функция: Определяет, является ли символ цифрой

Входные данные: с:сим

Выходные данные: лог

Внутренние переменные: e:цел fl:лог

начало

fl:=ложь

d:='0123456789' {все цифровые символы}

цикл для e:=1 до 10 делать {перебор всех символов цифр}

если c=d[e] то fl:=истина

кцикл

{Ели символ является цифрой, то функция возвратит истину,

иначе возвратит ложь}

digs:=fl {функция возвращает значение}

всё

Исходный код всей программы:

{Домашнее задание на тему "графика"}

{Выполнил студент: Макаров Владимир, группа С-26}

{Игра "Морской Бой"}

program SeaWar;

uses Graph,crt;

var

GraphDriver:integer;

GraphMode:integer;

ErrorCode:integer; {Переменные для инициализации графики}

s_score:string;

{Все переменные, используемые в программе}

x :integer;

y :integer; {Переменные для хранения координат}

xx :integer; {и переменные цикла}

typ :integer; {Тип текущего корабля}

xxx :integer; {Координаты}

tarx :integer; {Координаты прицела и пушки}

fx :integer; {Координаты}

fy :integer;

score :integer; {Кол-во очков}

old_score :integer; {Прошлое значение кол-ва очков}

mimo :integer; {Кол-во промахов}

oldx :integer; {Координаты}

oldy :integer;

crx :integer;

cr_type :integer; {Тип корабля}

flang :integer; {С какой стороны плывёт корабль}

croldx :integer;

cr_ind2 :integer;

cr_ind:longint; {Рабочая переменная}

c:char; {Хранение нажатых клавиш}

{Флаги}

b :boolean; {Флаг нажатия клавиш "стрелок"}

fire :boolean; {Стрельба}

swim :boolean; {Перемещение}

promah :boolean; {Промах}

vzriv :boolean; {Взрыв}

const

{Два константных массива точек для хранения координат скал}

trin1:array[1..4] of PointType=

((x:-70;y:380),(x:60;y:20),(x:150;y:350),(x:-70;y:380));

trin2:array[1..4] of PointType=

((x:670;y:380),(x:560;y:5),(x:500;y:350),(x:670;y:400));

{Процедура вывода прицела и пушки на экран}

procedure target(ix:integer;bb:boolean);

const iy=200;

begin

if bb then begin {Отображение}

SetColor(green);

SetFillStyle(SolidFill,green);

FillEllipse(ix,430,26,100);

SetColor(lightgreen);

Line(ix-10,iy,ix+10,iy);

Line(ix,iy-10,ix,iy+10);

end else begin {Стирание}

SetFillStyle(SolidFill,blue);

SetColor(blue);

FillEllipse(ix,430,26,100);

SetColor(blue);

Line(ix-10,iy,ix+10,iy);

Line(ix,iy-10,ix,iy+10);

end;

end;

{Процедура вывода на экран различных кораблей}

procedure sheep(ix:integer;tip:integer;bb:boolean);

const

iy=200;

var

col,col2:integer;

sp1,sp2,sp3:array[1..5] of PointType;

begin

col:=brown;

col2:=yellow;

if not bb then begin {Если bb=true, то отображение корабля}

col:=blue; {Иначе стирание корабля}

col2:=blue;

end;

{Координаты кораблей, относительно центральной точки ix}

sp1[1].x:=ix-40;

sp1[1].y:=190;

sp1[2].x:=ix+40;

sp1[2].y:=190;

sp1[3].x:=ix+20;

sp1[3].y:=215;

sp1[4].x:=ix-20;

sp1[4].y:=215;

sp1[5].x:=sp1[1].x;

sp1[5].y:=sp1[1].y;

sp2[1].x:=ix-30;

sp2[1].y:=190;

sp2[2].x:=ix+30;

sp2[2].y:=190;

sp2[3].x:=ix+15;

sp2[3].y:=210;

sp2[4].x:=ix-15;

sp2[4].y:=210;

sp2[5].x:=sp2[1].x;

sp2[5].y:=sp2[1].y;

sp3[1].x:=ix-20;

sp3[1].y:=195;

sp3[2].x:=ix+20;

sp3[2].y:=195;

sp3[3].x:=ix+10;

sp3[3].y:=205;

sp3[4].x:=ix-10;

sp3[4].y:=205;

sp3[5].x:=sp3[1].x;

sp3[5].y:=sp3[1].y;

{Отображение одного из трёх типов кораблей}

case tip of

3: begin

SetColor(col);

SetFillStyle(SolidFill,col);

FillPoly(5,sp1);

Rectangle(ix-18,iy-30,ix+18,iy-2);

SetColor(col2);

SetFillStyle(SolidFill,col2);

Rectangle(ix-10,iy-25,ix+10,iy-15);

FillEllipse(ix-18,iy,5,5);

FillEllipse(ix+18,iy,5,5);

FillEllipse(ix,iy,5,5);

end;

2: begin

SetColor(col);

SetFillStyle(SolidFill,col);

FillPoly(5,sp2);

line(ix,200,ix,170);

line(ix-5,175,ix+5,175);

line(ix-10,180,ix+10,180);

end;

1: begin

SetColor(col);

SetFillStyle(SolidFill,col);

FillPoly(5,sp3);

line(ix,200,ix,185);

line(ix-5,185,ix+5,185);

line(ix-10,190,ix+10,190);

end;

end;

end;

{Начало главной процедуры программы}

begin

x:=100;

xx:=0;

xxx:=0;

oldx:=0;

b:=false;

tarx:=320;

fire:=false; {инициализация переменных}

crx:=0;

croldx:=800;

score:=0;

old_score:=0;

mimo:=0;

promah:=false;

vzriv:=false;

{Переключение в графический режим}

GraphDriver:=Detect;

InitGraph(GraphDriver,GraphMode,'');

if ErrorCode=grok then begin

SetColor(green);

SetBKColor(black);

end else begin

Writeln('ERROR!');

exit;

end;

SetColor(white);

OutText('Vipolnil: Makarov Vladimir');

OutTextXY(0,10,'Group: C-26');

SetTextJustify(CenterText,CenterText);

OutTextXY(640 div 2,480 div 2,'Press <Enter> to start play game!');

c:=ReadKey;

{Подготовка экрана к игре}

ClearDevice;

SetBkColor(blue);

SetColor(lightgray);

SetFillStyle(SolidFill,lightgray);

FillPoly(4,trin1);

FillPoly(4,trin2);

SetColor(black);

Target(320,true);

{Главный цикл обработки различных сообщений и событий}

repeat

repeat

{Обработка сообщения "Взрыв корабля"}

if vzriv then begin

if xx=0 then begin

typ:=cr_type;

xxx:=crx;

end;

if xx<150 then begin

{Рисование взрыва}

Sound(Random(100));

swim:=false;

SetColor(red);

SetColor(red);

SetFillStyle(SolidFill,red);

FillEllipse(xxx,200,21*typ,17*typ);

inc(xx);

end else begin

NoSound;

swim:=false;

SetColor(blue);

SetFillStyle(SolidFill,blue);

FillEllipse(xxx,200,21*typ,17*typ);

xx:=0;

vzriv:=false;

end;

end;

{Обработка сообщения "Перемещение"}

if swim then begin

if cr_ind<400 then begin

Sheep(crx,cr_type,false);

if promah then promah:=false;

end else begin

if cr_ind mod cr_type*5=0 then begin

if promah then begin

if flang=0 then flang:=1

else flang:=0;

promah:=false;

end;

if flang=0 then begin

if crx=485 then begin

inc(cr_ind2);

if cr_ind2<3 then Sheep(crx,cr_type,true)

else begin

Sheep(crx,cr_type,false);

swim:=false;

end;

end else begin

crx:=crx+1;

Sheep(croldx,cr_type,false);

Sheep(crx,cr_type,true);

croldx:=crx;

end;

end else begin

if crx=150 then begin

inc(cr_ind2);

if cr_ind2<3 then Sheep(crx,cr_type,true)

else begin

Sheep(crx,cr_type,false);

swim:=false;

end;

end else begin

crx:=crx-1;

Sheep(croldx,cr_type,false);

Sheep(crx,cr_type,true);

croldx:=crx;

end;

end;

end;

end;

inc(cr_ind);

end else begin

{Если корабля нет на экране, то случайным методом

выбирается новый корабль}

Randomize;

croldx:=800;

cr_ind2:=0;

if random(2)=0 then begin

crx:=150;

flang:=0;

end else begin

crx:=485;

flang:=1;

end;

swim:=true;

cr_ind:=0;

Randomize;

cr_type:=random(3)+1;

end;

{Обработка сообщения "Выстрел"}

{и рисование полёта снаряда}

if fire then begin

x:=x-10;

Sound(x);

SetColor(blue);

line(fx+1,fy-2,fx+1,fy+2);

line(fx-1,fy-2,fx-1,fy+2);

line(fx,fy-2,fx,fy+2);

fy:=fy-2;

SetColor(lightred);

line(fx+1,fy-2,fx+1,fy+2);

line(fx-1,fy-2,fx-1,fy+2);

line(fx,fy-2,fx,fy+2);

if fy<200 then begin

if (getpixel(fx-1,fy-3)=brown)or(getpixel(fx+1,fy-3)=brown) then begin

old_score:=score;

inc(score);

vzriv:=true;

end else begin

{Обработка сообщения "Промах"}

promah:=true;

inc(mimo);

if mimo>5 then begin

{Выход из игры в случае проигрыша}

ClearDevice;

SetColor(white);

SetBkColor(black);

SetTextJustify(CenterText,CenterText);

OutTextXY(640 div 2,480 div 2,'GAME OVER!');

Sound(200);

Delay(10000);

NoSound;

c:=ReadKey;

exit;

end;

end;

fire:=false;

NoSound;

SetColor(blue);

line(fx+1,fy-2,fx+1,fy+2);

line(fx-1,fy-2,fx-1,fy+2);

line(fx,fy-2,fx,fy+2);

end;

end;

if b then begin

{Перерисовка прицела и пушки в случае нажатия клавиш "стрелок"}

target(oldx,false);

target(tarx,true);

b:=false;

end else target(tarx,true);

{В случае попадания, производится начисление очков и вывод их на экран}

if old_score<>score then begin

SetColor(blue);

SetTextJustify(LeftText,BottomText);

Str(old_score,s_score);

OutTextXY(70,460,s_score);

old_score:=score;

end;

SetColor(white);

SetTextJustify(LeftText,BottomText);

OutTextXY(20,460,'Score');

Str(score,s_score);

OutTextXY(70,460,s_score);

delay(150); {Временная задержка главного цикла}

until keypressed;

{Обработка нажатия клавиш}

c:=readkey;

case c of

#75: begin {влево}

if tarx>220 then begin

oldx:=tarx;

tarx:=tarx-5;

b:=true;

end;

end;

#77: begin {вправо}

if tarx<420 then begin

oldx:=tarx;

tarx:=tarx+5;

b:=true;

end;

end;

#32: begin {пробел "Выстрел"}

if not fire then begin

x:=800;

fire:=true;

fx:=tarx;

fy:=380;

end;

end;

#27: begin {esc "Выход"}

NoSound;

exit;

end;

end;

until false; {Зацикливание главного цикла обработки сообщений}

end.