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

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

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

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

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

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

                                      группа: С-26

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

Требуется:

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

Эскиз:

 SHAPE  \* MERGEFORMAT

Аномалии:

Аномалия

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

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.