实验-源码

①计算器

#include "widget.h"
#include "ui_widget.h"
#include <stdio.h>
#include <string.h>
#include <QStack>
#include <QMessageBox>
 
 
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setWindowIcon(QIcon(":/1.jpeg"));
    this->setWindowTitle("计算器");
 
    QFont g("仿宋",15);
    ui->lineEdit->setFont(g);
 
}
 
Widget::~Widget()
{
    delete ui;
}
 
 
void Widget::on_oneButton_clicked()
{
    expression += "1";
    ui->lineEdit->setText(expression);
}
 
void Widget::on_twoButton_clicked()
{
    expression += "2";
    ui->lineEdit->setText(expression);
}
 
void Widget::on_threeButton_clicked()
{
    expression += "3";
    ui->lineEdit->setText(expression);
}
 
void Widget::on_fourButton_clicked()
{
    expression += "4";
    ui->lineEdit->setText(expression);
}
 
void Widget::on_fiveButton_clicked()
{
    expression += "5";
    ui->lineEdit->setText(expression);
}
 
void Widget::on_sixButton_clicked()
{
    expression += "6";
    ui->lineEdit->setText(expression);
}
 
void Widget::on_sevenButton_clicked()
{
    expression += "7";
    ui->lineEdit->setText(expression);
}
 
void Widget::on_eightButton_clicked()
{
    expression += "8";
    ui->lineEdit->setText(expression);
}
 
void Widget::on_nineButton_clicked()
{
    expression += "9";
    ui->lineEdit->setText(expression);
}
 
void Widget::on_zeroButton_clicked()
{
    expression += "0";
    ui->lineEdit->setText(expression);
}
 
void Widget::on_zuokuohao_clicked()
{
    expression += "(";
    ui->lineEdit->setText(expression);
}
 
void Widget::on_youkuohao_clicked()
{
    expression += ")";
    ui->lineEdit->setText(expression);
}
 
void Widget::on_chu_clicked()
{
    expression += "/";
    ui->lineEdit->setText(expression);
}
 
void Widget::on_cheng_clicked()
{
    expression += "*";
    ui->lineEdit->setText(expression);
}
 
void Widget::on_jian_clicked()
{
    expression += "-";
    ui->lineEdit->setText(expression);
}
 
void Widget::on_jia_clicked()
{
    expression += "+";
    ui->lineEdit->setText(expression);
}
 
 
 
//判断表达式是否合法
bool isArithmeticExpressionValid(const QString &expression) {
    QStack<QChar> stack;
 
    for (const QChar &ch : expression) {
        if (ch == '(') {
            stack.push(ch);
        } else if (ch == ')') {
            if (stack.isEmpty() || stack.pop() != '(') {
                return false; // 括号不匹配,表达式非法
            }
        }
    }
 
    return stack.isEmpty(); // 如果栈为空,表示所有括号都匹配,表达式合法
}
 
 
//判断是否为括号
bool isPra(char c)
{
    if(c=='('||c==')')
        return true;
    else
        return false;
}
 
 
//获得符号的优先性
int getPri(char c)
{
    switch(c)       //循环判断
    {
    case '+':
    case '-':
        return 0;	//如果是加减,返回0
        break;
    case '*':
    case '/':
        return 1;	//如果是乘除,返回1
        break;
    case '(':
    case ')':
        return -1;  //注意,这里将括号设为最低优先级,因此括号不会被弹出,除非遇到右括号
        break;
    }
}
 
 
void check(char c, QStack<char>& bbb, QQueue<char>& ccc)
{
    if(bbb.empty())
    {
        bbb.push(c);
        return;
    }
 
    if(isPra(c))
    {
        if(c=='(')
            bbb.push(c);
        else
        {
            //弹出所有元素直到遇到左括号
            while(bbb.top()!='(')
            {
                char ch = bbb.top();
                ccc.push_back(ch);
                bbb.pop();
            }
 
            //当遇到左括号时,弹出但不加入ccc(后缀表达式中)
            bbb.pop();
        }
    }
    else	//如果不是括号
    {
        //取出栈顶元素,与当前符号进行优先性比较
        char sym = bbb.top();
 
        //比较两符号的优先性
        if(getPri(c)<=getPri(sym))
        {
            //如果c的优先性比栈顶符号小或等于,弹出栈顶元素
            bbb.pop();
            //并将其压入ccc(后缀表达式)中
            ccc.push_back(sym);
            //递归调用check,比较当前符号c与下一个栈顶符号的优先性
            check(c,bbb,ccc);
        }
        else
        {
            //如果c比栈顶符号优先级大,那将c压入bbb(操作符栈)中
            bbb.push(c);
        }
    }
}
 
