C++ 实现推箱子

初始构思思维导图:

推箱子若是每移动一步都要去找到player的坐标位置和遍历数组判断是否完成游戏会使整个程序变得臃肿,时间复杂度较高

优化:

1.移动成功就改变player的坐标

2.类里面定义一个count,在找player 的坐标时记录BOX的个数,每有一个BOX在BOX_TARGET上面移走,count++,每有一个BOX移动到TARGET,count++

代码:

1.地图类:

包含地图绘制和读取地图(当时写的时候定义和实现没分开,后面就懒得改了)

关于为什么使用wcout详见另一个博客:C++关于Unicode特殊字符的输出(在控制台输出宽字符)

https://blog.csdn.net/cOnhthefroad/article/details/102613322

map.h:

#pragma once
#include<iostream>
#include<fstream>
#include<io.h>
#include<fcntl.h>
using namespace std;
#define N 10
#define M 10
class Map
{
public:
	void Init(int map[M][N]);//地图绘制
	bool ReadMapFile(int map[M][N], const char* filename);//读取地图文件到二维数组中,因为

};
void Map::Init(int map[M][N])
{
	_setmode(_fileno(stdout), _O_U16TEXT);
	for (int i = 0; i < M; i++)
	{

		for (int j = 0; j < N; j++)
		{
			switch (map[i][j])
			{
			case 0:
				wcout << L"⛆";//外围
				break;
			case 1:
				wcout << L"■";//墙体
				break;
			case 2:
				wcout << "  ";//路
				break;
			case 3:
				wcout << L"☒";//箱子
				break;
			case 4:
				wcout << L"⚐";//目的地
				break;
			case 5:
				wcout << L"☹";//玩家
				break;
			case 6:
				wcout << L'☑';//箱子和目标点重合
				break;
			case 7:
				wcout << L'✪';//玩家和目标点重合
				break;
			case 8:
				wcout << L"✌ ";//赢得游戏时player变成耶的手势
			default:
				break;
			}
		}
		wcout << endl;
	}
}
bool Map::ReadMapFile(int map[M][N], const char* filename)
{
	ifstream read;
	read.open(filename, ios::in);
	if (!read.is_open())
	{
		wcout << "地图打开失败" << endl;
		return false;
	}
	for (int i = 0; i < M; i++)
	{
		for (int j = 0; j < N; j++)
		{
			read >> map[i][j];
		}
	}
	return true;

}

2.游戏类:

game.h:

#pragma once
#include<iostream>
using namespace std;
#include<string>
#include<conio.h>
#define M 10             //定义数组的大小
#define N 10
#define OUT 0            //0表示外围
#define WALL 1           //1表示墙
#define ROAD 2           //2表示路
#define BOX 3            //3表示箱子
#define TARGET 4         //4表示目标点
#define PLAYER 5         //5表示玩家
#define BOX_TARGET 6     //6表示箱子在目标点
#define PLAYER_TARGET 7  //7表示玩家在目标点
#define YOU_WIN 8        //8表示游戏胜利
class Game
{
public:
	int pM;
	int pN;
	int count=0;//定义未达成目标点计数器
	void foundplayer(int map[M][N]);//找到玩家的位置和未达成目标点个数
	void move(int map[M][N], char ch);//玩家移动
};

实现:game.cpp:

因为要分类的情况比较多,所以稍显复杂,其实已经粗浅的优化过了,为玩家移动后该点的元素定义一个值,通过三元运算符来判断玩家是否在目标点上,并为移动后该点赋值

