推箱子游戲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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章