#include #include #include #include #include #include #include using namespace std; // 显示区域的大小 const size_t sWidth = 60, sHeight = 24; // 迷宫的实际大小(必须是奇数!) const size_t width = 33, height = 15; const char wall = 1; const char path = 0; const char target = 2; // 地图 char map[height][width]; bool fog[height][width]; bool walk[height][width]; // 带凿墙列表 vector, int> > walls; /* 随机prim算法的核心是: 1、让迷宫全是墙 2、选一个格作为迷宫的通路,然后把它的邻墙放入列表 3、当列表里还有墙时 ——1、从列表里随机选一个墙,如果它对面的格子不是迷宫的通路 ————1、把墙打通,让对面的格子成为迷宫的通路 ————2、把那个格子的邻墙加入列表 ——2、如果对面的格子已经是通路了,那就从列表里移除这面墙 */ enum Dir { Up, Down, Left, Right }; // 四周一步 int xx[] = { 0, 0, -1, 1 }; int yy[] = { -1, 1, 0, 0 }; // 四周两步 int x2[] = { 0, 0, -2, 2 }; int y2[] = { -2, 2, 0, 0 }; // 玩家坐标 int playerx; int playery; int SPX; int SPY; const int margin = 3; // 移动光标到xy位置 void gotoxy(int x, int y) { COORD coord = { (short)x, (short)y }; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord); } // 设置全地图为墙 void setAllWall() { for (int y = 0; y < height; ++y) for (int x = 0; x < width; ++x) map[y][x] = wall; } // 是否越界 bool isOutBounds(int x, int y) { return (x<0 || x >= width || y<0 || y >= height); } // 向四周探索 void explore(int x, int y) { // 遍历四个方向 for (int i = 0; i < 4; ++i) { // 顺着一条路走 for (int x1 = x, y1 = y; !isOutBounds(x1, y1) && map[y1][x1] == path; x1 += xx[i], y1 += yy[i]) { // 每走一个格子检查四周是否为通路 for (int fy = y1 - 1; fy <= y1 + 1; ++fy) for (int fx = x1 - 1; fx <= x1 + 1; ++fx) if (!isOutBounds(fx, fy) && fog[fy][fx]) fog[fy][fx] = false; } } } // 将坐标处的墙添加到待通墙中 void pushAroundWall(int x, int y) { // 遍历四个方向 for (int i = 0; i < 4; ++i) { int tx = x + xx[i]; int ty = y + yy[i]; if (isOutBounds(tx, ty)) continue; int wx = x + x2[i]; int wy = y + y2[i]; if (isOutBounds(wx, wy)) continue; // 只要是墙就加入列表 if (map[ty][tx] == wall) walls.push_back(pair, int>(pair( tx,ty ),i )); } } // 展示地图 void showMap() { int dx = sWidth / 2 - playerx; int dy = sHeight / 2 - playery; // 移动光标到最开始的位置 gotoxy(0, 0); // 遍历整个地图 for (int sy = 0; sy < sHeight; ++sy) { for (int sx = 0; sx < sWidth; ++sx) { //putchar(map[y][x]?'@':' '); int x = sx - dx; int y = sy - dy; const char *Symbol[5] = { "□", "▓", "▽", "☆", "◎" }; if (isOutBounds(x, y)) { printf("□"); continue; } if (x == playerx && y == playery) { printf("◎"); continue; } if (fog[y][x]) { printf("▓"); continue; } if (!walk[y][x]) { printf("▽"); continue; } if (map[y][x] == path) { printf("□"); continue; } if (map[y][x] == target) { printf("☆"); continue; } printf("▓"); continue; // 到此截断,后面为单字符地图时用 // int d = 0; // for (int i = 0; i < 4; ++i) // { // if (!isOutBounds(x + xx[i], y + yy[i]) && map[y + yy[i]][x + xx[i]] == wall) // d |= 1 << i; // } // const int up = 1; // const int down = 2; // const int left = 4; // const int right = 8; // char ch = 0; // switch (d) // { // case 0: // ch = '&'; // break; // //case up: // //case down: // case up | down: // ch = '|'; // break; // //case left: // //case right: // case left | right: // ch = '-'; // break; // default: // ch = '+'; // } // putchar(ch); } cout << endl; } //gotoxy(sWidth/2+1, sHeight/2+1); //putchar('A'); } // 生成地图算法,参数为起始点坐标 void generate(int cx, int cy) { // 首先将地图全部设置为墙 setAllWall(); // 填满迷雾,清空已经走过的路径 for (int i = 0; i < width*height; ++i) *((bool*)fog + i) = *((bool*)walk + i) = true; //设置玩家的坐标 playerx = cx; playery = cy; // 从起点开始,将四周的墙壁添加到待凿列表中 pushAroundWall(cx, cy); // 把这个点变成路 map[cy][cx] = path; // 只要还有待凿的墙,就一直循环 while (!walls.empty()) { // 随机找个待凿的墙 int index = rand() % walls.size(); int wx = walls[index].first.first; int wy = walls[index].first.second; int d = walls[index].second; // 如果是墙,打穿,将下一个点四周的墙壁加入待凿列表 if (map[wy + yy[d]][wx + xx[d]] == wall) { map[wy][wx] = path; map[wy + yy[d]][wx + xx[d]] = path; pushAroundWall(wx + xx[d], wy + yy[d]); } // 打穿后,将该墙移除待凿列表 walls.erase(walls.begin() + index); } map[height-2][width-2] = target; // 展开迷雾 explore(playerx, playery); } // 玩家移动,参数是移动的方向 bool playerMove(Dir dir) { if (0 > dir || dir >= 4) return false; int tx = playerx + xx[dir]; int ty = playery + yy[dir]; if (isOutBounds(tx, ty)) return false; if (map[ty][tx] == wall) return false; if (map[ty][tx] == target) { system("cls"); cout << "游戏胜利!" << endl; system("pause"); return true; } // 只有是路的时候才可以移动 if (map[ty][tx] == path) { playerx = tx, playery = ty; walk[ty][tx] = false; } // 移动完后再次探索迷雾 explore(playerx, playery); return false; } // 每一帧执行更新 bool updata() { char ch = getch(); bool win = false; switch (ch) { case 'w': win = playerMove(Dir::Up); break; case 's': win = playerMove(Dir::Down); break; case 'a': win = playerMove(Dir::Left); break; case 'd': win = playerMove(Dir::Right); break; case 'q': exit(0); break; case 'r': return false; break; } return !win; } int main() { // 设置种子 srand((unsigned int)time(0)); printf("WSAD移动,Q退出,R重开"); system("pause"); while (true) { // 生成地图 generate(1, 1); // 游戏循环 do { // 输出地图 showMap(); } while (updata()); } return 0; }