Игра на Си движение в лабиринте

10 декабря 2018 - Администратор

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

Процедура clear().

Процедура должна очищать всё игровое поле.

xm, ym – глобальные переменные, обозначают ширину и высоту создаваемого экрана для графики.

Для того, чтобы очистить всё поле, нужно закрасить всё поле чёрным цветом.

// очищаем поле от пройденного лабиринта

void clear() { 

              setfillstyle (1, 0);

                bar( 0, 0, xm, ym );         

}

Напомним, что setfillstyle (1, 0); задает параметры заполнения для оператора bar. Первый параметр задет вид заливки 1 означает полная сплошная заливка. Второй параметр задает цвет заливки. 0 означает  черный цвет.

Процедура Draw(x, y, color)

Процедура должна рисовать квадрат шириной s в заданном месте.

x, y – координаты точки центра, где рисуется квадрат.

color – цвет, которым рисуется квадрат.

s – глобальная переменная, отвечающая за ширину квадрата.

Чтобы нарисовать квадрат шириной s, с помощью команды bar для верхнего левого угла мы должны отнять от координат по s, для нижнего правого прибавить по s, так как ось Y направлена вниз, в отличие от математических координат.

// рисуем движущийся объект

void Draw ( int x, int y, int color )

  {

  setfillstyle( 1, color );  //  сплошная  заливка, цвет color

  bar ( x-s, y-s, x+s, y+s); //  залитый прямоугольник 

  }

Процедура labirint(nur). Процедура должна рисовать на поле для игры лабиринты. Каждому лабиринту соответствует свой номер nur.

схема лабиринта

nur – номер лабиринта, который нужно нарисовать.

xm, ym – глобальные переменные, обозначают ширину и высоту создаваемого экрана для графики.

Сначала необходимо нарисовать границы лабиринты, затем  ряд  вертикальных и горизонтальных стенок. В лабиринте указывается зона  финиша другим цветом.

Допустим, нам нужно нарисовать лабиринт под номером 2. Чтобы выбрать лабиринт под этим номером, нужно создать if с условием nur == 2. Пример.

if (nur == 1) {…

}

// отображение лабиринта с  номером nur

void labirint(int nur) // строим лабиринт

{  // первый уровень

  if (nur == 1) {

  clear();

  setfillstyle ( 1, 15 );   //  сплошная  заливка

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

  bar ( 0, 0, xm, 1 );

  bar ( 0, 0, 1, ym );

  bar ( xm-1, 0, xm, ym );

  bar ( 0, ym-1, xm, ym );

  // рисуем стены

  bar ( 150, 1, 180, 300 );

  bar ( 250, 150, 280, 400 ); 

  bar ( 180, 20, 400, 50 );

  bar ( 0, 80, 80, 120 );

  bar ( 40, 180, 150, 210 );

  // рисуем финиш

  setfillstyle ( 1, 12 );

  bar ( 350, 200, 380, 230 );

}

// второй уровень

if (nur == 2) {

  clear();

  setfillstyle ( 1, 15 );   //  сплошная  заливка

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

  bar ( 0, 0, xm, 1 );

  bar ( 0, 0, 1, ym );

  bar ( xm-1, 0, xm, ym );

  bar ( 0, ym-1, xm, ym );

  // рисуем стены

  bar ( 0, 100, 300, 120 );

  bar ( 100, 200, 400, 220 );

  bar ( 0, 300, 300, 320 );

  bar ( 150, 150, 170, 270 );

 // рисуем финиш

  setfillstyle ( 1, 12 );

  bar ( 20, 340, 50, 370 );

}

}

Функция sost(x, y, vel).

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

1      на данном месте черное поле

2      на данном месте финиш

3      на данном месте стена лабиринта или его граница

x, y – координаты квадрата, возле которого проверяется местность возле квадрата.

vel – скорость квадрата в данном раунде.

val – переменная, возвращаемая рассматриваемой функцией в зависимости от местности возле квадрата.

n1, n2, n3, n4 –цвета пикселей возле квадрата.

Чтобы получить цвет пикселя в данной точке, нужно ввести команду getpixel(x, y), где x, y – координаты точки. Свободному месту соответствуют черные точки с кодом цвета 0,  лабиринту  и границе белые с кодом цвета 15, зоне финиша соответствуют розовые пиксели с кодом цвета  12.

