通过WSAD控制箱子上下左右移动,Q退出程序。
{ '*',' ','O','#','@' }分别表示墙,空白,方块,目标地,人,可以根据自己喜欢重新设置
地图为7行10例,可以根据自己喜欢调整地图形式:
char map[7][11] = { "**********",
"** ***",
"**O*** *",
"* O O *",
"* ##* O@**",
"**##* **",
"**********", };
其他的代码里面有相应的注释。
#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include<vector>
using namespace std;
class Sokoban
{
private:
int startx1, starty1, startx2, starty2, startx3, starty3, startx4, starty4;//箱子的起始位置,未用
int endx1, endy1, endx2, endy2, endx3, endy3, endx4, endy4;//箱子终点位置
int manx, many;//人的起始位置
int boxx = 6, boxy = 9;
char direction;
bool controlswitch = true;
char map[7][11] = { "**********",
"** ***",
"**O*** *",
"* O O *",
"* ##* O@**",
"**##* **",
"**********",
};//竖着的是x,横着的是y
char boxback[5] = { '*',' ','O','#','@' };//墙,空白,方块,目标地,人
public:
void Setpara();//箱子终点位置获取
void Inputlocation();//输入移动方向
void Getlocation();//获取人的位置
bool Getcontrol();//控制while循环
void Move();//移动箱子
void Judgelocation();//判断箱子是否到地形边缘不能推动
void Resultshow();//刷新显示结果
};
bool Sokoban::Getcontrol()
{
return this->controlswitch;
}
void Sokoban::Inputlocation()
{
this->direction = getchar();
}
void Sokoban::Setpara()
{
//从数组图中获取重点位置,用于判断箱子是否就为
vector<vector<int>> endbox;
vector<int> endboxxy(2);
for (int i = 0; i <= boxx; i++)
{
for (int j = 0; j <= boxy; j++)
{
if (map[i][j] == boxback[3])
{
endboxxy[0] = i;
endboxxy[1] = j;
endbox.push_back(endboxxy);
}
}
}
this->endx1 = endbox[0][0];
this->endy1 = endbox[0][1];
this->endx2 = endbox[1][0];
this->endy2 = endbox[1][1];
this->endx3 = endbox[2][0];
this->endy3 = endbox[2][1];
this->endx4 = endbox[3][0];
this->endy4 = endbox[3][1];
}
void Sokoban::Getlocation()
{
//获取当前人物的位置,用于计算判断推箱子
manx, many = 0, 0;
for (int i = 0; i <= boxx; i++)//6
{
for (int j = 0; j <= boxy; j++)//10
{
if (map[i][j] == boxback[4])
{
this->manx = i;
this->many = j;
//cout << "人物当前坐标位置" << manx << "," << many << endl;
}
//cout << "当前坐标位置" <<map[i][j]<< endl;
}
}
}
void Sokoban::Resultshow()
{
system("cls");
cout << "欢迎使用推箱子游戏:" <<endl;
cout << "通过鼠标按键WSAD控制上下所有移动,Q退出,输入后回车" << endl;
for (int i = 0; i <= boxx; i++)
{
puts(map[i]);//用于打印显示a中的数据
}
//用于刷新避免人走过了目标提示就不在了
if (map[endx1][endy1] == boxback[1])
{
map[endx1][endy1] = boxback[3];
}
//用于刷新避免人走过了目标提示就不在了
if (map[endx2][endy2] == boxback[1])
{
map[endx2][endy2] = boxback[3];
}
//用于刷新避免人走过了目标提示就不在了
if (map[endx3][endy3] == boxback[1])
{
map[endx3][endy3] = boxback[3];
}
//用于刷新避免人走过了目标提示就不在了
if (map[endx4][endy4] == boxback[1])
{
map[endx4][endy4] = boxback[3];
}
//用于判断箱子是否被推进了目标区域
if (map[endx1][endy1]==boxback[2] && map[endx2][endy2] == boxback[2] && map[endx3][endy3] == boxback[2] && map[endx4][endy4] == boxback[2])
{
this->controlswitch = false;
cout << "游戏通关" << endl;
}
}
void Sokoban::Move()
{
if(map[manx][many] == boxback[4])
{
cout << map[manx][many] << endl;
//通过输入的移动方向AWSD判断箱子的移动方向,如果箱子移动方向是空地则向那个方向移动否则不动
if (direction == 'D' || direction == 'd')
{
if (map[manx][many + 1] == boxback[2] && (map[manx][many + 2] == boxback[1] || map[manx][many + 2] == boxback[3]))
{
map[manx][many] = boxback[1];
many++;
map[manx][many] = boxback[4];
many++;
map[manx][many] = boxback[2];
cout << "右移动了" << endl;
}
else if (map[manx][many + 1] == boxback[1] || map[manx][many + 1] == boxback[3])
{
map[manx][many] = boxback[1];
many++;
map[manx][many] = boxback[4];
cout << "右移动了" << endl;
}
}
else if(direction == 'A' || direction == 'a')
{
if (map[manx][many - 1] == boxback[2] && (map[manx][many - 2] == boxback[1] || map[manx][many - 2] == boxback[3]))
{
map[manx][many] = boxback[1];
many--;
map[manx][many] = boxback[4];
many--;
map[manx][many] = boxback[2];
cout << "左移动了" << endl;
}
else if (map[manx][many - 1] == boxback[1] || map[manx][many - 1] == boxback[3])
{
map[manx][many] = boxback[1];
many--;
map[manx][many] = boxback[4];
cout << "左移动了" << endl;
}
}
else if(direction == 'S' || direction == 's')
{
if (map[manx + 1][many] == boxback[2] && (map[manx + 2][many] == boxback[1] || map[manx + 2][many] == boxback[3]))
{
map[manx][many] = boxback[1];
manx++;
map[manx][many] = boxback[4];
manx++;
map[manx][many] = boxback[2];
cout << "下移动了" << endl;
}
else if (map[manx + 1][many] == boxback[1] || map[manx + 1][many] == boxback[3])
{
map[manx][many] = boxback[1];
manx++;
map[manx][many] = boxback[4];
cout << "下移动了" << endl;
}
}
else if((direction == 'W' || direction == 'w'))
{
if (map[manx - 1][many] == boxback[2] && (map[manx - 2][many] == boxback[1] || map[manx - 2][many] == boxback[3]))
{
map[manx][many] = boxback[1];
manx--;
map[manx][many] = boxback[4];
manx--;
map[manx][many] = boxback[2];
cout << "上移动了" << endl;
}
else if (map[manx - 1][many] == boxback[1] || map[manx - 1][many] == boxback[3])
{
map[manx][many] = boxback[1];
manx--;
map[manx][many] = boxback[4];
cout << "上移动了" << endl;
}
}
else if (direction == 'Q' || direction == 'q')
{
this->controlswitch = false;
cout << "退出游戏" << endl;
}
}
}
void Sokoban::Judgelocation()
{
for (int i = 0; i <= boxx; i++)//6
{
for (int j = 0; j <= boxy; j++)//10
{
if (map[i][j] == boxback[2])
{ //如果箱子在终点则忽略不能移动就退出的提前终止游戏机制
if (map[endx1][endy1] == boxback[2] || map[endx2][endy2] == boxback[2]
|| map[endx3][endy3] == boxback[2] || map[endx4][endy4] == boxback[2])
{
cout << "加油哦!" << endl;
}
//当箱子相邻两边是墙的时候,推不动了,就提前终止退出游戏
else if ((map[i + 1][j] == boxback[0] && map[i][j + 1] == boxback[0])
|| (map[i - 1][j] == boxback[0] && map[i][j - 1] == boxback[0])
|| (map[i + 1][j] == boxback[0] && map[i][j - 1] == boxback[0])
|| (map[i - 1][j] == boxback[0] && map[i][j + 1] == boxback[0]))
{
this->controlswitch = false;
cout << "你输了!" << endl;
}
}
}
}
}
int main()
{
//迷宫程序
//Maze maze;
//maze.Run();
Sokoban sokoban;
sokoban.Getlocation();
bool controlswitch = sokoban.Getcontrol();
sokoban.Setpara();
while (controlswitch)
{
sokoban.Resultshow();
sokoban.Inputlocation();
sokoban.Getlocation();
sokoban.Move();
sokoban.Judgelocation();
sokoban.Resultshow();
controlswitch = sokoban.Getcontrol();
}
cout << "很高兴见到你!" << endl;
Sleep(1000000);
return 0;
}