C语言实现简单的推箱子小游戏

本文实例为大家分享了C语言实现简单推箱子小游戏的具体代码,供大家参考,具体内容如下

此推箱子游戏可以实现人物移动,箱子移动,人物不出框,自义定文件关卡,重新开始以及回退复位等功能的实现,由于系统或版本问题,关卡和人物及物体未做美化处理,希望美化的可自行美化。

1.所用到的宏

#include <stdio.h> #include <stdlib.h> #include <getopt.h> #define MAX_ROWS 16 #define MAX_CLOS 16 #define MAX_LEVEL 5 #define FILE_NAME_LEN 40 #define ROAD 0  //路  #define WALL 1  //墙  #define BOX  2  //箱子  #define TERM 3  //门  #define MOUS 4  //老鼠  #define IGN  224 //无效的键值  #define LEFT  75 //上下左右相对应的键值  #define RIGHT 77 #define UP    72 #define DOWN  80 #define MINT MOUS+TERM   //老鼠在门上 #define BINT BOX+TERM    //箱子在门上  #define QUIT 'q'//退出  #define RESET 'r'//重新开始  #define BACK 'b'//回退  #define NM  0 #define MM  1 #define BM  2 #define MAX_BACK_STEP 10//回退最多的步数 

2.变量声明

struct Act{     int dir;     int sta;     }; struct Act acts[MAX_BACK_STEP] = {}; int stepsize = 0;//用于记录回退的数量 int newindex = -1;//用于记录产生一个新的动作  int board[MAX_ROWS][MAX_CLOS] = {}; int row, col; int mx = 0,my = 0;//记录老鼠位置  int bcnt = 0;//记录箱子

3.地图文件开启

void load(int level){//将地图文件存放在Dev-CC文件夹下      char fileName[FILE_NAME_LEN] = "";     sprintf(fileName,"%d.txt",level);     FILE *fp = fopen(fileName,"r");//只读形式打开文件      if(fp == NULL){         printf("%s文件打开失败\n",fileName);         exit(-1);//失败退出      }      fscanf(fp,"%d %d",&row,&col);     int i,j;     bcnt = 0;     for(i=0;i<row;i++){         for(j=0;j<col;j++){             fscanf(fp,"%d",&board[i][j]);//读取地图行和列              if(board[i][j] == MOUS || board[i][j] == MINT){                 mx = i;                 my = j;             }              else if(board[i][j] == BOX || board[i][j] == BINT){                 ++bcnt;             }         }     }     fclose(fp);     stepsize = 0;     newindex = -1;//返回值初始化  } 

4.地图显示及记录模块

//显示地图,记录箱子到达终点  int show(void){     int i,j;     int bs = 0;     for(i=0;i<row;i++){         for(j=0;j<col;j++){             switch(board[i][j]){//画出地图                  case ROAD:                     printf(" ");                     break;                 case WALL:                     printf("#");                     break;                 case BINT:                     ++bs;                 case BOX:                     printf("@");                     break;                 case TERM:                     printf("O");                     break;                  case MOUS:                 case MINT:                     printf("&");                     break;                              }         }         printf("\n");     }     return bs; }

5.物体的移动和关卡的延续

int move(int stepx,int stepy){//老鼠和箱子的移动      int nx = mx + stepx;     int ny = my + stepy;     if (board[nx][ny] == ROAD || board[nx][ny] == TERM){         board[mx][my] -= MOUS;         board[nx][ny] += MOUS;         mx = nx;         my = ny;         return MM;     }     else if(board[nx][ny] == BOX || board[nx][ny] == BINT){//推着箱子走          int nnx = nx + stepx;         int nny = ny + stepy;//箱子的坐标          if(board[nnx][nny] == ROAD || board[nnx][nny] == TERM){             board[nnx][nny] += BOX;//箱子到达新的地方              board[nx][ny] -= BOX;//箱子从原来的地方离开             board[mx][my] -= MOUS;//老鼠离开              board[nx][ny] += MOUS;//老鼠到达的新的点              mx = nx;             my = ny;             return BM;         }     }     return NM; }

6.回退功能的实现(最难部分)

void moveback(int stepx,int stepy){//回退      int nx = mx+stepx;     int ny = my+stepy;     board[mx][my] -= MOUS;     board[nx][ny] += MOUS;     if(acts[newindex].sta == BM){         int bx = mx-stepx;         int by = my-stepy;         board[bx][by] -=BOX;         board[mx][my] +=BOX;     }     mx = nx;     my = ny; } void back(void){     if(stepsize >0){         switch(acts[newindex].dir){             case UP:                 moveback(+1,0);                 break;             case DOWN:                 moveback(-1,0);                 break;             case LEFT:                 moveback(0,+1);                 break;             case RIGHT:                 moveback(0,-1);                 break;          }         --stepsize;         --newindex;         if(newindex == -1){             newindex = MAX_BACK_STEP -1;         }     } }

7.游戏运行主要部分

void play(int level){     while(1){         system("cls");//清屏          int ret = show();         if(ret == bcnt){//箱子和被推到终点的箱子数一样时              printf("恭喜过关,按任意键进入下一关!!");             getch();             return;          }         int key = getch();         if(key == IGN){             key = getch();         }         if(key == QUIT){//退出              printf("GAME OVER\n");             exit(0);         }          else if(key == RESET){//重新开始              load(level);//重新加载地图          }         else if(key == BACK){//回退功能              back();          }         ret = NM;         switch(key){             case UP:                 ret = move(-1,0);                 break;             case DOWN:                 ret = move(+1,0);                 break;             case LEFT:                 ret = move(0,-1);                 break;             case RIGHT:                 ret = move(0,+1);                 break;                         }         if(ret == MM || ret == BM){//保存有效动作 用于回退               struct Act act = {key,ret}; //记录动作             ++newindex;             if(newindex>= MAX_BACK_STEP){                 newindex = 0;             }             acts[newindex] = act;             if(stepsize<MAX_BACK_STEP){                 ++stepsize;//可以退回的步数+1              }         }     } } //运行函数  void run(void){     int level;     for(level=1;level<=MAX_LEVEL;level++){         load(level);         play(level);     } } //主函数  int main(int argc, char *argv[]) {     run();     return 0; }

8.参考关卡文件(可使用windos记事本以.txt 形式保存,第一列均为空格)

具体解释存在于代码中。如有不足,请指正!

推荐阅读