计算机软件技术实习 迷宫游戏(二)

迷宫的创建及布局

//绘制迷宫最小单元的(矩形)的长和宽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;
}

成果展示

自动寻路

                   

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值