初始构思思维导图:
推箱子若是每移动一步都要去找到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";
}
运行效果图: