c++之简单的推箱子游戏

来源:互联网 发布:gif屏幕录像软件 编辑:程序博客网 时间:2024/05/29 21:36

c++推箱子小游戏(linux也可以运行)

C++一直都是游戏开发的主流语言,特别是游戏引擎的开发。学了半年C++,还是很懵逼,网上找了一些C++推箱子的小游戏,涉及到的知识面太广,从容器到BFS等等算法,尤其是推多个箱子的时候。本人水平有限,只做到了固定地图,并且只有一个箱子可以推。能基本的实现后退,重新开始,上下关卡切换的功能。因为大部分游戏都是在Windows C++平台下编写运行的,很少有linux下也可以运行的推箱子游戏,(可能是我写的太low)代码有点乱,用的思想还是C语言的思想,仅供新手参考。因为第一次发博客,写的不好,欢迎各位批评指正!

//Sokoban.hclass Sokoban{private:    enum {L = 21,H = 10};    int Pex,Pey,OrgPex,OrgPey,OldPex,OldPey;//人的实时位置坐标,上一步人的坐标,人的初始位置坐标    int Boxx,Boxy,OrgBoxx,OrgBoxy,OldBoxx,OldBoxy;//箱子的实时位置,上一步箱子的初始位置坐标,箱子的初始位置坐标    int Tx,Ty;  //目标位置的坐标    int Succeed;    //判断成功的标志位    int dx[4],dy[4];//方向数组    int dir;public:    Sokoban();//构造函数    ~Sokoban();//析构函数    void Initial();//地图初始化函数    void Show();//地图刷新函数    void Button();//按键判断函数    void Move();//箱子移动函数    bool Check(int x,int y);//验证越界函数    void Rest();//重新开始};
//Sokoban.cpp#include"Sokoban.h"int level = 1;//游戏关卡char map[10][22]={"0"};//用来时时更新地图char oldmap[10][22]={"0"};//前一步的地图char orgmap[10][22]={"0"};//最初的地图void OldMap(){    int i = 0,j = 0;    for(i = 0;i<10;i++)        {            for(j = 0;j<21;j++)                {                        oldmap[i][j] = map[i][j];                }        }}void OrgMap(){        int i = 0,j = 0;        for(i = 0;i<10;i++)        {                for(j = 0;j<21;j++)                {                        orgmap[i][j] = map[i][j];                }        }}void Back(){    int i = 0,j = 0;    for(i = 0;i<10;i++)        {            for(j = 0;j<21;j++)                {                        map[i][j] = oldmap[i][j];        }    }}void Sokoban::Rest(){    int i = 0,j = 0;    for(i = 0;i<10;i++)        {            for(j = 0;j<21;j++)                {                        map[i][j] = orgmap[i][j];                }    }    Pex = OrgPex;//最初的地图恢复    Pey = OrgPey;    Boxx = OrgBoxx;    Boxy = OrgBoxy;             }Sokoban::Sokoban(){    dir = -1;    Succeed = 0;    //0~3分别代表上右下左    dx[0] = -1;  dx[1] = 0;  dx[2] = 1;  dx[3] = 0;        dy[0] = 0;   dy[1] = 1;  dy[2] = 0;  dy[3] = -1;  }Sokoban::~Sokoban(){}void Sokoban::Initial(){char   a[10][22]={//123456789012345678901    /*1*/      "#####################",    /*2*/      "#X #         #   #  #",     /*3*/      "## # ######  O      #",    /*4*/      "## # #       #####  #",    /*5*/      "## # # ##### ###### #",    /*6*/      "##   # #         T  #",    /*7*/      "#### # # ########   #",    /*8*/      "##   # #      #     #",    /*9*/      "##       #   #      #",     /*10*/     "#####################"        };char   b[10][22]={//123456789012345678901    /*1*/      "#####################",    /*2*/      "#X #                #",     /*3*/      "## # ############## #",    /*4*/      "#  # #  # #    # #  #",    /*5*/      "#  #        ##  #  ##",    /*6*/      "#  #  # #           #",    /*7*/      "# ## # #  ####### O #",    /*8*/      "# T   #   #    #    #",    /*9*/      "##      #    #      #",     /*10*/     "#####################"        };char   c[10][22]={//123456789012345678901    /*1*/      "#####################",    /*2*/      "#  #          #  #  #",     /*3*/      "## # # #####        #",    /*4*/      "#  # #   O   ## # # #",    /*5*/      "## # #######  ## #  #",    /*6*/      "#         X         #",    /*7*/      "#### ## ## ## ##  ###",    /*8*/      "##     #  #  #  #   #",    /*9*/      "##T                 #",     /*10*/     "#####################"        };char   d[10][22]={//123456789012345678901    /*1*/      "X#   ################",    /*2*/      " # #             #  #",     /*3*/      " #  # # ###### #    #",    /*4*/      " # # #       ## # # #",    /*5*/      " # # #######  ## #  #",    /*6*/      " #                  #",    /*7*/      " # # ## ##### ##  # #",    /*8*/      " # # #      #  # O# #",    /*9*/      " #T#                #",     /*10*/     "   ##################"        };char   e[10][22]={//123456789012345678901    /*1*/      "#####################",    /*2*/      "     #        #  #  #",     /*3*/      "        #####       #",    /*4*/      "   # # #    ##  # # #",    /*5*/      " # ### ## ##  ## #  #",    /*6*/      "     #              #",    /*7*/      " #####  #  ## ##  ###",    /*8*/      " # #   #  #  #  # O #",    /*9*/      "T#                  #",     /*10*/     "X####################"        };/********************地图初始化**************/    char (*pc)[22] = a;    switch(level)    {        case 0: break;        case 1: pc = a;break;        case 2: pc = b;break;        case 3: pc = c;break;        case 4: pc = d;break;        case 5: pc = e;break;    }/**********************人,箱子,目标位置的初始化****************/    int i = 0,j = 0;        for(;i<10;i++)                {                        for(j = 0;j<21;j++)                        {                                map[i][j]  = pc[i][j];                            if(map[i][j] == 'X')                {                    OrgPex = Pex = i;                    OrgPey = Pey = j;                }                else if(map[i][j] == 'O')                {                    OrgBoxx = Boxx = i;                    OrgBoxy = Boxy = j;                }                else if(map[i][j] == 'T')                {                    Tx = i;                    Ty = j;                }            }                }    OrgMap();//最初的地图    Sokoban::Show();}void Sokoban::Show(){    int i = 0,j = 0;    int key = 0;    while(true)    {        usleep(500000);//刷新        Sokoban::Button();        Sokoban::Move();        system("clear");        //打印地图        for(i = 0;i<10;i++)                {                    for(j = 0;j<21;j++)                        {                                printf("%c",map[i][j]);                        }                        cout<<endl;                 }    //画面        cout<<endl;        cout << " _________________________________" << endl;          cout << "|     C++语言推箱子游戏  (共5关)    |" << endl;          cout << "|    游戏规则:     当前关卡: "<<level<<"   |" << endl;          cout << "|     X:人        O:箱子          |" << endl;          cout << "|    #:障碍物    T:目的地          |" << endl;          cout << "|    操作说明:    Q:退出           | " << endl;        cout << "|     W:上         S:下           |"<<endl;        cout << "|     D:右         A:左           |"<<endl;        cout << "|     R:重新开始   B:后退         |"<<endl;        cout << "|     U:上张地图   N:下张地图      |"<<endl;        cout << "|————————————————————————————————|" << endl;          cout << "|    友请提示:                    |" << endl;          cout << "|    每次移动过后只能后退一次!      |" << endl;          cout << "|    人将箱子推到目的地即过关!      |" << endl;          cout << "|   输入按键后按一次回车才能生效!   |" << endl;          cout << "|————————————————————————————————|" << endl;          //箱子成功到达目的地        if(Succeed)        {               if(level == 5)            {                cout<<"太厉害了!!!你差点就和游戏开发者一样聪明了"<<endl;                   break;            }            else if(level == 0)            {                sleep(1);                break;            }            else            {                cout<<"       恭喜你啊,智商可以啊,有本是来通关阿!"<<endl;                cout<<"输入Q回车退出游戏,输入任意键回车等待2秒即可开启下一关卡"<<endl;                sleep(1);                if(kbhit() != 0)                {                    while(kbhit() != 0)                    key = getchar();                    if(key == 113)//按q                    break;                    else                    {                        usleep(500000);                        Succeed = 0;                         level++;//等级+1,地图就会更新                        Sokoban::Initial();                    }                }            }        }    }}void Sokoban::Button(){     int key = 0;      if(kbhit() != 0) //检查当前是否有键盘输入,若有则返回一个非0值,否则返回0       {           while(kbhit() != 0)  //可能存在多个按键,要全部取完,以最后一个为主              key = getchar(); //将按键从控制台中取出并保存到key中          switch(key)          {                //上              case 119:  dir = 0;                      break;              //右              case 100:  dir = 1;                           break;                      //下              case 115:  dir = 2;                       break;              //左              case 97:  dir = 3;                       break;             //后退             case 98: {                    Back();                    Pex = OldPex;                    Pey = OldPey;                    Boxx = OldBoxx;                    Boxy = OldBoxy;                break;                }            //重新开始            case 114: {                    Rest();                break;                }            //切换到下张图            case 110:{                    level++;                     if(level == 6)                    level = 1;                    Sokoban::Initial();                break;                }            //切换到上张图            case 117:{                    level--;                     if(level == 0)                    level = 5;                    Sokoban::Initial();                break;                }            //退出            case 113:                {                    level = 0;                    Succeed = 1;                    break;                              }        }      }   }//人推箱子移动函数void Sokoban::Move(){    int x,y;    //有按键的时候    if(dir != -1)    {        OldPex = Pex;        OldPey = Pey;        OldBoxx = Boxx;        OldBoxy = Boxy;        //人所推向的坐标位置         x = Pex + dx[dir];         y = Pey + dy[dir];        //1.人所推位置为空,就走向该位置,并且人初始位置不在目标位置上        if(Check(x,y) && map[x][y] == ' ' && (Pex != Tx || Pey != Ty))        {               OldMap();            map[Pex][Pey] = ' ';            map[x][y] = 'X';            Pex = x;            Pey = y;            dir = -1;        }        else    //2.人所推的位置是箱子,就将箱子移向人走的方向这点,并且初始位置不在目标位置上        if(Check(x,y) && map[x][y] == 'O' && Check( x+dx[dir],y+dy[dir] ) && map[ x+dx[dir] ][ y+dy[dir] ] == ' ' && (Pex != Tx || Pey != Ty))        {            OldMap();            map[Pex][Pey] = ' ';    //人的位置改变            Pex = x;            Pey = y;            map[Boxx][Boxy] = 'X';  //箱子位置改变,且人移动到箱子的位置            map[x+dx[dir]][y+dy[dir]] = 'O';//箱子移动的位置            Boxx = x + dx[dir];                 Boxy = y + dy[dir];            dir = -1;        }        else    //3.人将箱子推向的方向刚好是目的地        if(Check(x,y) && map[x][y] == 'O' && Check( x+dx[dir],y+dy[dir] ) && map[ x+dx[dir] ][ y+dy[dir] ] == 'T')         {               OldMap();            map[Pex][Pey] = ' ';    //人的移动前位置改变                        Pex = x;                        Pey = y;                        map[Boxx][Boxy] = 'X';  //箱子位置改变,且人移动到箱子的位置                        map[x+dx[dir]][y+dy[dir]] = 'O';//箱子移动的位置                        Boxx = x + dx[dir];                        Boxy = y + dy[dir];            dir = -1;            Succeed = 1;        }else   //4.人走到目标位置        if(Check(x,y) && map[x][y] == 'T')         {            OldMap();            map[Pex][Pey] = ' ';            map[x][y] = 'X';            Pex = x;            Pey = y;            dir = -1;        }else   //5.人离开目标位置且推不到箱子        if(Pex == Tx && Pey == Ty && Check(x,y) && map[x][y] == ' ')        {            OldMap();            map[Tx][Ty] = 'T';//人的位置变成目标地址             map[x][y] = 'X';    //人移动后的位置            Pex = x;            Pey = y;            dir = -1;        }        else   //6.人离开目标位置且能推到箱子        if(Pex == Tx && Pey == Ty && Check(x,y) && map[x][y] == 'O' && Check( x+dx[dir],y+dy[dir] ) && map[ x+dx[dir] ][ y+dy[dir] ] == ' ')        {            OldMap();            map[Pex][Pey] = 'T';//人的位置变成目标地址            map[x][y] = 'X';    //人的移动后的位置            Pex = x;            Pey = y;                        map[Boxx][Boxy] = 'X';  //箱子位置改变,且人移动到箱子的位置                        map[x+dx[dir]][y+dy[dir]] = 'O';//箱子移动的位置                        Boxx = x + dx[dir];                        Boxy = y + dy[dir];            dir = -1;        }    }}//判断越界情况bool Sokoban::Check(int x,int y){    if(x < 0 || x >= H || y < 0 || y >= L)    return 0;    else    return 1;}
//-----------------------------------------------------//kbhit.h//按键的程序#ifndef KEY_H#define KEY_H#include <termios.h>#include <iostream>#include"kbhit.h"#include <stdio.h>#include <termios.h>#include <unistd.h>#include <sys/types.h>#include <sys/time.h>int  kbhit(void);#endif
//---------------------------------------------//kbhit.cpp#include"kbhit.h"int kbhit (void){  struct timeval tv;  fd_set rdfs;  tv.tv_sec = 0;  tv.tv_usec = 0;  FD_ZERO(&rdfs);  FD_SET (STDIN_FILENO, &rdfs);  select(STDIN_FILENO+1, &rdfs, NULL, NULL, &tv);  return FD_ISSET(STDIN_FILENO, &rdfs);}
//---------------------------------------------//main.cpp#include"Sokoban.h"using namespace std;int main(){    Sokoban s;    s.Initial();    return 0;}

//运行方式

g++ -o main Sokoban.cpp hbit.cpp main.cpp

./main

游戏开始的界面
游戏开始的界面

游戏结束的界面
游戏结束画面

0 0