//从aaa中取出元素,分配元素到bbb和ccc中
void allocate(QQueue<char>& aaa, QStack<char>& bbb, QQueue<char>& ccc)
{
    while(!aaa.empty())
    {
        char c = aaa.front();
        aaa.pop_front();
 
        if(c>='0'&&c<='9')
        {
            ccc.push_back(c);
        }
        else
        {
            //调用check函数,针对不同情况作出不同操作
            check(c,bbb,ccc);
        }
 
    }
 
    //如果输入结束,将bbb的元素全部弹出,加入后缀表达式中
    while(!bbb.empty())
    {
        char c = bbb.top();
        ccc.push_back(c);
        bbb.pop();
    }
}
 
 
 
 
 
//计算后缀表达式
void calculate(QQueue<char>& ccc, QStack<int>& ddd)
{
    while(!ccc.empty())
    {
        char c = ccc.front();
        ccc.pop_front();
 
        //如果是操作数,压入栈中
        if(c>='0'&&c<='9')
        {
            //减去'0'得出偏移值,即为真实数值(如果直接转换成int,结果不对,因为char 转换为int是其编码值,例如'1'的编码值为49
            int op = c-'0';
            ddd.push(op);
        }
        else	 //如果是操作符,从栈中弹出元素进行计算
        {
            int op1 = ddd.top();
            ddd.pop();
            int op2 = ddd.top();
            ddd.pop();
            switch(c)
            {
            case '+':
                ddd.push(op2+op1);
                break;
            case '-':
                ddd.push(op2-op1);
                break;
            case '*':
                ddd.push(op2*op1);
                break;
            case '/':
                ddd.push(op2/op1);  //注意是op2(op)op1而不是op1(op)op2
                break;
            }
        }
    }
}
 
 
void Widget::on_deng_clicked()
{
    QString temp = ui->lineEdit->text();
    if(!isArithmeticExpressionValid(temp))
    {
        QMessageBox::warning(0, "", "表达式非法");
        return;
    }
    QQueue<char> aaa;  //盛放中缀表达式
    QStack<char> bbb;  //盛放操作符
    QQueue<char> ccc;  //盛放后缀表达式
    QStack<int> ddd;	//计算后缀表达式的辅助栈
 
 
    //把QString转换成char *
    QByteArray ba;
    ba.append(expression);
 
    //   strcpy(aaa, ba.data());
 
    for(int i = 0; i<ba.size(); i++)
    {
        aaa.push_back(ba.at(i));
    }
 
 
    //从aaa中取出元素,分配元素到bbb和ccc中
    allocate(aaa,bbb,ccc);
 
    //计算后缀表达式
    calculate(ccc,ddd);
 
 
 
    int num = ddd.top();
    QString f = QString::number(num,10);
    ui->lineEdit->setText(f);
    expression=f;
 
    ui->historytext->setText(ui->historytext->toPlainText() + "\n" + temp + " = " + f);
 
 
}
 
 
 
void Widget::on_clear_clicked()
{
    expression.chop(1);
    ui->lineEdit->setText(expression);
}
 
 
 
 
void Widget::on_history_clicked()
{
 
}
 

②贪吃蛇

#include "widget.h"
#include "ui_widget.h"
 
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    resize(600,400);
    setStyleSheet("QWidget{background:pink}");
    snake.append(QRectF(200,200,snakeNodeWidth,snakeNodeHeight));
    addTopRectF();
    addTopRectF();
 
    // 设置第一个奖励
    rewardNode.append(QRectF(400,200,snakeNodeWidth,snakeNodeWidth));
 
    timer = new QTimer;
    connect(timer, SIGNAL(timeout()),this,SLOT(timeOut()));
 
    rewardTimer = new QTimer;
    connect(rewardTimer,SIGNAL(timeout()),this,SLOT(rewardTimeOut()));
 
    this->setWindowTitle("贪吃兔小游戏");
    this->setWindowIcon(QIcon(":/1.jpeg"));
 
 
}
 
 
Widget::~Widget()
{
    delete ui;
}
 
 
void Widget::timeOut()
{
    int flage = 1;
    for(int i=0; i<rewardNode.length(); i++){
        if(rewardNode.at(i).contains(snake.at(0).topLeft()+QPointF(snakeNodeWidth/2,snakeNodeHeight/2)))
        {
            flage++; //吃一个奖励,蛇身加长一段
            rewardNode.removeAt(i);
            break;
        }
    }
    while(flage--){
        switch (moveFlage) {
        case Up:
            addTopRectF();
            break;
        case Down:
            addDownRectF();
            break;
        case Right:
            addRightRectF();
            break;
        case Left:
            addLeftRectF();
            break;
        default:
            break;
        }
    }
    deleteLastRectF();
 
    update();
}
 