Чтобы проверить попал ли наш объект в свободную зону мы должны считать  все угловые точки квадрата и проверить, что они все черного цвета.

в условии используется логическая операция И. Подробно о логических операциях в си

    if ((n1==0) && (n2==0) && (n3==0) && (n4==0)) {val=1;};// свободно

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

    if ((n1==15) || (n2==15) || (n3==15) || (n4==15)) {val=3;}// столкнулись с препятствием

Аналогично для зоны финиша.

   if ((n1==12) || (n2==12) || (n3==12) || (n4==12)) {val=2;}// достигли финиша

Подробно о работе  с условиями и логическими функциями в Си можно познакомится на уроке Условия в Си

// проверка  движения состояние 1 свободно, 2 финиш, 3 наехали на препятствие

int sost (int x, int y, int vel)

{  

    int val;// состояние

    val=0;

    int n1, n2, n3, n4; // цвета по сторонам

    n1=getpixel(x-s-1, y);//цвет слева

    n2=getpixel(x+s+1, y);// цвет справа

    n3=getpixel(x, y-s-1);// цвет сверху

    n4=getpixel(x, y+s+1);// цвет снизу  

    if ((n1==0) && (n2==0) && (n3==0) && (n4==0)) {val=1;};// свободно

    if ((n1==12) || (n2==12) || (n3==12) || (n4==12)) {val=2;}// достигли финиша

    if ((n1==15) || (n2==15) || (n3==15) || (n4==15)) {val=3;}// столкнулись с препятствием

    return val;

}

Процедура tur(vel, nur).Процедура должна проводить одну игру с квадратом, перемещающимся со скоростью vel и на лабиринте под номером nur.

vel – скорость квадрата в данном раунде.

nur – номер лабиринта, на котором проводится раунд.

xg, yg – начальные координаты квадрата.

dx – направление перемещения квадрата по горизонтали.

dy – направление перемещения квадрата по вертикали.

code – код нажатой клавиши.

res – состояние игры в данный момент.

Для  того , чтобы  определить нажата ли кнопка клавиатуры  используется функция Си  kbhit().

С помощью функции Си  getch() можно получить код нажатой клавиши.

Изменение направления движения происходит с помощью условной конструкции switch() { case: …}. Здесь прописаны все коды клавиш стрелок, и если на одну из них нажали, то направление меняется в соответствующую сторону.

Функция будет работать пока  мы на свободном поле, т.е. значение функции  sost ()

 равно 1. чтобы реализовать этот алгоритм используется цикл while.

Подробно о циклах в Си можно познакомится на уроке  циклы в Си.

// очередной тур  с номером лабиринта nur и скоростью vel

void tur (int nur, int vel)

{

// результат игры

int xg=20;

int yg=20;

int dx = 1;

int dy = 0; // сначала двигается вправо

  int code;// код нажатой клавиши

// рисуем лабиринт

labirint(nur);

while ( sost(xg, yg, vel)==1 )          //  выполняем пока поле свободно

  {

  if ( kbhit() ) {             //  если нажата клавиша 

    code = getch();               //  получить  ее код 

    if ( code == 27 ) break;      //  если Esc, то выход 

    switch ( code ) {             //  изменить  направление движения 

      case 75: dx = -1; dy = 0; break;

      case 77: dx = 1;  dy = 0; break;

      case 72: dx = 0;  dy = -1; break;

      case 80: dx = 0;  dy = 1;

      }

   }

 Draw ( xg, yg, COLOR(255,255,0) ); //  рисуем квадрат

 delay(200/vel);                   //  ждем

 Draw ( xg, yg, COLOR(0,0,0) );   //  стираем 

 xg += dx;                       //  двигаем квадрат

 yg += dy;

 }

 res=sost(xg,yg, vel);

 if (res==3){lifen=lifen+1;}     

 }

Полный текст программы на си игра лабиринт

#include <conio.h>
#include <graphics.h>
int xm=400;// ширина экрана
int ym=400;// высота экрана
int lifemax=5;// максимальное количество жизней
int nur; // текущий номер уровня
int lifen; // текущее количество жизней
int res;
const int s = 4;

// очищение экрана

void clear()

{
setfillstyle ( 1, BLACK );
bar ( 1, 1, xm, ym);
}

