//*******************************************************
Sokoban.h: ç±»å®ä¹ Sokoban.c: ç±»æåå½æ°å®ç°
Use_Sokoban.c: 主å½æ°
请ç¨VC6ï¼å«ç¼è¯å¨çä¹è¡ï¼å
è¿è¡Use_Sokoban.cæ件,è¦ç¼è¯è¯¥æ件ä¸ä¸,
åç¹Project-> Add To Project-> Files éæ©Sokoban.cæ件,
å³å°Sokoban.cå è½½å°å·¥ç¨é,æåè¿è¡å°±OKæã
//*******************************************************
Sokoban.h
//*******************************************************
#ifndef SOKOBAN_H_ //é²æ¢æ件éå¤å
å«
#define SOKOBAN_H_
#include <queue>
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.cpp
//*******************************************************
#include "Sokoban.h"
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <conio.h>
using std::cout;
using std::endl;
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<node>_Box; //å建箱åéå
//visit对ä¸ä¸æ¥èµ°å°ä¸ä¸æ¥çè®°å½,é²æ¢ç®±åèµ°éå¤è·¯å²
//visit[i][j][z][k]表示箱åä»ç¹(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<node>_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;
}
//*************************************************
Use_Sokoban.cpp
//*************************************************
#include <iostream>
#include "Sokoban.h"
using namespace std;
int main()
{
Sokoban s;
s.Initial();
return 0;
}
//*************************************************
追é®é¢ è¿ä¸å¤å æ们èå¸è¦1000è¡å¢ æä¹ååï¼
追çå
³é®æ¯æåè½å®ç°ã
追é®è¿è¯ä½ è·æ说没ç¨å æ们èå¸æ¯è¦1000è¡ç代ç èªå·±é æé便说äºä¸ä¸ªæ¨ç®±å ä¸è½æ¹äº
追çé£å¸®ä¸äºä½
追é®é¢ è¿æ¯è°¢è°¢å¢ æåççæ
追çä¸å®¢æ°