迷宫的创建及布局
//绘制迷宫最小单元的(矩形)的长和宽20,即正方形
#define size 20
using namespace std;
MainWindow::MainWindow(QWidget *parent)
: QWidget(parent)
{
//调整窗口中其它控件的大小
int n = 31;
/*新建迷宫*/
m = new MAZE();
m->set_n(n);
//迷宫初始化
m->mazeInit();
//迷宫绘制
m->print();
//设置窗口标题
this->setWindowTitle("迷宫");
//设置窗口固定大小
this->setFixedSize((n+9)*size,n*size);
//鼠标事件触发的焦点
this->setFocus(Qt::MouseFocusReason);
//对话框或控件的调色板,
//它管理着控件或窗体的所有颜色信息,
//每个窗体或控件都包含一个QPalette对象,
//在显示时按照它的QPalette对象中对各部分各状态下的颜色的描述来进行绘制
QPalette pa;
//前景颜色为黑色
pa.setColor(QPalette::WindowText, Qt::black);
//字体
QFont ft;
ft.setPointSize(14);
ql_shuru = new QLabel(this);
ql_shuru->setText("迷宫大小");
ql_shuru->setPalette(pa);
ql_shuru->setFont(ft);
ql_shuru->setGeometry((n+2)*size, 2*size, 100, 40);
infile = new QLineEdit(this);
infile->setText("10");
infile->setGeometry((n+2)*size, 4*size, 90, 20);
queding = new QPushButton(this);
queding->setText("创建");
queding->setGeometry((n+3)*size, 6*size, 60,40);
zhaolu = new QPushButton(this);
zhaolu->setText("找最短路");
zhaolu->setGeometry((n+2)*size, (n-6)*size, 100,40);
ql_bushu = new QLabel(this);
ql_bushu->setText("最短步数");
ql_bushu->setGeometry((n+1)*size, (n-4)*size, 110,40);
ql_bushuOut = new QLabel(this);
ql_bushuOut->setText("0");
ql_bushuOut->setGeometry((n+7)*size, (n-4)*size, 60,40);
connect(queding,SIGNAL(clicked()),this,SLOT(startMaze()));
connect(zhaolu,SIGNAL(clicked()),this,SLOT(startBFS()));
}
MainWindow::~MainWindow()
{
}
void MainWindow::paintEvent(QPaintEvent *)
{
QPainter painter(this);
int n = m->get_n();
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
//绘制迷宫围墙
if(m->maze[i][j] ==1){
painter.setPen(Qt::darkCyan);
painter.setBrush(QBrush(Qt::darkCyan,Qt::SolidPattern));
painter.drawRect(QRect(j*size,i*size,size,size));
}
//绘制你当前的位置,用图片表示
else if(m->maze[i][j] == 2){
painter.drawPixmap(j*20,i*20,20,20,QPixmap(":/new/海绵.jpg").scaled(20,20));
}
//绘制迷宫终点,用图片表示
else if(m->maze[i][j] == 3){
painter.setPen(Qt::red);
painter.setBrush(QBrush(Qt::red,Qt::SolidPattern));
painter.drawRect(QRect(j*size,i*size,size,size));
painter.drawPixmap(j*20,i*20,20,20,QPixmap(":/new/蟹堡王.JPEG").scaled(20,20));
}
//绘制迷宫过道
else if(m->maze[i][j] == 0){
painter.setPen(Qt::white);
painter.setBrush(QBrush(Qt::white,Qt::SolidPattern));
painter.drawRect(QRect(j*size,i*size,size,size));
}
//绘制路径提示,用图片表示
else if(m->maze[i][j] == 6){
painter.drawPixmap(j*20,i*20,20,20,QPixmap(":/new/海绵.jpg").scaled(20,20));
}
}
}
}
void MainWindow::keyPressEvent(QKeyEvent *e)
{
if(bfs_fg){
m->recoverPath();
bfs_fg = false;
ql_bushuOut->setText("0");
update();
}
int tx = X, ty = Y;
int n = m->get_n();
if(e->key()==87||e->key()==16777235)//上
{
if(X>0 && m->maze[X-1][Y] != 1)
{
X=X-1;
}
}
else if(e->key()==83||e->key()==16777237)//下
{
if(X<n-1 && m->maze[X+1][Y] != 1)
{
X=X+1;
}
}
else if(e->key()==65||e->key()==16777234)//左
{
if(Y>0 && m->maze[X][Y-1] != 1)
{
Y=Y-1;
}
}
else if(e->key()==68||e->key()==16777236)//右
{
if(Y<n-1 && m->maze[X][Y+1] != 1)
{
Y=Y+1;
}
}
int tmp = m->maze[X][Y];
if(tmp == 3){
QMessageBox::information(this,"提示","到达终点",QMessageBox::Yes);
}else{
m->maze[X][Y] = m->maze[tx][ty];
m->maze[tx][ty] = tmp;
}
update();
}
void MainWindow::startMaze()//创建迷宫
{
//获取设置的迷宫大小
int n = infile->text().toInt();
//迷宫最小为15
if(n<15)n = 15;
//迷宫最大为100
if(n>100)n = 100;
//迷宫大小为奇数,不是奇数则 加一为偶数
if(n%2 == 0)n++;
//重新设置窗口大小,使之可以绘制迷宫地图
this->setFixedSize((n+9)*size,n*size);
//重置控件
ql_shuru->setGeometry((n+2)*size, 2*size, 100, 40);
infile->setGeometry((n+2)*size, 4*size, 90, 20);
queding->setGeometry((n+3)*size, 6*size, 60,40);
zhaolu->setGeometry((n+2)*size, (n-6)*size, 100,40);
ql_bushu->setGeometry((n+1)*size, (n-4)*size, 110,40);
ql_bushuOut->setText("0");
ql_bushuOut->setGeometry((n+7)*size, (n-4)*size, 60,40);
//设置迷宫大小
m->set_n(n);
//初始化迷宫
m->mazeInit();
//初始化人物当前位置
X = 1, Y = 0;
//鼠标事件触发的焦点
this->setFocus(Qt::MouseFocusReason);
//重绘地图,会调用void MainWindow::paintEvent(QPaintEvent *)
update();
}
int MAZE::searchPath(int x, int y)
{
//往四个方向挖
static int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
int zx = x*2;
int zy = y*2;
int next, turn, i;
maze[zx][zy] = 0;
//设置turn为[0, 4]之间的任意一个奇数
turn = rand()%2 ? 1 : 3;
//next=rand()%4 取值范围[0, 4),
//next=(next+turn)%4 每个循环在奇数和偶数之间切换,[0, 4)遍历一遍
//在迷宫地图里,随机选一个地方,开始挖路,4次循环,往4个方向挖
for(i=0, next=rand()%4; i<4; ++i, next=(next+turn)%4)
//搜索当前位置的第二步,如果是围墙,这将但前位置的沿着指定方向的下一步设置为路
//这样做的原因: 防止打穿最外层的围墙, 防止造成回环
if(maze[zx+2*dir[next][0]][zy+2*dir[next][1]] == 1)
{
maze[zx+dir[next][0]][zy+dir[next][1]] = 0;
searchPath(x+dir[next][0], y+dir[next][1]);
}
return 0;
}
void MAZE::getPath(int pos)
{
while(pos != -1)
{
path[len_path].x = q[pos].x;
path[len_path].y = q[pos].y;
len_path++;
pos = q[pos].pre;
}
}
void MAZE::bfs()
{
int front, tail, sx, sy;
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
if(maze[i][j] == 2)
{
sx = i; sy = j;
}
front = tail = 0;
q[tail].x = sx;
q[tail].y = sy;
q[tail].pre = -1;
tail++;
int x, y, nx, ny;
bool fg = false;
while(front < tail)
{
x = q[front].x;
y = q[front].y;
for(int i = 0; i < 4; i++)
{
nx = x+dx[i];
ny = y+dy[i];
if(nx>=0&&nx<n&&ny>=0&&ny<n&&maze[nx][ny]==0)
{
maze[nx][ny] = 5;
q[tail].x = nx;
q[tail].y = ny;
q[tail].pre = front;
tail++;
}
if(maze[nx][ny] == 3){
q[tail].x = nx;
q[tail].y = ny;
q[tail].pre = front;
tail++;
fg = true;
len_path = 0;
path[len_path].x = nx;
path[len_path].y = ny;
len_path++;
getPath(front);
}
}
if(fg)break;
front++;
}
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
if(maze[i][j] == 5)
maze[i][j] = 0;
}
成果展示
自动寻路