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


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.