首页 推箱子源代码

推箱子源代码

举报
开通vip

推箱子源代码#include #include #include #include #include using std::cout; using std::endl; #ifndef SOKOBAN_H_ //防止文件重复包含 #define SOKOBAN_H_ #include using std::queue; //每一步的数据类型 struct node { int bx, by; //箱子的坐标 int px, py; //人的坐标 }; //推箱子类 class ...

推箱子源代码
#include #include #include #include #include using std::cout; using std::endl; #ifndef SOKOBAN_H_ //防止文件重复包含 #define SOKOBAN_H_ #include using std::queue; //每一步的数据类型 struct node { int bx, by; //箱子的坐标 int px, py; //人的坐标 }; //推箱子类 class Sokoban { private: enum {L = 15, H = 7}; char GameMap[H][L]; //地图 int Pex, Pey; //人的位置 int Boxx, Boxy; //箱子的位置 int Succeed, Prove; //是否成功到目的地, 是否可玩性 int dx[4], dy[4]; //方向数组 protected: char Empty; char People; char Box; char Block; char Target; int dir; //记录按键方向 node s, e; public: Sokoban(); //构建函数 ~Sokoban() {} //析构函数,即为inline //地图初始化函数 void Initial(); //箱子路劲验证函数,参数为箱子坐标(bx,by),人坐标(px,py) void Box_Bfs(int bx, int by, int px, int py); //人路劲验证函数,人所到的目的地(ex,ey) bool People_Bfs(int ex, int ey); //地图刷新函数 void Show(); //按键判断函数 void Button(); //箱子人移动函数 void Move(); //验证越界函数 bool Check(int x, int y); }; #endif
 Sokoban::Sokoban() //构建函数即对变量初始化 
{ 
dir = -1; 
Succeed = Prove = 0; 
memset(GameMap, '.', sizeof(GameMap)); 
Empty = '.'; 
People = 'P'; 
Box = '#'; 
Block = '*'; 
Target = 'T'; 
//方向依次为上右下左 
dx[0] = -1; dx[1] = 0; dx[2] = 1; dx[3] = 0; 
dy[0] = 0; dy[1] = 1; dy[2] = 0; dy[3] = -1; 
//随机种子,使程序每次运行时所产生的随机数不同srand(time(0)); 
} 
//地图初始化函数 
void Sokoban::Initial() 
{ 
int count = 0, x, y; 
//对地图中随机产生25个阻碍物 
while(count != 25) 
{ 
x = rand()%H; 
y = rand()%L; 
if(GameMap[x][y] == Empty) 
{ 
GameMap[x][y] = Block; 
count++; 
} 
} 
while(true) //随机产生人开始的位置 
{ 
x = rand()%H; 
y = rand()%L; 
if(GameMap[x][y] == Empty) 
{ 
GameMap[x][y] = People; 
Pex = x; 
Pey = y; 
break; 
} 
} 
while(true) //随机产生箱子开始的位置 
{ 
x = rand()%H; 
y = rand()%L; 
//不让箱子在地图的边界处 
if(GameMap[x][y] == Empty && x != 0 && y != 0 
&& x != H-1 && y != L-1) 
{ 
GameMap[x][y] = Box; 
Boxx = x; 
Boxy = y; 
break; 
} 
} 
while(true) //随机产生目标的位置 
{ 
x = rand()%H; 
y = rand()%L; 
if(GameMap[x][y] == Empty) 
{ 
GameMap[x][y] = Target; 
break; 
} 
} 
//对游戏地图检查是否可将箱子推到目的地,即判断游戏可玩性Sokoban::Box_Bfs(Boxx, Boxy, Pex, Pey); 
//如游戏不可玩,即再随机产生地图 
if(!Prove) 
{ 
memset(GameMap, '.', sizeof(GameMap)); Sokoban::Initial(); 
} 
else 
Sokoban::Show(); 
} 
//箱子路劲验证函数 
//用BFS算法对箱子验证是否可到目的地 
void Sokoban::Box_Bfs(int bx, int by, int px, int py) 
{ 
queue_Box; //创建箱子队列 
//visit对上一步走到下一步的记录,防止箱子走重复路劲 
//visit[i][j][z][k]
            
            关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
        示箱子从点(i,j)到点(z,k) 
//visit[][][][]为0时表示为走过,1时表示已走过 
int visit[H][L][H][L]; 
memset(visit, 0, sizeof(visit)); //visit数组初始化 
s.bx = bx; s.by = by; //将起始的箱子、人位置放入队列 
s.px = px; s.py = py; 
_Box.push(s); 
int pe_x, pe_y; 
while(!_Box.empty()) //队列为空时跳出 
{ 
s = _Box.front(); 
_Box.pop(); 
if(GameMap[s.bx][s.by] == Target) //到达目的地 
{ 
Prove = 1; 
break; 
} 
for(int i = 0; i < 4; i++) 
{ 
e.bx = s.bx + dx[i]; e.by = s.by + dy[i]; 
switch(i) //人推箱子的位置 
{ 
case 0: pe_x = s.bx + dx[2]; pe_y = s.by + dy[2]; break; 
case 1: pe_x = s.bx + dx[3]; pe_y = s.by + dy[3]; break; 
case 2: pe_x = s.bx + dx[0]; pe_y = s.by + dy[0]; break; 
case 3: pe_x = s.bx + dx[1]; pe_y = s.by + dy[1]; break; 
} 
//验证箱子和人的位置的合法性 
if(!Check(e.bx, e.by) || !Check(pe_x, pe_y) 
|| GameMap[e.bx][e.by] == Block || GameMap[pe_x][pe_y] == Block 
|| visit[s.bx][s.by][e.bx][e.by] ) 
continue; 
//如人可推箱子即进入队列 
if(Sokoban::People_Bfs(pe_x, pe_y)) 
{ 
//保存人推箱子后的位置 
e.px = pe_x; e.py = pe_y; 
_Box.push(e); 
visit[s.bx][s.by][e.bx][e.by] = 1; //箱子路劲的标记 
} 
} 
} 
} 
//人路劲验证函数 
//用BFS算法对人验证是否可推箱子 
bool Sokoban::People_Bfs(int ex, int ey) 
{ 
queue_People; 
node t, end; 
//visit数组对人的路劲进行标记,0为未走过,1为走过 
int visit[H][L]; 
//visit数组初始化为0 
memset(visit, 0, sizeof(visit)); 
t.px = s.px; t.py = s.py; //人初始位置进入队列 
_People.push(t); 
visit[t.px][t.py] = 1; 
while(!_People.empty()) //对立为空时跳出 
{ 
t = _People.front(); 
_People.pop(); 
if(t.px == ex && t.py == ey) //人可到达(ex,ey)该点 
return 1; 
for(int i = 0; i < 4; i++) 
{ 
end.px = t.px + dx[i]; end.py = t.py + dy[i]; 
//检查人的位置合法性 
if(!Check(end.px, end.py) || GameMap[end.px][end.py] == Block || GameMap[end.px][end.py] == Box || visit[end.px][end.py]) 
continue; 
//进入队列 
_People.push(end); 
visit[end.px][end.py] = 1; //记录 
} 
} 
return 0; 
} 
//地图刷新函数 
void Sokoban::Show() 
{ 
int i, j; 
while(true) 
{ 
//每半秒刷新一次地图 
clock_t s = clock(); 
while(clock() - s < CLOCKS_PER_SEC/2) 
; 
//先判断按键在移动 
Sokoban::Button(); 
Sokoban::Move(); 
system("cls"); 
for(i = 0; i < H; i++) 
{ 
for(j = 0; j < L; j++) 
cout << GameMap[i][j]; 
cout << endl; 
} 
cout << endl; 
cout << "\n**********************************" << endl; cout << "* 小小C++语言推箱子游戏*" << endl; cout << "* 游戏规则: *" << endl; 
cout << "* P: 人#: 箱子*" << endl; 
cout << "* *: 障碍物T: 目的地*" << endl; cout << "**********************************" << endl; 
cout << "* 每次游戏地图不一样*" << endl; 
cout << "* 人将箱子推到目的地即过关*" << endl; 
cout << "*所给地图,一定可过关,请慎重移箱子*" << endl; 
cout << "* 箱子无路可走时,机器不会提示*" << endl; 
cout << "**********************************" << endl; 
//箱子成功到达目的地 
if(Succeed) 
{ 
cout << "\n ^_^ >_<" << endl; 
cout << "恭喜过关成功! 再来一盘吧" << endl; 
getchar(); 
break; 
} 
} 
} 
//按键判断函数 
void Sokoban::Button() 
{ 
int key; 
if(kbhit() != 0) //检查当前是否有键盘输入,若有则返回一个非0值,否则返回0 { 
while(kbhit() != 0) //可能存在多个按键,要全部取完,以最后一个为主key = getch(); //将按键从控制台中取出并保存到key中 
switch(key) 
{ 
//上 
case 72: dir = 0; 
break; 
//右 
case 77: dir = 1; 
break; 
//下 
case 80: dir = 2; 
break; 
//左 
case 75: dir = 3; 
break; 
} 
} 
} 
//人推箱子移动函数 
void Sokoban::Move() 
{ 
int x, y; 
//有按键时 
if(dir != -1) 
{ 
//人所推向的位置坐标 
x = Pex + dx[dir]; y = Pey + dy[dir]; 
//人所推位置为空,即走向该位置 
if(Check(x, y) && GameMap[x][y] == '.') 
{ 
GameMap[Pex][Pey] = '.'; //人的位置改变 
GameMap[x][y] = 'P'; 
Pex = x; Pey = y; 
dir = -1; //按键记录为无即-1 
} 
else //人所推位置为箱子,即将箱子推向该方向的前面这点if(Check(x, y) && GameMap[x][y] == '#' 
&& Check(x+dx[dir], y+dy[dir]) 
&& GameMap[ x+dx[dir] ][ y+dy[dir] ] == '.') 
{ 
GameMap[Boxx][Boxy] = '.'; //箱子的位置改变 
GameMap[x+dx[dir] ][ y+dy[dir] ] = '#'; 
Boxx = x + dx[dir]; Boxy = y + dy[dir]; 
GameMap[Pex][Pey] = '.'; //人的位置改变 
GameMap[x][y] = 'P'; 
Pex = x; Pey = y; 
dir = -1; 
} 
else //将箱子推向该方向的前面这点为目的地 
if(Check(x, y) && GameMap[x][y] == '#' 
&& Check(x+dx[dir], y+dy[dir]) 
&& GameMap[ x+dx[dir] ][ y+dy[dir] ] == 'T') { 
GameMap[Boxx][Boxy] = '.'; //箱子的位置改变 
GameMap[x+dx[dir] ][ y+dy[dir] ] = '#'; 
Boxx = x + dx[dir]; Boxy = y + dy[dir]; 
GameMap[Pex][Pey] = '.'; //人的位置改变 
GameMap[x][y] = 'P'; 
Pex = x; Pey = y; 
dir = -1; 
Succeed = 1; //记录成功到达目的地 
} 
} 
} 
//判断越界情况 
bool Sokoban::Check(int x, int y) 
{ 
if(x < 0 || x >= H || y < 0 || y >= L) 
return 0; 
else 
return 1; 
} 
#include  
//#include "Sokoban.h" 
using namespace std; 
int main() 
{ 
Sokoban s; 
s.Initial(); 
return 0; 
} 
本文档为【推箱子源代码】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_036899
暂无简介~
格式:doc
大小:39KB
软件:Word
页数:20
分类:互联网
上传时间:2019-01-22
浏览量:220