void Widget::rewardTimeOut()
{
    qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
    if(rewardNode.length() > 5)
    {
        rewardNode.removeAt(qrand()%3);
    }
    rewardNode.append(QRectF(qrand()%(this->width()/20)*20,qrand()%(this->height()/20)*20,snakeNodeWidth,snakeNodeWidth));
    if(qrand()%3 == 3){
        rewardNode.append(QRectF(qrand()%(this->width()/20)*20-5,qrand()%(this->height()/20)*20-5,snakeNodeWidth*2,snakeNodeWidth*2));
    }
}
 
// 向上移动
void Widget::addTopRectF()
{
    if(snake.at(0).y()-snakeNodeHeight < 0)//当蛇碰到窗口的顶时
    {
        snake.insert(0,QRectF(QPointF(snake.at(0).x(),this->height()-snakeNodeHeight),
                              QPointF(snake.at(0).x()+snakeNodeWidth,this->height())));
     }
     else
     {
        snake.insert(0,QRectF(snake.at(0).topLeft()+QPointF(0,-snakeNodeHeight),snake.at(0).topRight()));
 
    }
}
 
// 向下移动
void Widget::addDownRectF()
{
    if(snake.at(0).y()+snakeNodeHeight*2 > this->height())//当蛇碰到窗口的底时
    {
        snake.insert(0,QRectF(QPointF(snake.at(0).x(),snakeNodeHeight),
                              QPointF(snake.at(0).x()+snakeNodeWidth,0)));
    }
    else
    {
        snake.insert(0,QRectF(snake.at(0).bottomLeft(),snake.at(0).bottomRight()+QPointF(0,snakeNodeHeight)));
    }
}
 
// 向左移动
void Widget::addLeftRectF()
{
    if(snake.at(0).x()-snakeNodeWidth < 0)//当蛇碰到窗口的左边界时
    {
        snake.insert(0,QRectF(QPointF(this->width()-snakeNodeWidth,snake.at(0).y()),
                              QPointF(this->width(),snake.at(0).y()+snakeNodeHeight)));
    }
    else
    {
        snake.insert(0,QRectF(snake.at(0).topLeft()+QPointF(-snakeNodeWidth,0),snake.at(0).bottomLeft()));
    }
}
 
// 向右移动
void Widget::addRightRectF()
{
    if(snake.at(0).x()+snakeNodeWidth*2 > this->width())//当蛇碰到窗口的右边界时
    {
        snake.insert(0,QRectF(QPointF(0,snake.at(0).y()),
                              QPointF(snakeNodeWidth,snake.at(0).y()+snakeNodeHeight)));
    }
    else
    {
        snake.insert(0,QRectF(snake.at(0).topRight(),snake.at(0).bottomRight()+QPointF(snakeNodeWidth,0)));
    }
}
 
// 删除结尾数据
void Widget::deleteLastRectF()
{
    snake.removeLast();
}
 
void Widget::startTheGame()
{
    timer->start(time);
    rewardTimer->start(time2*30);
    gameStart = false;
}
 
void Widget::endTheGame()
{
    timer->stop();
    rewardTimer->stop();
    gameStart = true;
}
 
// 绘图
void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    QPen pen;
    QBrush brush;
    QFont fontg ( "黑体", 20, 50);
 
    painter.setRenderHint(QPainter::Antialiasing);
    pen.setColor(Qt::blue);
    brush.setColor(Qt::white);
    brush.setStyle(Qt::SolidPattern);
    painter.setPen(pen);
    painter.setBrush(brush);
 
 
    for(int i=0; i<snake.length(); i++){
        //painter.drawRect(snake.at(i));
        painter.drawImage(snake.at(i), QImage(":/6.png"), QRectF(0,0,1076,909));
    }//画蛇
 
    brush.setColor(Qt::yellow);
    painter.setBrush(brush);
 
    for(int i=0; i<rewardNode.length(); i++){
       //painter.drawEllipse(rewardNode.at(i));
       painter.drawImage(rewardNode.at(i), QImage(":/4.png"), QRectF(0,0,750,1024));
    }//画奖励
 
    pen.setColor(Qt::black);
    painter.setPen(pen);
    painter.setFont(fontg);
//    painter.drawText(240,40,QString("得分:")+QString("%1").arg());
 
    emit changeScore(snake.length()-3);
 
    if(snakeStrike()){
        QFont font("幼圆",30,QFont::ExtraLight,false);
        painter.setFont(font);
        painter.drawText((this->width()-300)/2,(this->height()-30)/2,QString("游戏结束"));
        timer->stop();
        rewardTimer->stop();
        gameOver = true;
    }
 
    QWidget::paintEvent(event);
}
 
