当前位置 博文首页 > 灰小猿的博客:程序员带你回味童年,一起用C语言做一个“推箱子

    灰小猿的博客:程序员带你回味童年,一起用C语言做一个“推箱子

    作者:[db:作者] 时间:2021-07-03 13:09

    这篇文章是用C语言做了一个推箱子小游戏,实现起来比较简单,和大家一起回味一下童年捧着按键机玩推箱子的日子!文末附带万字源码!

    目录

    一、写在前面

    二、设计思路

    1.主界面函数介绍

    2.选择界面函数

    3.选择函数

    4.游戏步骤重播函数

    5.键盘键位设置函数

    6.游戏界面函数

    7.向左函数

    8.向右函数

    9.向下函数

    10.向上函数

    11.通关函数

    12.最佳记录函数

    13.入队列函数

    14.出队列函数

    三、最后总结

    四、完整源码


    Hello,你好呀,我是灰小猿!一个超会写bug的程序猿!

    还记得我们曾经的那个推箱子吗,记得小时候家里只有按键的诺基亚的时候,推箱子、贪吃蛇都是我天天最经常玩的游戏,然后最近正好有小伙伴问我有没有做过相关的开发,所以今天在这里跟大家一个用C语言实现的简单推箱子的小游戏,带着大家一起回味一下童年呀!【点赞收藏,上车坐好!】

    一、写在前面

    推箱子游戏程序的设计为分别设置各类型函数类,设定推箱子房子布局的数据结构二维数组,以及记录最短步骤数目以及最好成绩的二维数组,通过函数对房子进行布局,定义数据结构队列类,并设置公有成员函数和私有成员函数。

    与此同时,我运用C++中的派生类相关知识设定相同类名以及不同类名的对象,用于构造推箱子游戏的分布函数,设定数据结构出队和入队函数,同时设计以箱子为对象,依据于人的横纵坐标位置的函数,设计基于游戏数据界面的,开始界面通关提示、游戏时选项提示、玩游戏时界面显示地图左右上下方向通关提示以及排行榜等。

    同时,根据游戏要求设定输出游戏主界面和游戏关卡选择界面,用于我们的操作,构造将游戏步骤进行重新播放的函数,根据以上以及各类型详细函数设定主函数并进行操作运行游戏,以此来达到使游戏平稳运行的要求。除上述内容之外,在制作游戏时,我还运用了多元分组的构造模式,使得程序内容简单易懂,任何有程序基础的人都可以进行交流学习。接下来我跟大家分享一下主要的模块设计,最后附上完整源码供大家参考!小伙伴们别忘了三连支持,收藏学习呀!

    二、设计思路

    在程序中我利用类与对象完成了对游戏地图的设计,以及对于关卡的选择等众多功能。并且利用数据结构中的理念,实现了对人与箱子的定位和时间步数等功能的实现。总体来说,该程序涵盖了我们所学习的相关知识,虽然游戏有点简单,但是其中内容却涉猎甚广,

    推箱子游戏的设计目的,在于合理有效运用数据结构栈与队列,以及C++中的类与对象以及派生类的相关知识,将游戏中的各个环节拆分开来,运用派生类将各个环节串联起来,达到实现程序稳定运行的目的。以下是总体设计图:

    1.主界面函数介绍

    在box下的begin派生类中,我们的主要功能是输出游戏界面,在该函数中,我们对游戏内部功能进行了详细介绍,其中包括游戏玩法和操作指令,与此同时,对游戏主界面进行了详细优化,在该函数中,在游戏功能的介绍上,我们分别使用星星,圆圈和特殊符号代表箱子,目标位置和推箱子的小人物,我们调用进行观察,选择的函数来完成游戏,玩家对游戏关卡的选择,并且在操作指令上对进行撤销选择和退出游戏进行了详细介绍,方便玩家更好的游戏体验,

    2.选择界面函数

    在游戏选择界面中,我们采用双五角星的界面图形动画,在中间设定关卡选项,选择选项中有1到4个关卡可供选择,在用户进行关卡选择以后,可将选择关卡的序号进行返回到函数之中,函数对玩家选择的序号进行识别,一次对1到4个关卡进行选择判断,然后在程序中跳转到相应的函数界面,供玩家进行游戏,倘若玩家输入的序号不在1到4之间,则系统会自动提示输入错误,请重新输入的字样。

    3.选择函数

    在派生类选择函数中,我们设定了重播,主界面,最好记录,退出四个选项,当玩家游戏无法通关时,可按键盘上的c键来跳转出选择界面进行玩家的选择,和选择关卡的设定一样,我们在玩家反馈过来的1到4四个序号进行判断,然后依次作出重播放,返回主界面,跳转出最好记录,退出系统四个功能。

    4.游戏步骤重播函数

    在游戏玩一下通关以后,我们会设定一个游戏步骤重播函数,在该函数执行以后,玩家可以观看由程序对玩家步骤进行记录而设定好的游戏步骤重播,在该函数中,我们主要是依据玩家进行上下左右方向键操作,对其方向的使用进行存储到数组之中,当玩家选择进行游戏步骤重播时,我们可将该二维数组中的数据释放出来,达到将游戏步骤进行重新播放的效果。

    5.键盘键位设置函数

    在游戏开始以后,有玩家可通过上下左右方向键来进行游戏中小人的控制操作,而游戏中小人控制操作的方向键,我们所依据的是Ascii码键盘键位,其中左键为75号,右键为77号上键为72号,下键为80号,在开始游戏以后,玩家对按键进行操作,与此同时,我们在内部函数中会对75,77,72,84个数进行记忆,当返回值为四个数中的其中之一时,我们会将该记录存入函数之中,并且在游戏步骤上加1,其中我们还设定键盘上的c键为26,当选择c键时可进行重新选择操作,在该重新选择以后,我们设置返回主界面和退出游戏两个选项,可供玩家进行选择。

    6.游戏界面函数

    在游戏界面函数中,我们设定了游戏的各种形状来代表我们游戏内部的不同内容,分别以‘■’代表墙体,‘○’代表目标位置,‘★’代表箱子,‘♀’代表人,和‘㊣’代表箱子在目标位置上的效果展示,与此同时,在界面的最下边,我们增加有撤销(Ctrl+z),选择(c)和游戏步数记录选项,可实时记录玩家进行的游戏步骤,效果图如下:


    7.向左函数

    在游戏按键中的向左函数中,我们有进行多项判断,我们所依据的是小人向左位置的地址进行返回值,如果我们检测到该数组内部的值为零时进行判断,我们将记录小人左侧函数的数组赋值给4,然后进行判断,同时,如果该数组上元数等于2,我们要使人员移动到目标位置上,同时恢复目标位置的函数,使其恢复到原来位置,同时对该位置进行标记,记录人员经过该位置,方便我们进行重播函数的操作,

    如果说我们检测到该函数内的值为零,或者是3的话,我们可以执行将箱子推到空白位置上的函数操作,如果该函数为5或者为1的话,我们要执行的是将箱子从目标位置上推出的函数操作,如果该函数值为3且为2,我们要执行的是将箱子推到目标位置上的函数操作,且人在目标位置上用来抵消仍不动的情况。

    8.向右函数

    我们在执行向右函数时,所依据的原理和向左函数类似,我们对右键的地址来进行判断且返回值,如果说函数值等于零,我们则进行以下操作,如果说返回值等于2,我们要将人员移到目标位置之上,同时恢复目标位置及原来的状态标志,该位置记录仍在该位置上的地址,方便我们进行重播操作,否则如果说该函数值为3且为0的话,我们将箱子推到空白位置上,如果按函数值为5或者不等于1的话,我们要将箱子从目标位置上推出,移动到下一个目标位置,且还是目标位置,如果该函数值为3且为2的话,要将箱子推到目标位置上。

    9.向下函数

    在向下函数中,我们对向下按键的地址进行返回,并且读取判断,如果说数组记录中为2,要将人要移到目标位置上,同时恢复目标位置的原来状态标志,该位置记录仍在目标位置上的地址,方便我们进行重播操作,如果该数组的值为3且等于0,将箱子推到空白位置之上,将箱子从标位置上推出,如果下一个位置还是目标位置,我们将该值为5或4,如果下一个位置是空白,之后我们将该数组值赋为3且为4,如果该数组的值为3且为2,我们要将箱子推到目标位置上,并且如果说该数组值为5的话,将箱子推到目标位置之上,仍在目标位置上,否则如果人不在目标位置之上的话,我们将该函数值赋值为0,同时抵消人不动的情况。

    10.向上函数

    在执行向上函数时,我们对应函数值返回的地址值进行判断,如果该数组值为0,则我们将该数组值赋值为4,否则如果说该函数值为2,我们要说明人在目标位置之上,同时恢复目标位置的原来状态标志,该位置记录人在目标位置上的地址,方便进行重播操作,如果该数组位置为3且为0,我们将箱子推到空白位置之上,否则如果数组值为5或不等于1,要将箱子从目标位置上推出,如果下一个位置还是目标位置,我们则将输出值赋值为5,将另一个数组赋值为4,如果该数组赋值为3,且另一个数组数值为2,要将箱子推到目标位置上,并且将该值赋值为5,将箱子在目标位置上,仍在目标位置之上,若人在目标位直之上,则抵调整波动的情况。

    11.通关函数

    在玩家进行通关以后,我们系统会自动识别,并且返回一个通关界面,该界面我们会对玩家进行询问的操作,该操作分为四步,继续,观看通关视频过程,查看最好记录,退出界面,返回主界面,当玩家进行1到4的选择以后,我们会返回相应的操作,并且可以在按任意键回到主页面。

    12.最佳记录函数

    在最佳记录函数中,我们设定一个值来记录游戏玩家的步数,每当游戏玩家对按键进行操作一次,则该函数定义的变量则加一次,当我们读取到该玩家通关以后,将应该数据进行保存,当我们检测到有最好记录时,即该步数为最小值时,确定为最佳记录。

    13.入队列函数

    在入队列函数中,主要运用数据结构的队列知识,设置入队列函数,并定义指针变量指向头结点,相关数值在入队列以后,会自动的将数值赋值到队头位置,并且循环使searchp节点不为空,然后按照次序,将数值依次从队头向对尾进行赋值运算,

    14.出队列函数

    在出队列操作中,主要依据队列相关规则,设置指针变量,将队头元素赋值给指针,同时在进行if语句的判断,将for循环之中如i的数值小于正方形的边长,则使用队头接收searchp的数值,与此同时,让count的数值不断的进行减减操作,

    三、最后总结

    截止到这里,推箱子游戏的基本功能就完成了,最后把它总结一下,我们设计的推箱子小游戏,合理的使用了数据结构中队列的知识点,在使用这些知识点的时候,我们也对游戏过程进行了详细的优化,通过这次推箱子游戏的设计,大家应该能学到队列在实际应用中的操作,同时这也很好地让大家对数据结构的知识点进行了一个巩固和复习,也从中学到了游戏界面,布局的构造思想和构造方法,以及键盘与代码之间的有效联系,所以这个设计能够学习到的东西还是很多的了。

    我把完整源码放在了最后,小伙伴们可以自己修改地图界面、设定关卡。

    ?

    四、完整源码

    //推箱子小游戏
    #include<iostream>
    #include<windows.h>
    #include<stdlib.h>
    #include<conio.h>
    #include<fstream>
    #include<iomanip>
    using namespace std;
    const int roomsize = 9;//设计房子内部为正方形,边长为9
    int map[roomsize + 2][roomsize + 2]; //推箱子房子布局的数据结构:二维数组
    int followmap[1000];
    int data;//记录最短步骤数目
    int times = 0;
    int array[2] = { 100, 100 }; //记录最好成绩
    char String[30] = "开始比赛...........";
    //以下为前几轮游戏房子中细节布局的数据结构:二维数组的实际内容
    int map1[roomsize + 2][roomsize + 2] =
    {   //0,1,2,3,4,5,6,7,8,9,10
    	{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, //0
    	{ -1, 0, 0, 0, 0, 1, 1, 1, 1, 1, -1 },          //1
    	{ -1, 0, 0, 0, 0, 1, 2, 0, 0, 1, -1 },          //2
    	{ -1, 1, 1, 1, 0, 1, 0, 3, 0, 1, -1 },          //3
    	{ -1, 1, 2, 1, 0, 1, 0, 0, 0, 1, -1 },          //4
    	{ -1, 1, 2, 1, 0, 1, 0, 3, 0, 1, -1 },          //5
    	{ -1, 1, 2, 1, 1, 1, 0, 3, 0, 1, -1 },          //6
    	{ -1, 1, 0, 0, 0, 0, 3, 4, 0, 1, -1 },          //7
    	{ -1, 1, 0, 0, 1, 0, 0, 0, 0, 1, -1 },          //8
    	{ -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1 },          //9
    	{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } //10
    };
    int map2[roomsize + 2][roomsize + 2] =
    {   //0,1,2,3,4,5,6,7,8,9,10
    	{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },//0
    	{ -1, 0, 1, 1, 1, 1, 1, 0, 0, -1, -1 },        //1
    	{ -1, 0, 1, 4, 0, 0, 1, 1, 0, -1, -1 },        //2
    	{ -1, 0, 1, 0, 3, 0, 0, 1, 0, -1, -1 },        //3
    	{ -1, 1, 1, 1, 0, 1, 0, 1, 1, -1, -1 },        //4
    	{ -1, 1, 2, 1, 0, 1, 0, 0, 1, -1, -1 },        //5
    	{ -1, 1, 2, 3, 0, 0, 1, 0, 1, -1, -1 },        //6
    	{ -1, 1, 2, 0, 0, 0, 3, 0, 1, -1, -1 },        //7
    	{ -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1 },        //8
    	{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },//9
    	{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } //10
    };
    int map3[roomsize + 2][roomsize + 2] =
    {   //0,1,2,3,4,5,6,7,8,9,10
    	{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },//0
    	{ -1, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1 },        //1
    	{ -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1 },        //2
    	{ -1, 1, 1, 0, 0, 0, 0, 1, 1, -1, -1 },        //36
    	{ -1, 1, 0, 3, 0, 3, 3, 0, 1, -1, -1 },        //4
    	{ -1, 1, 2, 2, 2, 2, 2, 2, 1, -1, -1 },        //5
    	{ -1, 1, 0, 3, 3, 0, 3, 0, 1, -1, -1 },        //6
    	{ -1, 1, 1, 1, 0, 1, 1, 1, 1, -1, -1 },        //7
    	{ -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1 },        //8
    	{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },//9
    	{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } //10
    };
    int map4[roomsize + 2][roomsize + 2] =
    {   //0,1,2,3,4,5,6,7,8,9,10
    	{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },//0
    	{ -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1 },        //1
    	{ -1, 1, 0, 0, 0, 0, 0, 0, 1, -1, -1 },        //2
    	{ -1, 1, 0, 3, 0, 1, 1, 1, 1, -1, -1 },        //3
    	{ -1, 1, 0, 0, 0, 2, 2, 1, 1, -1, -1 },        //4
    	{ -1, 1, 0, 0, 1, 2, 1, 1, 1, -1, -1 },        //5
    	{ -1, 1, 0, 3, 0, 4, 3, 0, 1, -1, -1 },        //6
    	{ -1, 1, 0, 0, 0, 0, 0, 0, 1, -1, -1 },        //7
    	{ -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1 },        //8
    	{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },//9
    	{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } //10
    };
    
    
    
    class node
    {
    public:
    	int data[1000];
    	int positionL;//位置左
    	int positionH;//位置
    	node *next;
    
    };
    /*
    *队列
    */
    class linkqueue//定义队列类
    {
    private://定义私有数据成员
    	node *front;
    	int count;
    public://定义公有数据成员
    	linkqueue();
    	~linkqueue();
    	void insert(int item[]);//定义公有成员函数
    	void out(int item[]);
    	void clearqueue(void);
    	int getcount();
    };
    linkqueue::linkqueue()//定义相同类名的派生类
    {
    	front = new node;//将定义的变量赋值给队头
    	front->next = NULL;//队头指向空节点
    	count = 0;
    }
    linkqueue::~linkqueue()
    {
    	clearqueue();
    	count = 0;
    }
    
    void linkqueue::out(int item[])//出队列
    {
    	node *searchp;
    	searchp = front->next;//将队头元素赋值给指针
    	for (int i = 0; i<(roomsize + 2)*(roomsize + 2); i++)//使i的值小于正方形滴边长
    		item[i] = searchp->data[i];
    	front->next = searchp->next;//队头接收searchp
    	delete searchp;
    	count--;
    }
    
    void linkqueue::insert(int item[])//进队
    {
    	node *newnodep = new node, *searchp = front; 
    	while (searchp->next != NULL)//循环使searchp节点不为空
    		searchp = searchp->next;
    	for (int i = 0; i<121; i++)
    		newnodep->data[i] = item[i];
    	newnodep->next = searchp->next;
    	searchp->next = newnodep;
    	count++;
    }
    void linkqueue::clearqueue(void)//定义依据于linkequeue的派生类
    {
    
    	if (front->next == NULL)//若头结点为空。则返回
    		return;
    	while (front->next != NULL)//若队头结点不为空,则将头结点赋值给指针
    	{
    		node *searchp;
    		searchp = front->next;
    		front->next = searchp->next;
    		delete searchp;
    	}
    	count = 0;
    }
    int linkqueue::getcount()//定义依据于linkequeue的派生类用来返回count滴值
    {
    	return count;
    }
    /*
    *栈
    */
    class  seqstack//定义类
    {
    public://设定公有成员函数
    	seqstack();
    	~seqstack();
    	void clearseqstack(void);
    	void push(int item[], int &line, int &lie);//括号内为只接收变量滴地址
    	void pop(int item[], int &line, int &lie);
    private:
    	node *top;
    };
    seqstack::seqstack()
    {
    	top = new node;
    	top->next = NULL;
    }
    seqstack::~seqstack()
    {}
    
    void seqstack::push(int item[], int &line, int &lie)//定义以seqtack类滴push(推)的类,用来记录推动箱子的地址和位置
    {
    	node *newnodep, *searchp = top;
    	newnodep = new node;
    	for (int i = 0; i<(roomsize + 2)*(roomsize + 2); i++)
    		newnodep->data[i] = item[i];
    	newnodep->positionH = line;//将地址进行返回
    	newnodep->positionL = lie;//将地址进行返回
    	newnodep->next = searchp->next;
    	searchp->next = newnodep;
    
    }
    
    void seqstack::pop(int item[], int &line, int &lie)
    {
    	node *newnodep, *searchp = top;
    	if (searchp->next != NULL)
    	{
    		newnodep = top->next;
    		for (int i = 0; i<(roomsize + 2)*(roomsize + 2); i++)
    			item[i] = newnodep->data[i];
    		line = newnodep->positionH;
    		lie = newnodep->positionL;
    		top->next = newnodep->next;
    		delete newnodep;
    	}
    }
    void seqstack::clearseqstack(void)
    {
    	if (top->next == NULL)
    		return;
    	while (top->next != NULL)
    	{
    		node *searchp;
    		searchp = top->next;
    		top->next = searchp->next;
    		delete searchp;
    	}
    }
    
    //对象:箱子
    class box//记录人位置滴函数
    {
    	int positionh;//人的位置纵坐标
    	int positionl;//人的位置横坐标
    	int flag;//标志位,记录人在目标位置上
    	int gate;//这个变量是记录关数
    	int count;//这个变量是记录步数
    	seqstack st;
    	linkqueue linkqu;
    public:
    	box();
    	void begin();//开始界面
    	void choose_gate();//选关提示
    	void choose();//游戏时c选项的提示
    	void replay();//重玩
    	void playing();//玩游戏时界面
    	void display();//显示地图
    	void left();//左方向
    	void right();//右方向
    	void down();//下方向
    	void up();//上方向
    	void test_flag();//过关提示
    	void record();//这段函数为排行榜
    	void travers();
    	void returnpush();
    	void returninseart();
    	//void random();//这段函数为随机生成室内布局,暂时没有提供
    };
    
    box::box()
    {
    	positionh = 0;
    	positionl = 0;
    	flag = 0;
    	count = 0;
    	gate = 0;
    }
    void box::begin()
    {
    	system("color 17");
    
    	/*******************************输出游戏主界面***********************************/
    	cout << "   ╭────────────-─────────────────-──╮" << endl <<//1                                                                       "<<endl<<//1
    		"  │                                                                  │" << endl <<//2
    		"  │              ★☆★       推箱子游戏        ★☆★               │" << endl <<//3
    		"  │★☆★★☆★★☆★★☆★★☆★★☆★★☆★★☆★★☆★★☆★★☆★│" << endl <<//4
    		"  │                            游戏介绍                              │" << endl <<//5
    		"  │                                                                  │" << endl <<//6
    		"  │怎么玩这个游戏呢?我来介绍一下:这是小人人(♀)小星星就是箱子啦(★)│" << endl <<//7
    		"  │你要把星星放在这个地方喔(○),等到有了㊣.你就赢咯!快来挑战吧!!   │" << endl <<//8
    		"  │                                                                  │" << endl <<//9
    		"  │                           操作指令                               │" << endl <<//10
    		"  │                                                                  │" << endl <<//11
    		"  │使用方向键控制哦!'Ctrl+z' 用来撤销,'c'用来选择 'Esc'退出游戏!  │" << endl <<//12
    		"  │                                                                  │" << endl <<//13
    		"  │                                                                  │" << endl <<//14
    		"  ╰─────────────────────────────────╯" << endl; //15
    	choose_gate();//选择关数
    	cout << String << endl;
    	Sleep(1000);
    	system("cls");
    	linkqu.clearqueue();
    	st.clearseqstack();
    	playing();
    }
    void box::choose_gate()
    {
    	//system("color 10");
    	int j, k;
    
    		/*******************************输出游戏关卡选择界面***********************************/
    	cout << "              ★               ╭────╮            ★      " << endl
    		<< "             ★★             │ 关卡选择 │          ★★      " << endl
    		<< "            ★  ★            │ 1.first  │         ★  ★        " << endl
    		<< "       ★★★    ★★★       │ 2.scend  │    ★★★    ★★★     " <<endl
    		<< "        ★          ★        │ 3.third  │     ★          ★        " << endl
    		<< "         ★        ★         │ 4.forth  │      ★        ★          " << endl
    		<< "          ★  ★  ★          │★★★★  │       ★  ★  ★            " << endl
    		<< "          ★★  ★★          │  ★★★★│       ★★  ★★         " << endl
    		<< "          ★      ★          ╰─────╯       ★      ★         " << endl<<endl<<endl;
    	cout << "请选择关卡哟:";
    	cin >> gate;
    	do
    	{
    		switch (gate)
    		{
    		case 1:
    			for (j = 0; j<roomsize + 2; j++)//此处 j控制行,k控制列
    			for (k = 0; k<roomsize + 2; k++)
    				map[j][k] = map1[j][k];
    			positionh = 7; positionl = 7;
    			break;
    		case 2:
    			for (j = 0; j<roomsize + 2; j++)
    			for (k = 0; k<roomsize + 2; k++)
    				map[j][k] = map2[j][k];
    			positionh = 2; positionl = 3;
    			break;
    		case 3:
    			for (j = 0; j<roomsize + 2; j++)
    			for (k = 0; k<roomsize + 2; k++)
    				map[j][k] = map3[j][k];
    			positionh =7, positionl = 5;
    			break;
    		case 4:
    			for (j = 0; j<roomsize + 2; j++)
    			for (k = 0; k<roomsize + 2; k++)
    				map[j][k] = map4[j][k];
    			positionh = 6, positionl = 5;
    			break;
    		default:
    			cout << "输入错误啦^_^请重新输入哟@v@!";
    			cin >> gate;
    		}
    	} while (gate>4);
    }
    void box::choose()//选项
    {
    	int choice;
    	cout << " ╭────────╮" << endl
    		<< " │1. 重播         │" << endl
    		<< " │2. 主界面       │" << endl
    		<< " │3. 最好的记录   │" << endl
    		<< " │4. 退出         │" << endl
    		<< " ╰────────╯" << endl;
    	cin >> choice;
    	switch (choice)
    	{
    	case 1:
    		system("cls");
    		replay();
    		break;
    	case 2:
    		system("cls");
    		begin();
    		break;
    	case 3:
    		record();
    		system("cls");
    		playing();
    		break;
    	case 4:
    		exit(0);
    	}
    }
    void box::replay()//将游戏步骤进行重播
    {
    	int j, k;
    	count = 0;
    	flag = 0;
    	st.clearseqstack();
    	linkqu.clearqueue();
    	do
    	{
    		switch (gate)
    		{
    		case 1:
    			for (j = 0; j<roomsize + 2; j++)
    			for (k = 0; k<roomsize + 2; k++)
    				map[j][k] = map1[j][k];
    			positionh = 7; positionl = 7;
    			break;
    		case 2:
    			for (j = 0; j<roomsize + 2; j++)
    			for (k = 0; k<roomsize + 2; k++)
    				map[j][k] = map2[j][k];
    			positionh = 2; positionl = 3;
    			break;
    		case 3:
    			for (j = 0; j<roomsize + 2; j++)
    			for (k = 0; k<roomsize + 2; k++)
    				map[j][k] = map3[j][k];
    			positionh = positionl = 4;
    			break;
    		case 4:
    			for (j = 0; j<roomsize + 2; j++)
    			for (k = 0; k<roomsize + 2; k++)
    				map[j][k] = map4[j][k];
    			positionh = 6, positionl = 5;
    			break;
    		
    		}
    	} while (gate>4);
    	playing();
    }
    void box::playing()//Ascii码键盘键位:左为75 右为77 上为72 下为80
    {
    	int choice, i, l, r, item[1000],j,k;
    	count = 0;
    	cout << "游戏开始";
    	while (1)
    	{
    		display();
    		switch (_getch())
    		{
    		case 72:
    			returninseart();
    			returnpush();
    			up();
    			count++;
    			break;
    		case 80:
    			returninseart();
    			returnpush();
    			down();
    			count++;
    			break;
    		case 75:
    			returninseart();
    			returnpush();
    			left();
    			count++;
    			break;
    		case 77:
    			returninseart();
    			returnpush();
    			right();
    			count++;
    			break;
    		//case 'x':
    		case 26:
    			i = 0;
    			system("cls");
    			st.pop(item, l, r);
    			for (j = 0; j<roomsize + 2; j++)
    			for (k = 0; k<roomsize + 2; k++)
    			{
    				map[j][k] = item[i];
    				i++;
    			}
    			positionl = r; positionh = l;
    			display();
    			break;
    		case 'c':
    		case 'C':
    			choose();
    			break;
    		//case 'q':
    		case 27:
    			cout << " ╭──────────────╮" << endl
    				<< " │请给你选择喔:              │" << endl
    				<< " │   1. 我要返回主界面        │" << endl
    				<< " │   2. 我不玩了退出游戏      │" << endl
    				<< " ╰──────────────╯" << endl;
    			cin >> choice;
    			switch (choice)
    			{
    			case 1:
    				count = 0;
    				Sleep(500);
    				system("cls");
    				begin();
    				break;
    			case 2:
    				exit(0);
    			}
    		default:
    			break;
    		}
    		system("cls");
    	}
    }
    void box::display()
    {
    	cout << endl << endl << endl << endl << endl << endl;
    	for (int i = 1; i <= roomsize; i++)
    	{
    		cout << setw(30);
    		for (int j = 1; j <= roomsize; j++)
    		{
    			if (map[i][j] == 0) cout << "  ";
    			if (map[i][j] == 1) cout << "■";//墙
    			if (map[i][j] == 2) cout << "○";//目标位置
    			if (map[i][j] == 3) cout << "★";//箱子
    			if (map[i][j] == 4) cout << "♀";//人
    			if (map[i][j] == 5) cout << "㊣";//箱子在目标位置上
    		}
    		cout << endl;
    	}
    	cout << endl << endl;
    	cout << "撤销(Ctrl+z)★★★" << "选择(c)★★★" << "游戏步数:" << count << endl;
    }
    void box::left()//向左函数
    {
    	if (map[positionh][positionl - 1] == 0)
    	{
    		map[positionh][positionl - 1] = 4;
    		if (flag == 1)
    		{
    			map[positionh][positionl] = 2;  flag = 0;
    		}
    		else
    			map[positionh][positionl] = 0;
    		positionl--;
    	}
    	else if (map[positionh][positionl - 1] == 2)//人要到目标位置上
    	{
    		map[positionh][positionl - 1] = 4;
    		if (flag == 1)
    			map[positionh][positionl] = 2;//恢复目标位置
    		else
    		{
    			map[positionh][positionl] = 0;//恢复原来的状态
    			flag = 1;//标志位,记录人在目标位置上
    		}
    		positionl--;
    	}
    	else if (map[positionh][positionl - 1] == 3 && map[positionh][positionl - 2] == 0)//将箱子推到空白位置上
    	{
    		map[positionh][positionl - 2] = 3;
    		map[positionh][positionl - 1] = 4;
    		if (flag == 1)
    		{
    			map[positionh][positionl] = 2; flag = 0;
    		}
    		else
    			map[positionh][positionl] = 0;
    		positionl--;
    	}
    	else if (map[positionh][positionl - 1] == 5 && map[positionh][positionl - 2] != 1)//要将箱子从目标位置上推出
    	{
    		if (map[positionh][positionl - 2] == 2)//下一个位置还是目标位置
    		{
    			map[positionh][positionl - 2] = 5;
    			map[positionh][positionl - 1] = 4;
    			if (flag == 1)
    				map[positionh][positionl] = 2;
    			else
    			{
    				map[positionh][positionl] = 0; flag = 1;
    			}
    		}
    		else if (map[positionh][positionl - 2] == 0)//下一个位置是空白
    		{
    			map[positionh][positionl - 2] = 3;
    			map[positionh][positionl - 1] = 4;
    			if (flag == 1)
    				map[positionh][positionl] = 2;
    			else
    			{
    				map[positionh][positionl] = 0; flag = 1;
    			}
    		}
    		positionl--;
    	}
    	else if (map[positionh][positionl - 1] == 3 && map[positionh][positionl - 2] == 2)//要将箱子推到目标位置上
    	{
    		map[positionh][positionl - 2] = 5;//箱子在目标位置上
    		map[positionh][positionl - 1] = 4;
    		if (flag == 1)//人在目标位置上
    		{
    			map[positionh][positionl] = 2; flag = 0;
    		}
    		else //人不在目标位置上
    			map[positionh][positionl] = 0;
    		positionl--;
    	}
    	else count--;//抵消人不动的情况
    	test_flag();
    
    }
    void box::right()//向右函数
    {
    	if (map[positionh][positionl + 1] == 0)
    	{
    		map[positionh][positionl + 1] = 4;
    		if (flag == 1)
    		{
    			map[positionh][positionl] = 2;  flag = 0;
    		}
    		else
    			map[positionh][positionl] = 0;
    		positionl++;
    	}
    	else if (map[positionh][positionl + 1] == 2)//人要到目标位置上
    	{
    		map[positionh][positionl + 1] = 4;
    		if (flag == 1)
    			map[positionh][positionl] = 2;//恢复目标位置
    		else
    		{
    			map[positionh][positionl] = 0;//恢复原来的状态
    			flag = 1;//标志位,记录人在目标位置上
    		}
    		positionl++;
    	}
    	else if (map[positionh][positionl + 1] == 3 && map[positionh][positionl + 2] == 0)//将箱子推到空白位置上
    	{
    		map[positionh][positionl + 2] = 3;
    		map[positionh][positionl + 1] = 4;
    		if (flag == 1)
    		{
    			map[positionh][positionl] = 2; flag = 0;
    		}
    		else
    			map[positionh][positionl] = 0;
    		positionl++;
    	}
    	else if (map[positionh][positionl + 1] == 5 && map[positionh][positionl + 2] != 1)//要将箱子从目标位置上推出
    	{
    		if (map[positionh][positionl + 2] == 2)//下一个位置还是目标位置
    		{
    			map[positionh][positionl + 2] = 5;
    			map[positionh][positionl + 1] = 4;
    			if (flag == 1)
    				map[positionh][positionl] = 2;
    			else
    			{
    				map[positionh][positionl] = 0; flag = 1;
    			}
    		}
    		else if (map[positionh][positionl + 2] == 0)//下一个位置是空白
    		{
    			map[positionh][positionl + 2] = 3;
    			map[positionh][positionl + 1] = 4;
    			if (flag == 1)
    				map[positionh][positionl] = 2;
    			else
    			{
    				map[positionh][positionl] = 0; flag = 1;
    			}
    		}
    		positionl++;
    	}
    	else if (map[positionh][positionl + 1] == 3 && map[positionh][positionl + 2] == 2)//要将箱子推到目标位置上
    	{
    		map[positionh][positionl + 2] = 5;//箱子在目标位置上
    		map[positionh][positionl + 1] = 4;
    		if (flag == 1)//人在目标位置上
    		{
    			map[positionh][positionl] = 2; flag = 0;
    		}
    		else //人不在目标位置上
    			map[positionh][positionl] = 0;
    		positionl++;
    	}
    	else count--;//抵消人不动的情况
    	test_flag();
    }
    void box::down()//向下函数
    {
    	if (map[positionh + 1][positionl] == 0)
    	{
    		map[positionh + 1][positionl] = 4;
    		if (flag == 1)
    		{
    			map[positionh][positionl] = 2; flag = 0;
    		}
    		else
    			map[positionh][positionl] = 0;
    		positionh++;
    	}
    	else if (map[positionh + 1][positionl] == 2)//人要到目标位置上
    	{
    		map[positionh + 1][positionl] = 4;
    		if (flag == 1)
    			map[positionh][positionl] = 2;//恢复目标位置
    		else
    		{
    			map[positionh][positionl] = 0;//恢复原来的状态
    			flag = 1;//标志位,记录人在目标位置上
    		}
    		positionh++;
    	}
    	else if (map[positionh + 1][positionl] == 3 && map[positionh + 2][positionl] == 0)//将箱子推到空白位置上
    	{
    		map[positionh + 2][positionl] = 3;
    		map[positionh + 1][positionl] = 4;
    		if (flag == 1)
    		{
    			map[positionh][positionl] = 2; flag = 0;
    		}
    		else
    			map[positionh][positionl] = 0;
    		positionh++;
    	}
    	else if (map[positionh + 1][positionl] == 5 && map[positionh + 2][positionl] != 1)//要将箱子从目标位置上推出
    	{
    		if (map[positionh + 2][positionl] == 2)//下一个位置还是目标位置
    		{
    			map[positionh + 2][positionl] = 5;
    			map[positionh + 1][positionl] = 4;
    			if (flag == 1)
    				map[positionh][positionl] = 2;
    			else
    			{
    				map[positionh][positionl] = 0; flag = 1;
    			}
    		}
    		else if (map[positionh + 2][positionl] == 0)//下一个位置是空白
    		{
    			map[positionh + 2][positionl] = 3;
    			map[positionh + 1][positionl] = 4;
    			if (flag == 1)
    				map[positionh][positionl] = 2;
    			else
    			{
    				map[positionh][positionl] = 0; flag = 1;
    			}
    		}
    		positionh++;
    	}
    	else if (map[positionh + 1][positionl] == 3 && map[positionh + 2][positionl] == 2)//要将箱子推到目标位置上
    	{
    		map[positionh + 2][positionl] = 5;//箱子在目标位置上
    		map[positionh + 1][positionl] = 4;
    		if (flag == 1)//人在目标位置上
    		{
    			map[positionh][positionl] = 2; flag = 0;
    		}
    		else //人不在目标位置上
    			map[positionh][positionl] = 0;
    		positionh++;
    	}
    	else count--;//抵消人不动的情况
    	test_flag();
    }
    void box::up()//向上函数
    {
    	if (map[positionh - 1][positionl] == 0)
    	{
    		map[positionh - 1][positionl] = 4;
    		if (flag == 1)
    		{
    			map[positionh][positionl] = 2; flag = 0;
    		}
    		else
    			map[positionh][positionl] = 0;
    		positionh--;
    	}
    	else if (map[positionh - 1][positionl] == 2)//人要到目标位置上
    	{
    		map[positionh - 1][positionl] = 4;
    		if (flag == 1)
    			map[positionh][positionl] = 2;//恢复目标位置
    		else
    		{
    			map[positionh][positionl] = 0;//恢复原来的状态
    			flag = 1;//标志位,记录人在目标位置上
    		}
    		positionh--;
    	}
    	else if (map[positionh - 1][positionl] == 3 && map[positionh - 2][positionl] == 0)//将箱子推到空白位置上
    	{
    		map[positionh - 2][positionl] = 3;
    		map[positionh - 1][positionl] = 4;
    		if (flag == 1)
    		{
    			map[positionh][positionl] = 2; flag = 0;
    		}
    		else
    			map[positionh][positionl] = 0;
    		positionh--;
    	}
    	else if (map[positionh - 1][positionl] == 5 && map[positionh - 2][positionl] != 1)//要将箱子从目标位置上推出
    	{
    		if (map[positionh - 2][positionl] == 2)//下一个位置还是目标位置
    		{
    			map[positionh - 2][positionl] = 5;
    			map[positionh - 1][positionl] = 4;
    			if (flag == 1)
    				map[positionh][positionl] = 2;
    			else
    			{
    				map[positionh][positionl] = 0; flag = 1;
    			}
    		}
    		else if (map[positionh - 2][positionl] == 0)//下一个位置是空白
    		{
    			map[positionh - 2][positionl] = 3;
    			map[positionh - 1][positionl] = 4;
    			if (flag == 1)
    				map[positionh][positionl] = 2;
    			else
    			{
    				map[positionh][positionl] = 0; flag = 1;
    			}
    		}
    		positionh--;
    	}
    	else if (map[positionh - 1][positionl] == 3 && map[positionh - 2][positionl] == 2)//要将箱子推到目标位置上
    	{
    		map[positionh - 2][positionl] = 5;//箱子在目标位置上
    		map[positionh - 1][positionl] = 4;
    		if (flag == 1)//人在目标位置上
    		{
    			map[positionh][positionl] = 2; flag = 0;
    		}
    		else //人不在目标位置上
    			map[positionh][positionl] = 0;
    		positionh--;
    	}
    	else count--;//抵消人不动的情况
    	test_flag();
    
    }
    void box::test_flag()
    {
    	int choice;
    	int item[1000];
    	for (int i = 1; i <= roomsize; i++)
    	for (int j = 1; j <= roomsize; j++)
    	{
    		if (map[i][j] == 3)
    			return;
    	}
    	system("cls");
    	count++;
    	data = count;
    	times++;
    	display();
    	returninseart();
    	cout << "╭──────────────╮" << endl
    		<< "│恭喜小可爱呀!你通关啦哟!  │" << endl
    		<< "│★★★ 再来一局不?★★★   │" << endl
    		<< "│1. 继续                     │" << endl
    		<< "│2. 观看通关过程             │" << endl
    		<< "│3. 最好滴记录               │" << endl
    		<< "│4. 退出呀                   │" << endl
    		<< "╰──────────────╯" << endl;
    	cin >> choice;
    	switch (choice)
    	{
    	case 1:
    		count = 0;
    		Sleep(500);
    		system("cls");
    		begin();
    		break;
    	case 2:
    		travers();
    		cout << "按任意键回到主界面哟..." << endl;
    		_getch();
    		system("cls");
    		begin();
    		break;
    	case 3:
    		record();
    		system("cls");
    		cout << "按任意键回到主界面哟..." << endl;
    		begin();
    		break;
    	case 4:
    		cout << "★★★嘻嘻!欢迎再次游戏★★★" << endl;
    		cout << "★★★按任意键退出喔★★★" << endl;
    		_getch();
    		exit(0);
    	}
    }
    void box::record()//最佳记录
    {
    	int rhigh;
    	if (times % 2)
    		array[0] = data;
    	else
    		array[1] = data;
    	if (array[0]>array[1])
    		rhigh = array[1];
    	else
    		rhigh = array[0];
    	if (times % 2)
    		array[0] = rhigh;
    	else
    		array[1] = rhigh;
    	cout << "最优秀滴记录:" << rhigh << endl;
    	_getch();
    }
    void box::travers()
    {
    	int i, l = linkqu.getcount(), item[1000];
    	while (l)
    	{
    		i = 0;
    		linkqu.out(item);
    		for (int j = 0; j<roomsize + 2; j++)
    		for (int k = 0; k<roomsize + 2; k++)
    		{
    			map[j][k] = item[i];
    			i++;
    		}
    		system("cls");
    		display();
    		Sleep(50);
    		l--;
    	}
    }
    void box::returnpush()
    {
    	int i = 0, l, r;
    	for (int j = 0; j<roomsize + 2; j++)
    	for (int k = 0; k<roomsize + 2; k++)
    	{
    		if (map[j][k] == 4)
    		{
    			l = j;
    			r = k;
    		}
    		followmap[i] = map[j][k];
    		i++;
    	}
    	st.push(followmap, l, r);
    }
    void box::returninseart()
    {
    	int i = 0;
    	for (int j = 0; j<roomsize + 2; j++)
    	for (int k = 0; k<roomsize + 2; k++)
    	{
    		followmap[i] = map[j][k];
    		i++;
    	}
    	linkqu.insert(followmap);
    }
    
    //主程序
    int main()
    {
    	box Mybox;
    	system("color B0");
    	Mybox.begin();
    	return 0; 
    }