推箱子游戲C++實現原理
阿新 • • 發佈:2018-11-19
通過WSAD控制箱子上下左右移動,Q退出程式。
{ '*',' ','O','#','@' }分別表示牆,空白,方塊,目標地,人,可以根據自己喜歡重新設定
地圖為7行10例,可以根據自己喜歡調整地圖形式:
char map[7][11] = { "**********",
"** ***",
"**O*** *",
"* O O *",
"* ##* [email protected]**",
"**##* **",
"**********", };
其他的程式碼裡面有相應的註釋。
#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 *",
"* ##* [email protected]**",
"**##* **",
"**********",
};//豎著的是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;
}