void Widget::keyPressEvent(QKeyEvent *event)
{
    switch(event->key()){
    case Qt::Key_Up:
        if(moveFlage != Down){
            moveFlage = Up;
        }
        break;
    case Qt::Key_Down:
        if(moveFlage != Up){
            moveFlage = Down;
        }
        break;
    case Qt::Key_Right:
        if(moveFlage != Left){
            moveFlage = Right;
        }
        break;
    case Qt::Key_Left:
        if(moveFlage != Right){
            moveFlage = Left;
        }
        break;
    case Qt::Key_Enter:
    case Qt::Key_Return:
        if(gameOver){
            snake.clear();
            rewardNode.clear();
            moveFlage = Up;
            snake.append(QRectF(200,500,snakeNodeWidth,snakeNodeHeight));
            addTopRectF();
            addTopRectF();
 
            //首先生成一个奖励节点
            rewardNode.append(QRectF(100,100,snakeNodeWidth,snakeNodeWidth));
            timer->start(time);
            rewardTimer->start(time2*30);
            gameOver = false;
        }
        break;
    case Qt::Key_Space:
        if(gameStart && !gameOver){
            timer->start(time);
            rewardTimer->start(time2*30);
            gameStart = false;
        }else if(!gameStart && !gameOver){
            timer->stop();
            rewardTimer->stop();
            gameStart = true;
        }
        break;
    default:
        break;
    }
}
 
// 判断是否相撞
bool Widget::snakeStrike()
{
    for(int i=0; i<snake.length(); i++)
    {
        for(int j=i+1; j<snake.length(); j++)
        {
            if(snake.at(i) == snake.at(j))
            {
                return true;
            }
        }
    }
    return false;
}
 
 
 
 

③基于A*算法的迷宫游戏

#include "play_maze.h"
#include "ui_play_maze.h"
#include <QDebug>
 
 
play_maze::play_maze(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::play_maze)
{
    ui->setupUi(this);
    this->setWindowIcon(QIcon("D:/matlab/maze_play/img/1.jpeg"));
 
    control_direction=2;//往右
 
    QDesktopWidget *deskdop = QApplication::desktop();
    move((deskdop->width() - this->width())/2, (deskdop->height() - this->height())/2);
 
 
    control_LEFT.load("D:/matlab/maze_play/img/6.png");
    control_RIGHT.load("D:/matlab/maze_play/img/6.png");
    target.load("D:/matlab/maze_play/img/4.png");
    road.load("D:/matlab/maze_play/img/7.jpg");
    wall.load("D:/matlab/maze_play/img/8.png");
 
}
 
play_maze::~play_maze()
{
    delete ui;
}
 
void play_maze::on_get_row_valueChanged(int arg1)
{
    pre_maze_row = arg1;
    flag_get_row = true;
}
 
void play_maze::on_get_col_valueChanged(int arg1)
{
    pre_maze_col = arg1;
    flag_get_col = true;
}
 
