#include <iostream>
#include <windows.h>
#include <conio.h>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
const int ROW = 13;
const int COL = 13;
const int BOX_NUM = 3;
void GotoXY(int x, int y)
{
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void HideCursor()
{
CONSOLE_CURSOR_INFO c;
c.dwSize = 1;
c.bVisible = FALSE;
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &c);
}
char map[ROW][COL];
int px, py;
int dir4[4][2] = {{0,1},{0,-1},{1,0},{-1,0}};
void FindPlayer();
bool IsReachable(int sx, int sy, int ex, int ey, char tmpMap[ROW][COL]);
void CopyMap(char src[ROW][COL], char dst[ROW][COL]);
void GenerateMap();
bool IsReachable(int sx, int sy, int ex, int ey, char tmpMap[ROW][COL])
{
bool vis[ROW][COL] = {false};
queue<pair<int, int>> q;
q.push(make_pair(sx, sy));
vis[sy][sx] = true;
while(!q.empty())
{
pair<int,int> cur = q.front();
q.pop();
int x = cur.first;
int y = cur.second;
if(x == ex && y == ey)
return true;
for(int d = 0; d < 4; d++)
{
int nx = x + dir4[d][0];
int ny = y + dir4[d][1];
if(nx > 0 && nx < COL - 1 && ny > 0 && ny < ROW - 1)
{
if(!vis[ny][nx] && tmpMap[ny][nx] != '#')
{
vis[ny][nx] = true;
q.push(make_pair(nx, ny));
}
}
}
}
return false;
}
void CopyMap(char src[ROW][COL], char dst[ROW][COL])
{
for(int i = 0; i < ROW; i++)
for(int j = 0; j < COL; j++)
dst[i][j] = src[i][j];
}
void FindPlayer()
{
for(int i = 0; i < ROW; i++)
for(int j = 0; j < COL; j++)
if(map[i][j] == '@')
{
py = i;
px = j;
return;
}
}
void DrawMap()
{
GotoXY(0, 0);
for(int i = 0; i < ROW; i++)
{
for(int j = 0; j < COL; j++)
cout << map[i][j];
cout << endl;
}
cout << "WASD移动 | R重新生成 | Q退出";
}
bool CheckWin()
{
for(int i = 0; i < ROW; i++)
for(int j = 0; j < COL; j++)
if(map[i][j] == '$')
return false;
return true;
}
void Move(int dx, int dy)
{
int nx = px + dx;
int ny = py + dy;
if(map[ny][nx] == '#')
return;
if(map[ny][nx] == ' ' || map[ny][nx] == '.')
{
if(map[py][px] == '+')
map[py][px] = '.';
else
map[py][px] = ' ';
if(map[ny][nx] == '.')
map[ny][nx] = '+';
else
map[ny][nx] = '@';
px = nx;
py = ny;
return;
}
if(map[ny][nx] == '$' || map[ny][nx] == '*')
{
int boxNextX = nx + dx;
int boxNextY = ny + dy;
if(map[boxNextY][boxNextX] == '#' ||
map[boxNextY][boxNextX] == '$' ||
map[boxNextY][boxNextX] == '*')
return;
if(map[boxNextY][boxNextX] == '.')
map[boxNextY][boxNextX] = '*';
else
map[boxNextY][boxNextX] = '$';
if(map[py][px] == '+')
map[py][px] = '.';
else
map[py][px] = ' ';
if(map[ny][nx] == '*')
map[ny][nx] = '+';
else
map[ny][nx] = '@';
px = nx;
py = ny;
}
}
// 关键:生成一个中心连通的大房间,不再乱撒墙
void GenerateMap()
{
while(true)
{
char temp[ROW][COL];
for(int i = 0; i < ROW; i++)
for(int j = 0; j < COL; j++)
temp[i][j] = ' ';
for(int i = 0; i < ROW; i++)
{
temp[i][0] = '#';
temp[i][COL - 1] = '#';
}
for(int j = 0; j < COL; j++)
{
temp[0][j] = '#';
temp[ROW - 1][j] = '#';
}
// 只在边缘放少量内墙,中心保持可推空间
for(int i = 1; i < ROW - 1; i++)
{
for(int j = 1; j < COL - 1; j++)
{
if(abs(i - ROW / 2) <= 2 && abs(j - COL / 2) <= 2)
continue;
int r = rand() % 100;
if(r < 12)
temp[i][j] = '#';
}
}
int pX = COL / 2;
int pY = ROW / 2;
temp[pY][pX] = '@';
vector<pair<int,int>> boxes;
vector<pair<int,int>> targets;
int cnt = 0;
while(cnt < BOX_NUM)
{
int x = rand() % (COL - 4) + 2;
int y = rand() % (ROW - 4) + 2;
if(temp[y][x] == ' ' && IsReachable(pX, pY, x, y, temp))
{
temp[y][x] = '$';
boxes.push_back(make_pair(x, y));
cnt++;
}
}
cnt = 0;
while(cnt < BOX_NUM)
{
int x = rand() % (COL - 4) + 2;
int y = rand() % (ROW - 4) + 2;
if(temp[y][x] == ' ')
{
temp[y][x] = '.';
targets.push_back(make_pair(x, y));
cnt++;
}
}
bool allOk = true;
for(int b = 0; b < boxes.size(); b++)
{
int bx = boxes[b].first;
int by = boxes[b].second;
bool canPushToTarget = false;
for(int t = 0; t < targets.size(); t++)
{
int tx = targets[t].first;
int ty = targets[t].second;
if(IsReachable(bx, by, tx, ty, temp))
{
canPushToTarget = true;
break;
}
}
if(!canPushToTarget)
{
allOk = false;
break;
}
}
if(allOk)
{
CopyMap(temp, map);
break;
}
}
FindPlayer();
}
int main()
{
HideCursor();
srand((unsigned)time(NULL));
GenerateMap();
char key;
while(true)
{
DrawMap();
if(CheckWin())
{
GotoXY(0, ROW + 2);
cout << "==== 恭喜通关!按R刷新 ====" << endl;
}
if(_kbhit())
{
key = _getch();
switch(key)
{
case 'w': Move(0, -1); break;
case 's': Move(0, 1); break;
case 'a': Move(-1, 0); break;
case 'd': Move(1, 0); break;
case 'r': GenerateMap(); break;
case 'q': return 0;
}
}
Sleep(40);
}
system("pause");
return 0;
}