C++ 简化 推箱子 小游戏 完整代码 参考网络资料 命令行运行 仅供初学者参考交流
说明:学做了4关推箱子, 仅供初学者参考可用g++ 编译,可以将内容复制到TXT文件,将后缀改为".cpp"。打开“运行”,输“CMD”,进命令行窗口,用"CD "命令切换目录到main .cpp所在处,输入"g++ main.cpp"回车,输入"a.exe"回车,进入游戏,输入"ALT + C"退出。
效果图
#墙, _空白区, _终点, $箱子, I人。
完整C++代码如下:命令行 g++ 编译 即可运行
#include <iostream>
#include <string>
using namespace std;
//学做了4关推箱子,与初学者交流
//可用g++ 编译,可以将内容复制到TXT文件,将后缀改为".cpp"。
//打开“运行”,输“CMD”,进命令行窗口,用"CD "命令切换目录到main .cpp所在处
//输入"g++ main.cpp"回车
//输入"a.exe"回车,进入游戏
//输入"ALT + C"退出
//公共变量
int gTimes = 1;//当前关数
int gStageWidth;
int gStageHeight;
int gN;
//关卡1地图,#墙 _空白区 .终点 o砖块 p人,
char gStageData_1[] = "\
########\n\
# #\n\
# $ $__#\n\
# I #\n\
########";
int gStageWidth_1 = 8;
int gStageHeight_1 = 5;
int N_1 = 20;//游戏限定步数
//关卡2地图
char gStageData_2[] = "\
################### \n\
# I ## # # \n\
# _ $ # # \n\
# $## # # # \n\
# # # ### \n\
# _ _ \n\
## ## ##### $ _ # \n\
";
int gStageWidth_2 = 20;
int gStageHeight_2 = 8;
int N_2 = 100;//游戏限定步数
//关卡3地图
char gStageData_3[] = "\
####################\n\
# ##_ # _#\n\
# _ $ # #\n\
# ## # #_ #\n\
# # # ###$ #\n\
# _ I #\n\
##_ ### ##### $ #\n\
# $ _ #\n\
# # _ #\n\
####################";
int gStageWidth_3 = 20;
int gStageHeight_3 = 10;
int N_3 = 150;//游戏限定步数
//关卡4地图
char gStageData_4[] = "\
####################\n\
# ##_ # _#\n\
# _ $ ##_ # $ _#\n\
# #### # #_ #\n\
# # ###$$ #\n\
# $ _ $$ #\n\
# _ #_ $ #\n\
# # $ # ### \n\
# I ### # #_ #\n\
####################";
int gStageWidth_4 = 20;
int gStageHeight_4 = 10;
int N_4 = 150;//游戏限定步数
enum Object{
OBJ_SPACE,
OBJ_WALL,
OBJ_GOAL,
OBJ_BLOCK,
OBJ_BLOCK_ON_GOAL,
OBJ_MAN,
OBJ_MAN_ON_GOAL,
OBJ_UNKNOWN,
};
//函数声明
void initialize( Object* state, int w, int h, char* stageData );
void draw( const Object* state, int w, int h);
void update( Object* state, char input, int w, int h );
bool checkClear( const Object* state, int w, int h );
void part(int gStageWidth,int gStageHeight,int gN,char* gStageData);
int main(){
system("title 推箱子_V1.4");//标题名称
system("color 0E");//颜色 背景前景
cout<<"Tips:A:left D:right W:up S:down "; //操作说明
//各关卡
if(gTimes==1){
part( gStageWidth_1, gStageHeight_1,N_1,gStageData_1);
}
if(gTimes==2){
part( gStageWidth_2, gStageHeight_2,N_2,gStageData_2);
}
if(gTimes==3){
part(gStageWidth_3, gStageHeight_3,N_3,gStageData_3);
}
if(gTimes==4){
part(gStageWidth_4, gStageHeight_4,N_4,gStageData_4);
}
cout << "QUIT GAME , print\"ctrl + C\" quit GAME." << endl;
//幕后信息
system("color 0E");
cout <<"欢迎继续开发改编,祥子学习制作 2022-01-01\n";//通关信息
//死循环防闪现
while( true ){ ; }
return 0;
}
//---------------------函数--------------
//关卡加载函数
void part(int gStageWidth_,int gStageHeight_,int n,char* gStageData_){
cout<<gTimes <<" start";
gStageWidth = gStageWidth_;
gStageHeight = gStageHeight_;
gN = n;
Object* state = new Object[ gStageWidth * gStageHeight ]; //创建数组
initialize( state, gStageWidth_, gStageHeight_, gStageData_ ); //初始化
bool flag = true;
while ( gN!=0 && flag ){
//绘制
draw( state, gStageWidth, gStageHeight);
//通关检测
if ( checkClear(state, gStageWidth, gStageHeight) ){
cout << "Congratulation's! you won" << endl;
++gTimes;//过关当前关数+1
flag = false;
}
char input;
cin >> input;
//更新
update( state, input, gStageWidth, gStageHeight );
system("cls");//清理屏幕
}
//析构
delete[] state;
state = 0;
}
//数据加载函数
void initialize( Object* state, int width, int /* height */, char* stageData ){
const char* d = stageData; //数据读取位置
int x = 0;
int y = 0;
while ( *d != '\0' ){ //指针不等于NULL,,老手常用操作
Object t; //临时变量
switch ( *d ){
case '#': t = OBJ_WALL; break;
case ' ': t = OBJ_SPACE; break;
case '$': t = OBJ_BLOCK; break;
case '0': t = OBJ_BLOCK_ON_GOAL; break;
case '_': t = OBJ_GOAL; break;
case 'I': t = OBJ_MAN; break;
case 'M': t = OBJ_MAN_ON_GOAL; break;
case '\n': x = 0; ++y; t = OBJ_UNKNOWN; break; //换行处理
default: t = OBJ_UNKNOWN; break;
}
++d;
if ( t != OBJ_UNKNOWN ){ //未定义元素处理
state[ y*width + x ] = t; //写入
++x;
}
}
}
void draw( const Object* state, int width, int height){
cout<<" LIFE:"<<gN<<endl;
cout<<endl;
const char font[] = {' ', '#', '_', '$', '0', 'I', 'M'}; //Object的可能值
for ( int y = 0; y < height; ++y ){
for ( int x=0; x < width; ++x ){
Object o = state[ y*width + x ];
cout << font[ o ];
}
cout << endl;
}
gN--;//自减1,计算剩余步数
cout<<endl;
}
void update( Object* s, char input, int w, int h ){
//移动量
int dx = 0;
int dy = 0;
switch ( input ){
case 'a': dx = -1; break; //左
case 'd': dx = 1; break; //右
case 'w': dy = -1; break; //上,Y朝下为+
case 's': dy = 1; break; //下
}
//查主角坐标
int i = -1;
for ( i = 0; i < w * h; ++i ){
if ( s[ i ] == OBJ_MAN || s[ i ] == OBJ_MAN_ON_GOAL ){
break;
}
}
int x = i % w;
int y = i / w;
//移动
//移后坐标
int tx = x + dx;
int ty = y + dy;
//判断坐标极值。不超出合理值
if ( tx < 0 || ty < 0 || tx >= w || ty >= h ){
return;
}
//A.该方向上是空白或者终点。主角则移动
int p = y*w + x; //人员位置
int tp = ty*w + tx; //目标位置(TargetPosition)
if ( s[ tp ] == OBJ_SPACE || s[ tp ] == OBJ_GOAL ){
s[ tp ] = ( s[ tp ] == OBJ_GOAL ) ? OBJ_MAN_ON_GOAL : OBJ_MAN; //如果该位置是终点,则将该位置值变为“终点上站着人”
s[ p ] = ( s[ p ] == OBJ_MAN_ON_GOAL ) ? OBJ_GOAL : OBJ_SPACE; //如果该位置已经是“终点上站着人”,则变为“终点”
//B.如果该方向上是箱子。并且该方向的下下个格子是空白或者终点,则允许移动
}else if ( s[ tp ] == OBJ_BLOCK || s[ tp ] == OBJ_BLOCK_ON_GOAL ){
//检测同方向上的下下个格子是否位于合理值范围
int tx2 = tx + dx;
int ty2 = ty + dy;
if ( tx2 < 0 || ty2 < 0 || tx2 >= w || ty2 >= h ){ //按键无效
return;
}
int tp2 = ( ty + dy )*w + ( tx + dx ); //下下个格子
if ( s[ tp2 ] == OBJ_SPACE || s[ tp2 ] == OBJ_GOAL ){
//按顺序替换
s[ tp2 ] = ( s[ tp2 ] == OBJ_GOAL ) ? OBJ_BLOCK_ON_GOAL : OBJ_BLOCK;
s[ tp ] = ( s[ tp ] == OBJ_BLOCK_ON_GOAL ) ? OBJ_MAN_ON_GOAL : OBJ_MAN;
s[ p ] = ( s[ p ] == OBJ_MAN_ON_GOAL ) ? OBJ_GOAL : OBJ_SPACE;
}
}
}
//如果没有移动目标物则判定为通关
bool checkClear( const Object* s, int width, int height ){
for ( int i = 0; i < width*height; ++i ){
if ( s[ i ] == OBJ_BLOCK ){
return false;
}
}
return true;
}