Побудуйте двигун для гри в лабіринті


9

Це подальше запитання щодо друку лабіринту . Якщо вам подобається це питання, будь ласка, додайте більше алгоритмів генерації лабіринту;).

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

Двигун запускається зчитуванням лабіринту зі стандартного вводу, а потім рядком, що містить файл .(крапка), поданий як аргумент у командному рядку. Далі гравець @розміщується у випадковому місці на карті. Потім двигун починає взаємодіяти з програвачем через стандартні io:

Команди від двигуна до гравця :

  • continue: Гра не закінчена. Навколишнє середовище друкується з написом .. Гравець представлений @символом. Клітини, що не спостерігаються, представлені символами ?.
  • finished: Гра закінчена. Надрукується кількість кроків і гра припиняється.

Команди від гравця до двигуна :

  • north: Переміщення гравця вгору.
  • south: Переміщує програвача вниз.
  • west: Переміщення гравця вліво.
  • east: Переміщення гравця вправо.

Будь-яка недійсна команда (наприклад, удари об стіну) від гравця ігнорується, але все ж рахується. Ви можете визначити околиці на свій смак.

  • Бали за найкоротший код.
  • Точки для складного оточення (наприклад, надрукуйте великі регіони та замініть комірки, які не видно ?).
  • Немає балів для коду, який не відповідає формату io

Приклад :

У цьому прикладі оточення визначається як осередок 3х3 з програвачем посередині.

$ cat maze
+-+-+
  |#|
|   |
+---+
$ python engine.py maze
 |#
 @ 
---
.
east
|#|
 @|
--+
.
north
+-+
|@|
  |
.
south
|#|
 @|
--+
.
west
 |#
 @ 
---
.
west
  |
|@ 
+--
.
north
+-+
 @|
|  
.
west
finished
7

@ Александру: Що ми використовуємо для створення наших лабіринтів? Чи можемо ми використовувати алгоритми лабіринтів інших людей (очевидно, з належним кредитом)? Або ми повинні виконати ваше перше завдання?
— snmcdonald

@snmcdonald: виправлена ​​помилка. Використовуйте чужі лабіринти. Пам'ятайте, що двигун зчитує лабіринт зі стандартного вводу.
— Олександру

Цей блог має відмінні статті по лабіринту покоління , використовуючи різні і змішані алгоритми weblog.jamisbuck.org Перевірте зростаючий алгоритм дерева в-зокрема weblog.jamisbuck.org/2011/1/27 / ...
— Дв

Мене бентежить те, як і лабіринт, і взаємодія з користувачем виходять із стандартних даних. Чи повинен користувач вводити свій лабіринт, а потім вирішувати його? Ніби не перемагає мету лише показати частину лабіринту ...
— Кіт Рендалл

Ви можете створити додаток (це завдання залишилося для іншого питання) поверх нього, щоб відокремити введення лабіринту від введення команд.
— Олександру

Відповіді:


7

C99, 771 персонаж

#include <ncurses.h>
#include <string.h>
#define MIN(A,B) (A<B?A:B)
#define MAX(A,B) (A>B?A:B)
#define T(C,X,Y) case C:if((m[x+X][y+Y]==' ')||(m[x+X][y+Y]=='#'))x+=X,y+=Y;s++;break;
char m[24][81],M[24][81];int i,j,I=0,J,x,y,s=0;
int main(int c,char**v){FILE*f=fopen(v[1],"r");
for(I=0;fgets(m[I],80,f);I++)J=MAX(J,strlen(m[I]));
J--;f=fopen("/dev/random","r");do{x=fgetc(f)%I;y=fgetc(f)%J;}
while(m[x][y]!=' ');initscr();curs_set(0);do{
switch(c){T('e',0,1)T('n',-1,0)T('s',1,0)T('w',0,-1)}
for(i=MAX(0,x-1);i<MIN(x+2,I);i++)for(j=MAX(0,y-1);j<MIN(y+2,J);j++)M[i][j]=1;
for(i=0;i<I;i++)for(j=0;j<J;j++)mvaddch(i,j,M[i][j]?m[i][j]:'?');
mvaddch(x,y,'@');refresh();}while((m[x][y]!='#')&&(c=getch())!='q');
if(m[x][y]=='#')mvprintw(I,0,"Finished in %d steps!",s),getch();endwin();}

Вимагає та використовує ncurses. Лише одна макроізоляція на довжину, а макроси N і M повинні замінити відсутні мінімум та максимальний оператор, і я не думаю, що на цьому можна зробити багато іншого.

Це передбачає , що вхідний лабіринт не перевищує 80 символів в ширину, і що лабіринти ім'я файлу вже було передано в командному рядку, і що число параметрів досить низько , що початкове значення з не команда руху.

  • Відхиляється від стандарту тим, що він приймає команди з одним символом як першу літеру з запропонованих рядків.

  • Показує невідомі регіони як "?".

Більше читати з коментарями:

#include <ncurses.h>
#include <string.h>

#define MIN(A,B) (A<B?A:B)/*unsafe,but short*/
#define MAX(A,B) (A>B?A:B)/*unsafe,but short*/
// #define MAX(A,B) ((_A=A)>(_B=B)?_A:_B) /* safe but verbose */
#define T(C,X,Y) case C:if((m[x+X][y+Y]==' ')||(m[x+X][y+Y]=='#'))x+=X,y+=Y;s++;break;
char m[24][81],M[24][81];/* [m]ap and [M]ask; NB:mask intialized by default */
int i,j, /* loop indicies over the map */
  I=0,J, /* limits of the map */
  x,y,   /* player position */
  s=0;   /* steps taken */
int main(int c,char**v){
  FILE*f=fopen(v[1],"r"); /* fragile, assumes that the argument is present */
  /* Read the input file */
  for(I=0;fgets(m[I],80,f);I++)J=MAX(J,strlen(m[I])); /* Read in the map */ 
  J--;
  /* note that I leak a file handle here */
  f=fopen("/dev/random","r");
  /* Find a open starting square */
  do{ 
    x=fgetc(f)%I; /* Poor numeric properties, but good enough for code golf */
    y=fgetc(f)%J;
  } while(m[x][y]!=' ');
  /* setup curses */
  initscr(); /* start curses */
  //  raw();     /* WARNING! intercepts C-c, C-s, C-z, etc...
  //          * but shorter than cbreak() 
  //          */
  curs_set(0); /* make the cursor invisible */
  /* main loop */
  do {
    switch(c){
      T('e',0,1)
      T('n',-1,0)
      T('s',1,0)
      T('w',0,-1)
    }
    /* Update the mask */
    for(i=MAX(0,x-1);i<MIN(x+2,I);i++)
      for(j=MAX(0,y-1);j<MIN(y+2,J);j++)
    M[i][j]=1;
    /* draw the maze as masked */
    for(i=0;i<I;i++)
      for(j=0;j<J;j++)
    mvaddch(i,j,M[i][j]?m[i][j]:'?');
    /* draw the player figure */
    mvaddch(x,y,'@');
    refresh(); /* Refresh the display */
  } while((m[x][y]!='#')&&(c=getch())!='q');
  if(m[x][y]=='#')mvprintw(I,0,"Finished in %d steps!",s),getch();
  endwin();
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.