void play_maze::on_creat_maze_clicked()//创建迷宫
{
    if(flag_click){
        return;
    }
    if(flag_get_row){
        maze_row=pre_maze_row;
    }
    else{
        maze_row=10;
    }
    if(flag_get_col){
        maze_col=pre_maze_col;
    }
    else{
        maze_col=10;
    }
    flag_success=false;
 
    //获取行列值
    control_X=1;
    control_Y=1;
    target_X=maze_row-3;
    target_Y=maze_col-3;
    //qDebug()<<target_X<<" "<<target_Y<<endl;
    //    maze=new point *[maze_row];
    //    for(int i=0;i<maze_row;i++){
    //        maze[i]=new point[maze_col];
    //    }
 
    for(int i=0;i<maze_row;i++){
        for(int j=0;j<maze_col;j++){
            maze[i][j].i=i;
            maze[i][j].j=j;
            maze[i][j].state=0;
        }
    }
    int max;
    if(maze_row>=maze_col)
        max=maze_row;
    else
        max=maze_col;
 
    maze_cell_size=650/max;
 
    startTimer(5*650/max);//启动定时器,定时器的间隔为5*650/max毫秒,用于生成迷宫的动画效果
 
    build_maze_stack.clear();
 
    int i=3,j=3;
    maze[i][j].state=1;
 
    point temp;
    temp.i=i;
    temp.j=j;
    temp.state=1;
    bool up=false,down=false,left=false,right=false;
 
    srand((unsigned)time(NULL));
 
    while(true){//利用prim算法生成迷宫
        temp.i=i;
        temp.j=j;
 
        int randnum=rand()%4;
 
        switch (randnum) {
        case 0: if(!up&&i>2&&maze[i-2][j].state==0){
                build_maze_stack.push(temp);
                maze[i-2][j].state=1;//表示当前格子和目标格子之间的墙壁被打通
                maze[i-1][j].state=1;//表示当前格子和相邻格子之间的墙壁被打通
                i=i-2;
                if(maze[i-1][j].state==0)//判断上邻居的状态
                    up=false; //再一次的新节点,如果又选中了case0,就可以重新进入!up
                else
                    up=true;
                if(maze[i+1][j].state==0)
                    down=false;
                else
                    down=true;
                if(maze[i][j-1].state==0)
                    left=false;
                else
                    left=true;
                if(maze[i][j+1].state==0)
                    right=false;
                else
                    right=true;
            }
            else{
                up=true;//将up设置为true,表示当前格子的上邻居,已经为通路不能打通
            }
            break;
        case 1: if(!down&&i<maze_row-3&&maze[i+2][j].state==0)
            {
                build_maze_stack.push(temp);
                maze[i+2][j].state=1;
                maze[i+1][j].state=1;
                i=i+2;
                if(maze[i-1][j].state==0)
                    up=false;
                else
                    up=true;
                if(maze[i+1][j].state==0)
                    down=false;
                else
                    down=true;
                if(maze[i][j-1].state==0)
                    left=false;
                else
                    left=true;
                if(maze[i][j+1].state==0)
                    right=false;
                else
                    right=true;
            }
            else{
                down=true;
            }
            break;
        case 2: if(!left&&j>2&&maze[i][j-2].state==0)
            {
                build_maze_stack.push(temp);
                maze[i][j-2].state = 1;
                maze[i][j-1].state = 1;
                j = j-2;
                if(maze[i-1][j].state == 0)
                    up = false;
                else
                    up = true;
                if(maze[i+1][j].state == 0)
                    down = false;
                else
                    down = true;
                if(maze[i][j-1].state == 0)
                    left = false;
                else
                    left = true;
                if(maze[i][j+1].state==0)
                    right = false;
                else
                    right = true;
            }
            else{
                left = true;
            }
            break;
        case 3: if(!right&&j<maze_col-3&&maze[i][j+2].state == 0)
            {
                build_maze_stack.push(temp);
                maze[i][j+2].state = 1;
                maze[i][j+1].state = 1;
                j = j+2;
                if(maze[i-1][j].state == 0)
                    up = false;
                else
                    up = true;
                if(maze[i+1][j].state == 0)
                    down = false;
                else
                    down = true;
                if(maze[i][j-1].state == 0)
                    left = false;
                else
                    left = true;
                if(maze[i][j+1].state == 0)
                    right = false;
                else
                    right = true;
            }
            else{
                right=true;
            }
            break;
        }
        if(up&&down&&left&&right)//全为通路
        {
            //如果四个方向都无法拆除,从堆栈中弹出一个位置作为当前位置
            if(!build_maze_stack.isEmpty()){
                i = build_maze_stack.top().i;
                j = build_maze_stack.top().j;
                build_maze_stack.pop();
                if(maze[i-1][j].state==0)
                    up=false;
                else
                    up=true;
                if(maze[i+1][j].state == 0)
                    down = false;
                else
                    down = true;
                if(maze[i][j-1].state == 0)
                    left = false;
                else
                    left = true;
                if(maze[i][j+1].state == 0)
                    right = false;
                else
                    right = true;
            }
            else//如果堆栈为空,表示迷宫生成完成
              { maze[1][1].state = 2;
                maze[maze_row-3][maze_col-3].state=3;
                creat_maze = true;
                for(int i=0; i < maze_row; i++)//防止生成迷宫后依旧显示路线
                    for(int j = 0; j < maze_col; j++){
                        path[i][j].state = 0;//在这里的状态表示父节点
                        path[i][j].i = i;//初始化路径数组path的状态和坐标
                        path[i][j].j = j;
                    }
                //迷宫已经创造完成
                return;
            }
        }
    }
 
}
 
 
bool cmp(point &a,point &b){//为了实现qsort函数的排序
    return a.state<b.state;
}
 
