推箱子游戏C++实现原理

通过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;
}

猜你喜欢

转载自blog.csdn.net/zx520113/article/details/83998706