// отображение лабиринта с  номером nur

void labirint(int nur) // строим лабиринт
{
 // первый уровень

  if (nur == 1) {
  clear();
  setfillstyle ( 1, 15 );   //  сплошная  заливка
 // рисуем границы, чтобы квадрат не выходил за пределы экрана
  bar ( 0, 0, xm, 1 );
  bar ( 0, 0, 1, ym );
  bar ( xm-1, 0, xm, ym );
  bar ( 0, ym-1, xm, ym );

 // рисуем стены
  bar ( 150, 1, 180, 300 );
  bar ( 250, 150, 280, 400 ); 
  bar ( 180, 20, 400, 50 );
  bar ( 0, 80, 80, 120 );
  bar ( 40, 180, 150, 210 );

// рисуем финиш

  setfillstyle ( 1, 12 );
  bar ( 350, 200, 380, 230 );

}

// второй уровень

if (nur == 2) {
  clear();
  setfillstyle ( 1, 15 );   //  сплошная  заливка

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

  bar ( 0, 0, xm, 1 );
  bar ( 0, 0, 1, ym );
  bar ( xm-1, 0, xm, ym );
  bar ( 0, ym-1, xm, ym );

// рисуем стены
  bar ( 0, 100, 300, 120 );
  bar ( 100, 200, 400, 220 );
  bar ( 0, 300, 300, 320 );
  bar ( 150, 150, 170, 270 );
// рисуем финиш
  setfillstyle ( 1, 12 );
  bar ( 20, 340, 50, 370 );
}
}

// проверка  движения состояние 1 свободно, 2 наехали на препятствие, 3 финиш
int sost (int x, int y, int vel)
{   int val;// состояние
    val=0;
    int n1, n2, n3, n4; // цвета по сторонам
    n1=getpixel(x-s-1, y);//цвет слева
    n2=getpixel(x+s+1, y);// сцвет справа
    n3=getpixel(x, y-s-1);// цвет сверху
    n4=getpixel(x, y+s+1);// цвет снизу
    if ((n1==0) && (n2==0) && (n3==0) && (n4==0)) {val=1;};// свободно
    if ((n1==12) || (n2==12) || (n3==12) || (n4==12)) {val=2;}// достигли финиша
    if ((n1==15) || (n2==15) || (n3==15) || (n4==15)) {val=3;}// столкнулись с препятствием
    return val;
}

// рисуем движущийся объект
void Draw ( int x, int y, int color )
  {
  setfillstyle( 1, color );  //  сплошная  заливка, цвет color
  bar ( x-s, y-s, x+s, y+s); //  залитый прямоугольник 
  }

// очередной тур  с номером лабиринта nur и скоростью vel

void tur (int nur, int vel)
{
// результат игры
int xg=20;
int yg=20;
int dx = 1;
int dy = 0; // сначала двигается вправо
int code;// код нажатой клавиши
labirint(nur);

while ( sost(xg, yg, vel)==1 )          //  бесконечный цикл  пока поле свободно
  {
  if ( kbhit() ) {             //  если нажата клавиша 
    code = getch();               //  получить  ее код 
    if ( code == 27 ) break;      //  если Esc, то выход 
    switch ( code ) {             //  изменить  направление движения 
      case 75: dx = -1; dy = 0; break;
      case 77: dx = 1;  dy = 0; break;
      case 72: dx = 0;  dy = -1; break;
      case 80: dx = 0;  dy = 1;
      }
   }
 Draw ( xg, yg, COLOR(255,255,0) ); //  рисуем квадрат
 delay(200/vel);                   //  ждем
 Draw ( xg, yg, COLOR(0,0,0) );   //  стираем 
 xg += dx;                       //  двигаем квадрат
 yg += dy;
 }
 res=sost(xg,yg, vel);
 if (res==3){lifen=lifen+1;}
     }
main()
{    
res=3;
initwindow (xm, ym);        //  открыть окно для  графики  
while (res==3 && lifen<lifemax)
{
tur(1, 70);
tur(2, 50);
}
 getch(); 
 closegraph();     //  закрыть окно для  графики
}

Задание . Нарисуете еще олин лаиринт и создайте еще один уровень

Вернуться к содержанию

Комментарии (0)

Нет комментариев. Ваш будет первым!