- //迷宫Demo, 计算机图形学OpenGL版本案例2.5
- //构造迷宫的关键是,模拟算法:
- //在R x C的格子上放一只老鼠,随机朝四周打洞,
- //如果格子的四个墙壁都完好,则该格子的一个墙壁会被老鼠咬破,
- //所有的格子处理一遍后,再处理一下出口和入口即可.
- #include <windows.h>
- #define GLEW_STATIC
- #include "GL/glew.h"
- #include "GL/glut.h"
- #include <iostream>
- #include <cstring>
- #include <fstream>
- #include <cstdio>
- #include <cstdlib>
- #include <vector>
- #include <stack>
- #include <ctime>
- using namespace std;
- static bool initialize();
- static void render();
- static void reshape(int width, int height);
- static void mouse(int button, int state, int x, int y);
- static void keyboard(unsigned char key, int x, int y);
- static void idle();
- //迷宫的行和列数
- static int R, C;
- //north表示迷宫格子北面(上)的墙(0-可通行,1-墙), east表示迷宫东面的墙状态,
- //record表示迷宫格子本身是否被处理过,1-没有处理,0-处理过
- static char **ppNorth, **ppEast, **ppRecord;
- //二维向量
- template<typename Type>
- struct Vector2 {
- Vector2(Type _x = Type(0), Type _y = Type(0)):x(_x), y(_y) {}
- Type x, y;
- };
- typedef Vector2<int> Int2;
- //单个格子边长
- const static int GSZ = 10;
- //用于绘制的线段顶点
- static vector<Int2> vecLines;
- //创建迷宫
- static void createMaze();
- int main(int argc, char *argv[])
- {
- glutInit(&argc, argv);
- glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
- glutInitWindowPosition(50, 50);
- glutInitWindowSize(800, 600);
- glutCreateWindow("Template-Glut");
- GLenum err = glewInit();
- if(err != GLEW_OK) {
- cerr << "glew init fail! err-str: " << glewGetErrorString(err) << endl;
- system("pause");
- exit(-1);
- }
- glutReshapeFunc(reshape);
- glutMouseFunc(mouse);
- glutKeyboardFunc(keyboard);
- glutIdleFunc(idle);
- glutDisplayFunc(render);
- if(!initialize()) {
- cerr << "initialize application fail!" << endl;
- system("pause");
- exit(-1);
- }
- glutMainLoop();
- system("pause");
- return 0;
- }
- void createMaze()
- {
- //申请迷宫内存表示
- ppNorth = new char*[R + 1];
- ppEast = new char*[R + 1];
- ppRecord = new char*[R + 2];//给迷宫设置一个外围
- for(int i = 0; i <= R; i++){
- ppNorth[i] = new char[C+1];
- ppEast[i] = new char[C+1];
- ppRecord[i] = new char[C+2];
- for(int j = 0; j <= C; j++) {
- ppNorth[i][j] = 1;
- ppEast[i][j] = 1;
- ppRecord[i][j] = 1;
- }
- }
- ppRecord[R + 1] = new char[C+2];
- for(int i = 0; i <= R + 1; i++) ppRecord[i][0] = ppRecord[i][C+1] = 0;
- for(int i = 0; i <= C + 1; i++) ppRecord[0][i] = ppRecord[R + 1][i] = 0;
- //L U R D
- Int2 dir[4] = {
- Int2(0, -1),
- Int2(1, 0),
- Int2(0, 1),
- Int2(-1, 0)
- };
- vector<int> vg;//记录格子(左上右下)可以打洞的方向
- stack<Int2> sk;//DFS-遍历栈
- //生成老鼠所在的格子
- int x = rand() % R + 1;
- int y = rand() % C + 1;
- sk.push(Int2(x, y));
- while(!sk.empty()) {
- Int2 pos = sk.top();
- vg.clear();
- for(int i = 0; i < 4; i++) {
- int r = pos.x + dir[i].x;
- int c = pos.y + dir[i].y;
- //可以打洞
- if(ppRecord[r][c]) vg.push_back(i);
- }
- if(vg.size() <= 0) {
- //该格子四周都不需要打洞
- sk.pop();
- continue;
- }else {
- //随机一个方向打洞
- int i = vg[rand() % vg.size()];
- ppRecord[pos.x + dir[i].x][pos.y + dir[i].y] = 0;
- ppRecord[pos.x][pos.y] = 0;
- switch(i) {
- case 0:
- ppEast[pos.x][pos.y - 1] = 0; break;
- case 1:
- ppNorth[pos.x][pos.y] = 0; break;
- case 2:
- ppEast[pos.x][pos.y] = 0; break;
- case 3:
- ppNorth[pos.x - 1][pos.y] = 0; break;
- }
- if(vg.size() == 1) sk.pop();
- sk.push(Int2(pos.x + dir[i].x, pos.y + dir[i].y));
- }
- }
- //最外层墙壁打洞,(生成出口)
- ppNorth[R][C] = 0;
- ppEast[1][0] = 0;
- }
- bool initialize()
- {
- //设置清除颜色为黑色
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- //Note:
- //opengl的默认视点eye-(0, 0, 0), 默认视线方向(0, 0, -1), 默认眼睛上方向(0, 1, 0)
- //默认为正投影, 范围:x-(-1, 1), y-(-1, 1)
- srand(time(0));
- cout << "please input maze row and column:" << endl;
- cin >> R >> C;
- //TODO, check R and C
- createMaze();
- //设置正投影
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluOrtho2D(0, 800, 0, 600);
- glViewport(0, 0, 800, 600);
- //构造迷宫线段
- int x0 = 400 - GSZ * C / 2;
- int y0 = 300 - GSZ * R / 2;
- //横向线段
- for(int i = 0; i <= R; i++)
- for(int j = 1; j <= C; j++) {
- if(ppNorth[i][j]) {
- Int2 a, b;
- a.x = (j - 1) * GSZ + x0;
- a.y = i * GSZ + y0;
- b.x = j * GSZ + x0;
- b.y = i * GSZ + y0;
- vecLines.push_back(a);
- vecLines.push_back(b);
- }
- }
- //竖向线段
- for(int i = 1; i <= R; i++)
- for(int j = 0; j <= C; j++) {
- if(ppEast[i][j]) {
- Int2 a, b;
- a.x = j * GSZ + x0;
- a.y = (i - 1) * GSZ + y0;
- b.x = j * GSZ + x0;
- b.y = i * GSZ + y0;
- vecLines.push_back(a);
- vecLines.push_back(b);
- }
- }
- return true;
- }
- void reshape(int width, int height)
- {}
- void idle()
- {}
- void render()
- {
- glClear(GL_COLOR_BUFFER_BIT);
- //设置红色线段
- glColor3f(1, 0, 0);
- glBegin(GL_LINES);
- for(int i = 0; i < vecLines.size(); i++)
- glVertex2i(vecLines[i].x, vecLines[i].y);
- glEnd();
- glFlush();
- glutSwapBuffers();
- }
- void mouse(int button, int state, int x, int y)
- {}
- void keyboard(unsigned char key, int x, int y)
- {}
- //该片段来自于http://www.codesnippet.cn/detail/2310201513881.html
来源: http://www.codesnippet.cn/detail/2310201513881.html