void play_maze::on_A_search_clicked()//A*算法
{
 
    if(flag_click||flag_success)//正在游戏或游戏成功
    {
        return;
    }
    if(!creat_maze)
    {
        return;
    }
    A_search.clear();
 
    qDebug()<<"begin find path";
 
    ftime.start();
 
    for(int i=0; i<maze_row; i++)
        for(int j=0; j<maze_col; j++){
            path[i][j].state=0;//在这里的状态表示父节点,1,2,3,4分别表示从上下左右发展过来,初始状态下,所有节点的父节点都设置为0,表示尚未确定
            path[i][j].i=i;    //记录起点旁边的点到终点的
            path[i][j].j=j; //path数组用于记录节点的状态(父节点)和坐标信息
        }
    //graph数组用于记录节点是否被搜索过
    for(int i=0; i<maze_row; i++)
        for(int j=0; j<maze_col; j++){
            if(maze[i][j].state==0)
                graph[i][j]=1;
            else
                graph[i][j]=0;//初始化未被搜索
        }
 
    QString message;
    int searchnum=0;//搜索节点次数
    point top;//初始化“起点”信息
    top.i=control_X;
    top.j=control_Y;
    top.state=abs(control_X-target_X)+abs(control_Y-target_Y);//点到终点的绝对距离
 
    A_search.push_back(top);//这里的状态什么也不表示
    graph[top.i][top.j]=0;
 
    while(!A_search.isEmpty())//寻路开始,直到vector A_search为空为止
    {
 
        qSort(A_search.begin(),A_search.end(),cmp);//使用qSort对A_search进行排序,依据是点到终点的估计值(状态)
 
        top=A_search.front(); //取出A_search的第一个节点作为当前节点top。
 
        A_search.pop_front();
 
 
        if(graph[top.i][top.j]==0)//判断当前节点是否已经被搜索过,如果是则跳过当前节点
        {
            searchnum+=1;
            if(maze[top.i][top.j].state==3){
                message="寻找成功!";
                QMessageBox::information(NULL, " ", message, QMessageBox::Yes, QMessageBox::Yes);
                break;
            }
            //path表示此点状态
            //并将真实路径代价计算进去,用graph存储
            //graph记录节点是否已经被搜索过,如果下方节点的状态为0,则表示该节点未被搜索
            switch (path[top.i][top.j].state) {
            case 1:
                graph[top.i][top.j]=graph[top.i-1][top.j]+1;//当前节点的路径长度设置为它的父节点路径长度加1
                break;
            case 2:
                graph[top.i][top.j]=graph[top.i+1][top.j]+1;
                break;
            case 3:
                graph[top.i][top.j]=graph[top.i][top.j-1]+1;
                break;
            case 4:
                graph[top.i][top.j]=graph[top.i][top.j+1]+1;
                break;
            default:
                graph[top.i][top.j]=1;
                break;
            }
            //将未访问的子节点放入开节点表A_search
            if((graph[top.i+1][top.j]==0)&&(maze[top.i+1][top.j].state!=0)){
                A_search.push_back(point(top.i+1,top.j,(graph[top.i][top.j]+1+abs(top.i+1-target_X)+abs(top.j-target_Y))));
                path[top.i+1][top.j].state=1;//表示从上发展而来
            //判断下方节点是否未被搜索过,并添加当前节点的下方节点到开节点表中,并更新路径节点数组的状态,以便进行后续的路径搜索
                //graph[top.i+1][top.j]=graph[top.i][top.j]+1;
            }
            if((graph[top.i-1][top.j]==0)&&(maze[top.i-1][top.j].state!=0)){
                A_search.push_back(point(top.i-1,top.j,(graph[top.i][top.j]+1+abs(top.i-1-target_X)+abs(top.j-target_Y))));
                path[top.i-1][top.j].state=2;//从下
 
                //graph[top.i-1][top.j]=graph[top.i][top.j]+1;
            }
            if((graph[top.i][top.j+1]==0)&&(maze[top.i][top.j+1].state!=0)){
                A_search.push_back(point(top.i,top.j+1,(graph[top.i][top.j]+1+abs(top.i-target_X)+abs(top.j+1-target_Y))));
                path[top.i][top.j+1].state=3;//从左
                //searchnum+=1;
                //graph[top.i][top.j+1]=graph[top.i][top.j]+1;
            }
            if((graph[top.i][top.j-1]==0)&&(maze[top.i][top.j-1].state!=0)){
                A_search.push_back(point(top.i,top.j-1,(graph[top.i][top.j]+1+abs(top.i-target_X)+abs(top.j-1-target_Y))));
                path[top.i][top.j-1].state=4;//从右
                //searchnum+=1;
                //graph[top.i][top.j-1]=graph[top.i][top.j]+1;
            }
 
 
        }
    }
    qDebug()<<"find the path!"<<endl;
 
}
 
 
void play_maze::keyPressEvent(QKeyEvent *event){//控制移动
    if(flag_click)
        return;
    switch (event->key()) {
    case Qt::Key_W: if((control_Y>0)&&((maze[control_X][control_Y-1].state==1)||(maze[control_X][control_Y-1].state==3))){
            path[control_X][control_Y-1].state=0;//这一段是防止到达终点依旧显示路线
            maze[control_X][control_Y-1].state=2;//将上方的路变成人
            maze[control_X][control_Y].state=1;//将原本的人变成路
            control_Y-=1;
        }
        break;
    case Qt::Key_S: if((control_Y<maze_col-1)&&((maze[control_X][control_Y+1].state==1)||(maze[control_X][control_Y+1].state==3))){
            path[control_X][control_Y+1].state=0;
            maze[control_X][control_Y+1].state=2;
            maze[control_X][control_Y].state=1;
            control_Y+=1;
        }
        break;
    case Qt::Key_A: if((control_X>0)&&((maze[control_X-1][control_Y].state==1)||(maze[control_X-1][control_Y].state==3))){
            path[control_X-1][control_Y].state=0;
            maze[control_X-1][control_Y].state=2;
            maze[control_X][control_Y].state=1;
            control_X-=1;
            control_direction=1;
        }
        break;
    case Qt::Key_D: if((control_X<maze_row-1)&&((maze[control_X+1][control_Y].state==1)||(maze[control_X+1][control_Y].state==3))){
            path[control_X+1][control_Y].state=0;
            maze[control_X+1][control_Y].state=2;
            maze[control_X][control_Y].state=1;
            control_X+=1;
            control_direction=2;
        }
        break;
 
    }
    //maze[target_X][target_Y].state=3;
    if((control_X==target_X)&&(control_Y==target_Y)&&creat_maze){
        maze[target_X][target_Y].state=2;
        //        for(int i=0; i<maze_row; i++)//这一段是防止到达终点依旧显示路线
        //            for(int j=0; j<maze_col; j++){
        //                path[i][j].state=0;//在这里的状态表示父节点,1,2,3,4分别表示从上下左右发展过来
        //                path[i][j].i=i;
        //                path[i][j].j=j;
        //            }
        target_X=0;
        target_Y=0;
        maze[target_X][target_Y].state=0;
        flag_success=true;
        QMessageBox::information(NULL, "游戏结束","兔子吃到了星星!", QMessageBox::Yes, QMessageBox::Yes);
    }
}
 
