程序员带你回味童年,一起用C语言做一个“推箱子”玩!文末源码

Posted 灰小猿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了程序员带你回味童年,一起用C语言做一个“推箱子”玩!文末源码相关的知识,希望对你有一定的参考价值。

这篇文章是用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; 
}

觉得有用的小伙伴可以点赞关注哟!

有问题的小伙伴可以在评论区留言提出!

我是灰小猿!我们下期见!

 

以上是关于程序员带你回味童年,一起用C语言做一个“推箱子”玩!文末源码的主要内容,如果未能解决你的问题,请参考以下文章

用Python玩任何一款街机,带你一起回味童年!

带你还原童年,扫雷游戏完整源码分析!

推箱子小游戏——c/c++实现

怀念童年,推箱子小游戏(vue版本)

用C写一个简单的推箱子游戏

回忆童年和小伙伴一起玩过的经典游戏炸弹人小游戏制作过程+解析 | 收藏起来跟曾经的小伙伴一起梦回童年!