为迷宫游戏构建引擎


9

这是“ 打印迷宫问题” 的后续内容。如果您喜欢这个问题,请添加更多迷宫生成算法;)。

对于此任务,您将必须为一个必须在迷宫中找到宝藏并离开地牢的玩家实现游戏引擎。

引擎首先从标准输入中.读取迷宫,然后在一行中包含(点)命令行中作为参数指定的文件。接下来,将玩家@放置在地图上的随机位置。然后引擎开始通过标准io与播放器进行交互:

引擎到播放器的命令:

  • continue:游戏未完成。印刷环境,后跟.。玩家由@角色代表。不可观察的细胞用表示?
  • finished:游戏结束。打印步骤数,游戏停止。

播放器到引擎的命令:

  • north:将玩家上移。
  • south:将玩家下移。
  • west:向左移动播放器。
  • east:向右移动播放器。

来自播放器的任何无效命令(例如撞墙)都将被忽略,但仍会计数。您可以自由定义自己喜欢的环境。

  • 最短的代码。
  • 复杂环境的(例如打印大区域并替换看不见的单元格?)。
  • 没有不遵守io格式的代码没有意义

范例

在此示例中,周围环境定义为3x3单元,播放器位于中间。

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

@Alexandru:我们用什么来产生迷宫?我们可以使用其他人的迷宫算法吗?还是我们必须完成您的第一个任务?
snmcdonald 2011年

@snmcdonald:固定错字。使用别人的迷宫。请记住,引擎从标准输入读取迷宫。
亚历山德鲁

这个博客上有很多关于使用各种混合算法生成迷宫的优秀文章 weblog.jamisbuck.org 检查成长中的树算法,特别是 weblog.jamisbuck.org/2011/1/27/…–
Dve

我对迷宫和用户交互如何来自标准输入感到困惑。用户是否应该打入迷宫然后加以解决?Kinda击败了只展示迷宫的一部分的目的……
Keith Randall

您可以在其顶部构建一个应用程序(此任务留给另一个问题),以将迷宫输入与命令输入分开。
亚历山德鲁

Answers:


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个字符,并且迷宫文件名在命令行中传递,并且参数的数量足够少,以至于c的初始值不是移动命令。

  • 与标准的不同之处在于,它采用单字符方向命令作为建议的小写首字母。

  • 是否将未知区域显示为“?”。

注释更易读:

#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();
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.