void play_maze::paintEvent(QPaintEvent *){//显示图像
    QPainter painter(this);
        QPen Pen(Qt::blue);
 
        for(int i=0;i<maze_row;i++){
            for(int j=0;j<maze_col;j++){
 
                if(maze[i][j].state==0){
                    painter.drawPixmap(maze_cell_size*i+5,maze_cell_size*j+5,maze_cell_size,maze_cell_size,wall);
                }
                else if(maze[i][j].state==1){
                    painter.drawPixmap(maze_cell_size*i+5,maze_cell_size*j+5,maze_cell_size,maze_cell_size,road);
                }
                else if(maze[i][j].state==2){
                    if(control_direction==1){
                        painter.drawPixmap(maze_cell_size*i+5,maze_cell_size*j+5,maze_cell_size,maze_cell_size,control_LEFT);
                    }
                    else{
                        painter.drawPixmap(maze_cell_size*i+5,maze_cell_size*j+5,maze_cell_size,maze_cell_size,control_RIGHT);
                    }
                }
                else if(maze[i][j].state==3){
                    painter.drawPixmap(maze_cell_size*i+5,maze_cell_size*j+5,maze_cell_size,maze_cell_size,target);
                }
                else{}
            }
        }
 
        if(!flag_click){
            painter.setPen(Pen);
            point draw_point=path[target_X][target_Y];
            point pre_draw_point;
 
            while(draw_point.state!=0){
                if(draw_point.i==control_X&&draw_point.j==control_Y)
                    break;
                if(draw_point.state==1)//上
                    pre_draw_point=path[draw_point.i-1][draw_point.j];
                if(draw_point.state==2)//下
                    pre_draw_point=path[draw_point.i+1][draw_point.j];
                if(draw_point.state==3)//左
                    pre_draw_point=path[draw_point.i][draw_point.j-1];
                if(draw_point.state==4)//右
                    pre_draw_point=path[draw_point.i][draw_point.j+1];
 
                painter.drawLine(QPointF(maze_cell_size*draw_point.i+(maze_cell_size/2)+5,maze_cell_size*draw_point.j+(maze_cell_size/2)+5),QPointF(maze_cell_size*pre_draw_point.i+(maze_cell_size/2)+5,maze_cell_size*pre_draw_point.j+(maze_cell_size/2)+5));
 
                draw_point=pre_draw_point;
 
            }
 
        }
 
        update();
}
 