#include"Game.h"
void Game::foundplayer(int map[M][N])
{
	for (int i = 0; i < M; i++)
	{
		for (int j = 0; j < N; j++)
		{
			if (map[i][j] == PLAYER||map[i][j]==PLAYER_TARGET)
			{
				pM = i;
				pN = j;
			}
			if (map[i][j]==TARGET|| map[i][j] == PLAYER_TARGET)
			{
				count++;
			}
		}
	}
}
void Game::move(int map[M][N],char ch)
{
	
	int x=0, y=0;
	switch (ch)//根据方向改变移位值
	{
	case 'W':case'w':
		x = -1; y = 0;
		break;
	case 'S':case's':
		x = 1; y = 0; 
		break;
	case 'A':case'a':
		x = 0; y = -1;
		break;
	case 'D':case'd':
		x = 0; y = 1;	
		break;
	default:
		break;
	}
	int is_aim;
	map[pM][pN]==PLAYER ? is_aim = ROAD : is_aim = TARGET;//若玩家在目标点,则移动后为目标点
	if (map[pM + x * 1][pN + y * 1] == ROAD)//上一格是路
	{
		map[pM + x * 1][pN + y * 1] = PLAYER;
		map[pM][pN] = is_aim;
		pM = pM + x;//玩家位置改变
		pN = pN + y;
		return;
	}
	else if (map[pM + x * 1][pN + y * 1] == TARGET)//上一格是目标点
	{
		map[pM + x * 1][pN + y * 1] = PLAYER_TARGET;
		map[pM][pN] = is_aim;
		pM = pM + x;//玩家位置改变
		pN = pN + y;
		return;
	}
	else if (map[pM + x * 1][pN + y * 1] == BOX )//上一格是箱子
	{
		if (map[pM + x * 2][pN + y * 2] == TARGET)//上上格是目标点
		{
			map[pM][pN] = is_aim;
			map[pM + x * 1][pN + y * 1] = PLAYER;
			map[pM + x * 2][pN + y * 2] = BOX_TARGET;
			pM = pM + x;//玩家位置改变
			pN = pN + y;
			count--;//一个BOX到达TARGET
			return;
		}
		if (map[pM + x * 2][pN + y * 2] == ROAD)//上上格是路
		{
			map[pM][pN] = is_aim;
			map[pM + x * 1][pN + y * 1] = PLAYER;
			map[pM + x * 2][pN + y * 2] = BOX;
			pM = pM + x;//玩家位置改变
			pN = pN + y;
			return;
		}
	}
	else if (map[pM + x * 1][pN + y * 1] == BOX_TARGET)//上一格是BOX_TARGET
	{
		if (map[pM + x * 2][pN + y * 2] == TARGET)//上上格是目标点,此时一个BOX从一个TARGET移出到另一个TARGET,count不变
		{
			map[pM][pN] = is_aim;
			map[pM + x * 1][pN + y * 1] = PLAYER_TARGET;
			map[pM + x * 2][pN + y * 2] = BOX_TARGET;
			pM = pM + x;//玩家位置改变
			pN = pN + y;
			return;
		}
		if (map[pM + x * 2][pN + y * 2] == ROAD)//上上格是路
		{
			map[pM][pN] = is_aim;
			map[pM + x * 1][pN + y * 1] = PLAYER_TARGET;
			map[pM + x * 2][pN + y * 2] = BOX;
			count++;//一个箱子从目标点移出
			pM = pM + x;//玩家位置改变
			pN = pN + y;
			return;
		}

	}
}

主函数:

main.cpp

#include"Map.h"
#include"Game.h"
#include<io.h>
#include<fcntl.h>
#define M 10
#define N 10
int main()
{
	Map map;
	Game game;
	int map_arr[M][N];
	int num = 0;
	bool is_readmap = 1;
	while (1)
	{
		
		string map_num = "Map/map_" + to_string(num) + ".txt";//文件名赋值给map_num
		const char* map_fileneme = map_num.c_str();//将文件名从string转为const char*
		is_readmap=map.ReadMapFile(map_arr, map_fileneme);//读取地图文件,并将返回值赋给is_readmap
		if (!is_readmap)//读取文件失败跳出循环
		{
			break;
		}
		game.foundplayer(map_arr);//找到玩家位置和未达成目标点个数
		while (game.count)//count为0时BOX全部移动到TARGET上
		{
			system("CLS");//清屏
			map.Init(map_arr);//绘制地图
			char ch = _getch();//接受键盘输入
			game.move(map_arr, ch);//移动
		}
		system("CLS");//清屏
		map_arr[game.pM][game.pN] = YOU_WIN;//玩家变成"耶"
		map.Init(map_arr);//绘制地图
		wcout << "You pass map" << num<<endl;
		num++;
		system("pause");
	}
	wcout << "You passed all the maps";
}

运行效果图:

 

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DEVC是一种实现推箱子游戏开发环境。在引用中,给出了详细介绍和示例代码,可以作为参考。在推箱子游戏中,玩家需要通过移动来推动箱子到目标位置。在引用中提供了一部分代码示例,展示了当玩家移动一步时,箱子和目标位置的变化。具体代码如下: ``` else if(a[x+1][y]=='O') { if(a[x+2][y]==' ') { a[x][y]=' '; x++; a[x][y]='S'; a[x+1][y]='O'; } else if(a[x+2][y]=='*') { a[x][y]=' '; x++; a[x][y]='S'; a[x+1][y]=' '; cnt++; } } ``` 这段代码展示了当玩家向下移动时,如果目标位置是空地,那么箱子和玩家都会向下移动,并且箱子会出现在新的目标位置上。如果目标位置是已经有箱子的地方,那么箱子会被推到下一个空地,并且计数器会增加。而DEVC开发环境可以帮助开发者更方便地实现推箱子游戏的逻辑。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [DEVC++实现推箱子游戏](https://download.csdn.net/download/weixin_38728464/12743680)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [如何用DevC++推箱子?(2)](https://blog.csdn.net/xiaohubushihu/article/details/128430031)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值