void play_maze::mousePressEvent(QMouseEvent *mouse){//自动寻路,与A*算法一致
    if(!creat_maze){
        return;
    }
    int x=mouse->x()-5;
    int y=mouse->y()-5;
    target_X2=x/maze_cell_size;
    target_Y2=y/maze_cell_size;
 
    if(maze[target_X2][target_Y2].state==0||maze[target_X2][target_Y2].state==3){
        flag_click=false;
        return;
    }
    else{
        flag_click=true;
    }
 
    //下面开始找路
    if(creat_maze==false){
        return;
    }
    auto_path2.clear();
    auto_path.clear();
 
    qDebug()<<"begin find path";
 
    for(int i=0; i<maze_row; i++)
        for(int j=0; j<maze_col; j++){
            path[i][j].state=0;//在这里的状态表示父节点,1,2,3,4分别表示从上下左右发展过来
            path[i][j].i=i;
            path[i][j].j=j;
        }
    //用于记录该点是否搜索的矩阵
    for(int i=0; i<maze_row; i++)
        for(int j=0; j<maze_col; j++){
            if(maze[i][j].state==0)
                graph[i][j]=1;
            else
                graph[i][j]=0;//初始化未被搜索
        }
 
 
    point top;
    top.i = control_X;
    top.j = control_Y;
    top.state = abs(control_X-target_X2)+abs(control_Y-target_Y2);
 
    auto_path.push_back(top);//这里的状态什么也不表示
 
    while(!auto_path.isEmpty()){
 
        qSort(auto_path.begin(),auto_path.end(),cmp);
 
 
 
        top=auto_path.front();
        //qDebug()<<top.i<<" "<<top.j<<" "<<top.state<<endl;
        auto_path.pop_front();
 
 
        if(graph[top.i][top.j]==0){
            if(top.i == target_X2&&top.j == target_Y2){
                //QMessageBox::information(NULL, " ", "搜索成功", QMessageBox::Yes, QMessageBox::Yes);
                break;
            }
            //将未访问的子节点放入开节点表
            if((graph[top.i+1][top.j] == 0)&&(maze[top.i+1][top.j].state != 0)){
                auto_path.push_back(point(top.i+1,top.j,abs(top.i+1-target_X2)+abs(top.j-target_Y2)));
                path[top.i+1][top.j].state = 1;
            }
            if((graph[top.i-1][top.j] == 0)&&(maze[top.i-1][top.j].state != 0)){
                auto_path.push_back(point(top.i-1,top.j,abs(top.i-1-target_X2)+abs(top.j-target_Y2)));
                path[top.i-1][top.j].state = 2;
            }
            if((graph[top.i][top.j+1] == 0)&&(maze[top.i][top.j+1].state != 0)){
                auto_path.push_back(point(top.i,top.j+1,abs(top.i-target_X2)+abs(top.j+1-target_Y2)));
                path[top.i][top.j+1].state = 3;
            }
            if((graph[top.i][top.j-1] == 0)&&(maze[top.i][top.j-1].state != 0)){
                auto_path.push_back(point(top.i,top.j-1,abs(top.i-target_X)+abs(top.j-1-target_Y2)));
                path[top.i][top.j-1].state = 4;
            }
            //将此点标记为访问过
            graph[top.i][top.j]=1;
        }
    }
    qDebug()<<"find the path!"<<endl;
 
    //下面进行反序,为了找到终点距离最小的点
    point mypoint;
    point pre_mypoint;
    mypoint=path[target_X2][target_Y2];
 
    while(mypoint.state!=0){
 
        if(mypoint.i==control_X&&mypoint.j==control_Y)
            break;
        if(mypoint.state==1)//上
            pre_mypoint=path[mypoint.i-1][mypoint.j];
        if(mypoint.state==2)//下
            pre_mypoint=path[mypoint.i+1][mypoint.j];
        if(mypoint.state==3)//左
            pre_mypoint=path[mypoint.i][mypoint.j-1];
        if(mypoint.state==4)//右
            pre_mypoint=path[mypoint.i][mypoint.j+1];
 
        auto_path2.push(mypoint);
        mypoint=pre_mypoint;
    }
 
 
    for(int i=0; i<maze_row; i++)
        for(int j=0; j<maze_col; j++){
            path[i][j].state=0;//在这里的状态表示父节点,1,2,3,4分别表示从上下左右发展过来
            path[i][j].i=i;
            path[i][j].j=j;
        }
 
 
 
}
 
void play_maze::timerEvent(QTimerEvent *){//自动寻路的显示
 
 
 
    if(!auto_path2.isEmpty()){
        mypoint=auto_path2.top();
        auto_path2.pop();
 
        if(maze[mypoint.i][mypoint.j].state==3){
            flag_target=true;
            flag_target2=false;//用两个flag的二进制编码考虑不同的状态
        }
 
        if(flag_target&&flag_target2){
            maze[mypoint.i][mypoint.j].state=2;
            maze[control_X][control_Y].state=3;
            flag_target=false;
            flag_target2=false;
        }
        else if(flag_target&&!flag_target2){
            maze[mypoint.i][mypoint.j].state=2;
            maze[control_X][control_Y].state=1;
            flag_target=true;
            flag_target2=true;
        }
        else{
            maze[mypoint.i][mypoint.j].state=2;
            maze[control_X][control_Y].state=1;
            flag_target=false;
            flag_target2=false;
        }
 
 
        control_X=mypoint.i;
        control_Y=mypoint.j;
    }
    else{
        flag_click=false;
    }
 
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值