计算机软件实习源代码

实习项目一源代码:

Headers:mianwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include<QVector>
#include "ui_mainwindow.h"


QT_BEGIN_NAMESPACE
//mianwindow是一个ui中得类
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
//    void iniUI();//习惯性地定义一个这样的函数,这是关于我们自己处理UI界面时候的样子
//    void MYUI();
//public slots:
//    void onButttonGroupClicked(QAbstractButton* btn);//关联信号与槽的函数
    QString expression;



private slots:
    void on_btn_lbr_clicked();

    void on_btn_rbr_clicked();

    void on_btn_add_clicked();

    void on_btn_sub_clicked();

    void on_btn_mul_clicked();

    void on_btn_div_clicked();

    void on_btn_equ_clicked();

//    void on_btn_ls_clicked();

//    void on_btn_rs_clicked();

    void on_btn_AC_clicked();

    void on_btn_del_clicked();

    void on_btn_0_clicked();

    void on_btn_1_clicked();

    void on_btn_2_clicked();

    void on_btn_3_clicked();

    void on_btn_4_clicked();

    void on_btn_5_clicked();

    void on_btn_6_clicked();

    void on_btn_7_clicked();

    void on_btn_8_clicked();

    void on_btn_9_clicked();

    void on_btn_poi_clicked();


    void on_btn_cmem_clicked();

private:
    Ui::MainWindow *ui;
//     QString expression;
    int count1=0;//计数器1,可以判断左右括号是不是正对出现
    int count2=0;//
};
#endif // MAINWINDOW_H

Sources:mianwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QButtonGroup>  //按钮组
#include <QDebug>
#include<QStack>

const int maxn=110;//最多只能输入440个字节,int是4字节,char是1字节
char priority[7][7]={
    //i表示表达书字符,j表示栈顶元素
    {'>','>','<','<','<','>','>'},
    {'>','>','<','<','<','>','>'},
    {'>','>','>','>','<','>','>'},
    {'>','>','>','>','<','>','>'},
    {'<','<','<','<','<','=','0'},   // 此行"("=")"表示左右括号相遇,括号内运算已完成,i=4,且j=5
    {'>','>','>','>','0','>','>'},
    {'<','<','<','<','<','0','='}    // "=" 表示整个表达式求值完毕
    };                           //  "0"表示不可能出现这种情况 ( 语法错误 )

//Procede 用于判断运算符栈栈顶运算符 a1 与读入运算符 a2 之间的优先关系函数
char Procede(char a,char b){
    //a表示栈顶元素,b表示表达式元素
    // 建立 priority[][] 到 运算符比较间的映射关系
    int i,j;
    switch(a){
        case'+':i=0;break;
        case'-':i=1;break;
        case'*':i=2;break;
        case'/':i=3;break;
        case'(':i=4;break;
        case')':i=5;break;
        case'#':i=6;break;   // # 是表达式的结束符
    }
    switch(b){
        case'+':j=0;break;
        case'-':j=1;break;
        case'*':j=2;break;
        case'/':j=3;break;
        case'(':j=4;break;
        case')':j=5;break;
        case'#':j=6;break;
    }
    return priority[i][j];
}

double Operate(double m,double n,char x){
    if(x=='+')
    return m+n;
    if(x=='-')
    return n-m;
    if(x=='*')
    return m*n;
    if(x=='/')
    return n/m;
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)//ui被实例化了
{
    ui->setupUi(this);//this是当前mainwindow类的实例对象。通过setupui就把ui设置给了this指针指向的实例对象


}

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::on_btn_equ_clicked()
{
    QChar j= expression.right(1).at(0);
    if(count1!=count2||j=="+"||j=="-"||j=="*"||j=="/")
    {
        ui->ted->setText("表达式错误");
        return;
    }
    QString e;
    e = expression;
    e += '=';

    QStack <float> OPND;      // 存数字
    QStack <char> OPTR;     // 存操作符
    char s[maxn];           //运算式数组

    OPTR.push('#');         //操作符栈底部加#
    char ss[2]="#";         //定义一个#,然后尾部还有\0


//    char path[50];


    QString str = expression;
    QByteArray ba = str.toLocal8Bit();
    memcpy(s,ba.data(),ba.size()+1);//加1是为了最后的终结符,否则转换回来的时候不知道什么时候截止

    QString str2;
    str2 = QString::fromLocal8Bit(s);

    /*qt fromLocal8Bit()函数可以设置编码。
    QT默认的编码是unicode,不能显示中文的 windows默认使用(GBK/GB2312/GB18030) 使用fromLocal8Bit()函数,
    实现了从本地字符集GB到Unicode的转换,用于处理汉语显示乱码等问题
     static inline QString fromLocal8Bit(const QByteArray &str);该函数返回的是String类型的数
*/

    //通过strcat函数,对表达式进行尾部加#,然后依次判断当前输入的是数字和运算符的情况
    strcat(s,ss);//strcat是一个追加字符串的函数,运算式尾部加 "#"--结束运算符
    char c=s[0];//c表示运算式的最前面那个字符
    int k=1;
    while(c!='#'||OPTR.top()!='#')
    {  //表达式未读完或者运算未完(未到底部)
        float y=0;
        //用c来表示当前输入的这个字符,如果是一个数字,那么压入OPND栈中
        if(c>='0' && c<='9')
        {           
            while(c>='0' && c<='9')
            {  // 读入连续的数字
                y=y*10+(c-'0');//y*10表示两位数及两位以上的数的处理

                c=s[k++];     //c向后遍历,一直遍历到s[110]

            }
            if(c=='.')
            {

            //小数点


                    float a=0,b=0;
                    k+=1;
                    c=s[k];
                    while (c>='0' && c<='9')
                    {
                        b=b*10+(c-'0');
                         c=s[k++];
                         a++;
                    }


                    for(;a>0;a--)
                    {
                        b=b*(10^(-1));

                    }

                    y=y+b;

               }
                OPND.push(y);  // 把读进的数字入数字栈
        }


        //运算符
        else
        {
            switch(Procede(OPTR.top(),c))  //栈顶运算符和当前读取运算符,比较优先级
                //OPTR.top()表示表格左边的,用OPTR.top()和c比较
            {
                        case'<':  //栈顶元素优先级低
                            OPTR.push(c);//表达式的字符压入栈顶
                            c=s[k++];//遍历
                            break;
                        case'=':
                            OPTR.pop();  // 脱括号,或者去掉井号
                            c=s[k++];  // 读入下一个字符
                            break;
                        case'>':  //退栈并将运算结果入栈
                            char x=OPTR.top();OPTR.pop();
                            float m=OPND.top();OPND.pop();
                            float n=OPND.top();OPND.pop();


                            OPND.push(Operate( m, n ,x ));//将结果存入操作数栈
                            break;
            }
        }
    }
    ui->ted->setText(QString::number(OPND.top()));//在ted界面显示结果


    //在tbr界面存储数据
    e += QString::number(OPND.top());
    ui->tbr->append(e);//在tbr界面展示遍历的结果
}




void MainWindow::on_btn_lbr_clicked()
{
    if((expression.back()=="(")||(expression.back()==")")||(expression.back()>='0' && expression.back()<='9'))return;
    expression+="(";
    count1++;
    ui->ted->setText(expression);
}

void MainWindow::on_btn_rbr_clicked()
{
    if((expression==NULL||expression.back()==".")||(expression.back()=="(")||(expression.back()==")")||(expression.back()=="+")||(expression.back()=="-")||(expression.back()=="*")||(expression.back()=="/"))return;
    if(count1>count2)
    {
        expression+=")";
        count2++;

    ui->ted->setText(expression);}
    else return;

}

void MainWindow::on_btn_add_clicked()
{

    if(expression==NULL||expression.back()=="+"||expression.back()=="-"||expression.back()=="*"||expression.back()=="/")return;
            expression+="+";
    ui->ted->setText(expression);
}

void MainWindow::on_btn_sub_clicked()
{
    if(expression==NULL||expression.back()=="+"||expression.back()=="-"||expression.back()=="*"||expression.back()=="/")return;
    expression+="-";
    ui->ted->setText(expression);
}

void MainWindow::on_btn_mul_clicked()
{
    if(expression==NULL||expression.back()=="+"||expression.back()=="-"||expression.back()=="*"||expression.back()=="/")return;
    expression+="*";
    ui->ted->setText(expression);
}

void MainWindow::on_btn_div_clicked()
{
    if(expression==NULL||expression.back()=="+"||expression.back()=="-"||expression.back()=="*"||expression.back()=="/")return;
    expression+="/";
    ui->ted->setText(expression);
}

void MainWindow::on_btn_AC_clicked()
{
    int n=sizeof(expression);
    expression.chop(n*n);
    ui->ted->setText(expression);
}

void MainWindow::on_btn_del_clicked()
{
    expression.chop(1);
    ui->ted->setText(expression);
}

void MainWindow::on_btn_0_clicked()
{
    if(expression.back()=="0"||expression.back()=="/")return;
    expression+="0";
    ui->ted->setText(expression);
}

void MainWindow::on_btn_1_clicked()
{
    if(expression.back()=="0")
      QString   clear(expression);
    expression+="1";
    ui->ted->setText(expression);
}

void MainWindow::on_btn_2_clicked()
{
    expression+="2";
    ui->ted->setText(expression);
}

void MainWindow::on_btn_3_clicked()
{
    expression+="3";
    ui->ted->setText(expression);
}

void MainWindow::on_btn_4_clicked()
{
    expression+="4";
    ui->ted->setText(expression);
}

void MainWindow::on_btn_5_clicked()
{
    expression+="5";
    ui->ted->setText(expression);
}

void MainWindow::on_btn_6_clicked()
{
    expression+="6";
    ui->ted->setText(expression);
}

void MainWindow::on_btn_7_clicked()
{
    expression+="7";
    ui->ted->setText(expression);
}

void MainWindow::on_btn_8_clicked()
{
    expression+="8";
    ui->ted->setText(expression);
}

void MainWindow::on_btn_9_clicked()
{
    expression+="9";
    ui->ted->setText(expression);
}

void MainWindow::on_btn_poi_clicked()
{
    if(expression.back()=="."||expression.back()=="("||expression.back()==")"||expression.back()=="+"||expression.back()=="-"||expression.back()=="*"||expression.back()=="/")return;
    if((expression.lastIndexOf(".")>expression.lastIndexOf("+"))||(expression.lastIndexOf(".")>expression.lastIndexOf("-"))||(expression.lastIndexOf(".")>expression.lastIndexOf("*"))||(expression.lastIndexOf(".")>expression.lastIndexOf("/")))
    {
    return;
    }
    else{
    expression+=".";
    ui->ted->setText(expression);
}
}

void MainWindow::on_btn_cmem_clicked()
{
     ui->tbr->clear();
}

 实习项目二源代码:

1.Headers:widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QKeyEvent>
#include <QTimer>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

//定义一个枚举类型的变量即可
enum Direct{
    DIR_UP,
    DIR_DOWN,
    DIR_RIGHT,
    DIR_LEFT
};

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

protected:
    //蛇的按键移动
    void keyPressEvent(QKeyEvent *event);//按键处理,是从父类QWidget继承的
    //每隔一个时延latency,朝一个方向加一个方块和去掉一个方块
    void addTop();
    void addDown();
    void addLeft();
    void addRight();


    //绘图
    void paintEvent(QPaintEvent *event);

    //前进时加头节点的同时删除尾节点
    void deleteLast();

    //随机生成食物
    void addNewReward();

    //判断游戏结束的条件
    bool checkContact();


private:
    Ui::Widget *ui;
    int moveFlag = DIR_UP;//游戏一开始的方向是朝向上的

    //得分
    int score = 0;

    bool gamestart = false;//表示游戏开始或者暂停

    QTimer *timer;//定时器

    //每隔一个时延让蛇移动,相当于蛇的速度
    int latency=150;




    //链表来表示一条蛇
    QList <QRectF> snake;//QRectf表示一块有面积的区域。可以理解成一个链表

    //食物
    QRectF rewardNode;

    //方块的宽高
    int nodeWidht = 20;
    int nodeHeight = 20;

protected slots:


    void counttimeout();


};
#endif // WIDGET_H

2.Sources:widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include<QPainter>
#include<QKeyEvent>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setWindowTitle("贪吃蛇");
        timer = new QTimer(this);//使用QTimer定时器类,首先创建一个定时器类的对象

        connect(timer,SIGNAL(timeout()),this,SLOT(counttimeout()));//timer 超时后会发出timeout()信号,所以在创建好定时器对象后给其建立信号与槽

        resize(1524,950);


        //初始化蛇身
        QRectF rect(500,230,nodeWidht,nodeHeight);
        snake.append(rect);
        addTop();
        addTop();
        addNewReward();//初始化食物
    }

    Widget::~Widget()
    {
        delete ui;
    }

    //对按钮处理,每次按不同按钮,就会进行不同处理,比如按上下左右产生移动,按空格表示暂停,按其他键表示速度增加或减小
    void Widget::keyPressEvent(QKeyEvent *event){
        //用switch分别表示面对相应按钮的相应操作
        switch (event->key()) {
        //朝上
        case Qt::Key_Up:
            if(moveFlag != DIR_DOWN){
            moveFlag = DIR_UP;
            }
            break;
        //朝下
        case Qt::Key_Down:
            if(moveFlag != DIR_UP){
             moveFlag = DIR_DOWN;
        }

            break;
        //朝左
        case Qt::Key_Left:
            if(moveFlag != DIR_RIGHT){
             moveFlag = DIR_LEFT;
            }
            break;
        //朝右
        case Qt::Key_Right:
            if(moveFlag != DIR_LEFT){
             moveFlag = DIR_RIGHT;
            }
            break;
        //暂停

        case Qt::Key_K:
            latency=50;timer->start(latency);
            break;
        case Qt::Key_M:
            latency=400;timer->start(latency);
            break;

        case Qt::Key_Space:
            if(gamestart==false)//如果一开始就等于false,那么游戏是没开始的,那么按下空格键就会让游戏开始
            {
                gamestart = true;

//              可以把这里的界面改了,
//                       改成初始界面选择速度



            //启动定时器
                timer->start(latency);
            }
            else //表示gamestart一开始是true,说明游戏是正在进行的,那么就让gamestart变为false
            {
                gamestart=false;
                timer ->stop();
            }
            break;
        default:
            break;
        }
    }
    //
    void Widget::counttimeout()//实现超时对应函数,即每隔latency单位的时延,就会产生一个信号让this指针相应一个函数counttimeout的操作

    {
         //吃到食物
         int counter = 1;
         if(snake[0].intersects(rewardNode)){
             counter++;
             score++;
             latency=latency-2;
             timer->start(latency);

             //吃到以后随机生成食物
             addNewReward();
         }
         while(counter--)
         {
             switch(moveFlag){
             case DIR_UP://顶部加方块
                 addTop();
                 break;
             case DIR_DOWN:
                 addDown();
                 break;
             case DIR_LEFT:
                 addLeft();
                 break;
             case DIR_RIGHT:
                 addRight();
                 break;
             }
        }

         deleteLast();
         update();//自动调用重绘方法
    }




     void Widget::addTop(){//向上
         QPointF leftTop;
         QPointF rightBottom;

//         if(snake[0].y() - nodeHeight < 0){
//             leftTop = QPoint(snake[0].x(),this->height() - nodeHeight);
//             rightBottom = QPointF(snake[0].x() + nodeWidht,this->height());
//         }
//         else{

         leftTop = QPointF(snake[0].x(),snake[0].y()-nodeHeight);//左下角坐标
         rightBottom = snake[0].topRight();//右下角坐标
//         }
         snake.insert(0,QRectF(leftTop,rightBottom));
     }




     void Widget::paintEvent(QPaintEvent *event){

        //画游戏界面
         QPainter painter(this);
         QPen pen;
         QBrush brush;

         //背景图
         QPixmap pix;
         pix.load("D:/C++/1.jpg");
         painter.drawPixmap(0,0,1524,950,pix);

         //画蛇
         pen.setColor(Qt::yellow);
         brush.setColor(Qt::blue);
         brush.setStyle(Qt::SolidPattern);
         painter.setPen(pen);
         painter.setBrush(brush);

         //遍历snake链表所有数据,依次活出一块块蛇身
         for(int i=0;i<snake.length();i++){
             painter.drawRect(snake[i]);
         }

         //画食物
         pen.setColor(Qt::green);
         brush.setColor(Qt::green);
         brush.setStyle(Qt::SolidPattern);
         painter.setPen(pen);
         painter.setBrush(brush);
         painter.drawEllipse(rewardNode);

         //结束画面
         if(checkContact()){
             QFont font("宋体",30,QFont::ExtraLight,false);
             painter.setFont((font));
             painter.drawText((this->width ()-300)/2,
              (this->height()-30)/2,
               QString("游戏结束"));
             timer->stop();
         }

         //画分数记录
         pen.setColor(Qt::red);
             brush.setColor(Qt::red);
             painter.setPen(pen);
             painter.setBrush(brush);
             QFont font("宋体",20,QFont::ExtraBold,false);
             painter.setFont(font);
             painter.drawText(0,nodeHeight*3,
                              QString("分数:"+QString::number(score*10)));

     }

     void Widget::deleteLast(){
         snake.removeLast();
     }

     void Widget::addDown(){//向下
         QPointF leftTop;
         QPointF rightBottom;
         //向下时如果接触到底端,则从对应的顶端重新生成蛇头
//         if(snake[0].y() + nodeHeight * 2 > this->height()){
//             leftTop = QPointF(snake[0].x(),0);
//             rightBottom = QPointF(snake[0].x() + nodeWidht,nodeHeight);

//         }
         //没有触碰下边界时,正常加减节点
//         else{
             leftTop = snake[0].bottomLeft();
             rightBottom = snake[0].bottomRight() + QPointF(0,nodeHeight);
//         }
         snake.insert(0,QRectF(leftTop,rightBottom));
     }
     void Widget::addLeft(){//向左
         QPointF leftTop;
         QPointF rightBottom;
//         if(snake[0].x() - nodeWidht<0){
//             leftTop = QPointF(this->width() - nodeWidht,snake[0].y());
//         }
//         else{
             leftTop = snake[0].topLeft() - QPointF(nodeWidht,0);
//         }
         rightBottom = leftTop + QPointF(nodeWidht,nodeHeight);
          snake.insert(0,QRectF(leftTop,rightBottom));
     }
     void Widget::addRight(){//向右
         QPointF leftTop;
         QPointF rightBottom;
//         if(snake[0].x() + nodeWidht*2 > this->width()){
//             leftTop = QPointF(0,snake[0].y());
//         }
//         else{
             leftTop = snake[0].topRight();
//         }
         rightBottom = leftTop + QPointF(nodeWidht,nodeHeight);
          snake.insert(0,QRectF(leftTop,rightBottom));
    }



     void Widget::addNewReward(){//随机生成食物
         rewardNode = QRectF(
                     qrand()%(this->width()/30)*20,
                     qrand()%(this->height()/30)*20,
                     nodeWidht,
                     nodeHeight);
     }
     bool Widget::checkContact(){//身体和头接触结束
         for(int i=1;i<snake.length();i++){
             if(snake[0] == snake[i]||(snake[0].y()  > this->height())||(snake[0].y()  <=0)||(snake[0].x() <=0)||(snake[0].x()  > this->width())){
                 return true;
             }
         }

         return false;
     }


实习项目三源代码:

1.Headers:mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QPainter>
#include <QKeyEvent>
#include <QMessageBox>
#include <iostream>
#include "maze.h"
using namespace std;

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    Maze *mymaze;
    int X;
    int Y;
    bool bfs_fg;

private slots:
    void slot_create();
    void slot_search();

protected:
    void paintEvent(QPaintEvent *);
    void keyPressEvent(QKeyEvent *e);
};

#endif // MAINWINDOW_H

2.Headers:maze.h

#ifndef MAZE_H
#define MAZE_H

#include <QObject>

using namespace std;
static const int N = 650;

class Maze : public QObject
{
    Q_OBJECT
public:
    explicit Maze(QObject *parent = nullptr);

    void set_n(int tn);
    int get_n();
    void printPath();//打印通路
    void recoverPath();
    void mazescr();//迷宫信息
    int searchPath(int x, int y);//搜索路径
    void print();

public:
    // 值为0:绘制迷宫过道
    // 值为1:绘制迷宫围墙
    // 值为2:绘制你当前的位置
    // 值为3:绘制迷宫终点
    // 值为4:绘制你当前的位置
    // 值为6:绘制最短路径提示
    int maze[N][N];

    struct point//定义结构体point
    {
        int x, y, pre;
    }q[N*N], path[N*N];//结构体数组

private:
    int n, len_path, nn;
    int fa[N*N];
    int dx[4] = {1, 0, -1, 0};
    int dy[4] = {0, 1, 0, -1};
    void bfs();
    void getPath(int pos);
};

#endif // MAZE_H

3.Sources:mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    int n = 31;//除了最外围的墙,一共有29行
    mymaze = new Maze();
    mymaze->set_n(n);//maze.cpp中的定义set_n,相当于让nn=n/2,相当于除了最外围那堵墙,一共有29列29行可以让
    mymaze->mazescr();//创建迷宫
    mymaze->print();//输出迷宫寻找的路径
    this->setWindowTitle("迷宫");//将窗口姓名改为“迷宫”
    this->setFixedSize(620,640);//将当前窗口大小设置为00*00像素

    connect(ui->btn_create,SIGNAL(clicked()),this,SLOT(slot_create()));//点击“初始化新迷宫”按钮进行创造随机迷宫
    connect(ui->btn_search,SIGNAL(clicked()),this,SLOT(slot_search()));//点击“自动寻路(寻找最短路径)”按钮
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::slot_create()
{
    mymaze->mazescr();
    X = 1, Y = 0;
    update();//更新画面,使重新构建的迷宫地图重新显示在画面中
}

//点击“自动寻路(寻找最短路径)”按钮,寻找迷宫到达终点的最短路径
void MainWindow::slot_search()

{
    mymaze->printPath();
    bfs_fg = true;//每次最短路径找到以后,更新bfs_fg的值为true,以便在自己移动时清除它
    update();
}


//绘制地图的墙、起点和终点、最短路径的标记样子、过道
void MainWindow::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    int n = mymaze->get_n();
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        {
            //围墙设置为灰色
            if(mymaze->maze[i][j] ==1){
                painter.setPen(Qt::gray);
                painter.setBrush(QBrush(Qt::gray,Qt::SolidPattern));
                painter.drawRect(QRect(j*20,i*20,20,20));
            }

            //黄色的点表示起点
            else if(mymaze->maze[i][j] == 2){
                painter.setPen(Qt::yellow);
                painter.setBrush(Qt::yellow);
                painter.drawRect(j*20,i*20,20,20);
            }
            //红色的点表示终点
            else if(mymaze->maze[i][j] == 3){
                painter.setPen(Qt::red);
                painter.setBrush(Qt::red);
                painter.drawRect(j*20,i*20,20,20);
            }
            //过道设置为白色
            else if(mymaze->maze[i][j] == 0){
                painter.setPen(Qt::white);
                painter.setBrush(QBrush(Qt::white,Qt::SolidPattern));
                painter.drawRect(QRect(j*20,i*20,20,20));
            }
            //最短路径设置
            else if(mymaze->maze[i][j] == 6){
                painter.setPen(Qt::white);
                painter.setBrush(Qt::blue);
                painter.drawRect(j*20+5,i*20+5,10,10);
            }
        }
    }
}

void MainWindow::keyPressEvent(QKeyEvent *e)
{
    if(bfs_fg)//bfs_fg默认初始值为true
    {
        mymaze->recoverPath();//让显示出的最短路径的痕迹消除,以便更新因生成新的迷宫而改变的新的最短路径

        bfs_fg = false;
        update();
    }

    int tx = X, ty = Y;
    int n = mymaze->get_n();
    if(e->key()==Qt::Key_W)//上
    {
        if(X>0 && mymaze->maze[X-1][Y] != 1)//周围四块移动的区域不是出边界或者墙的时候,可以移动
        {
            X=X-1;
        }
    }
    else if(e->key()==Qt::Key_S)//下
    {
        if(X<n-1 && mymaze->maze[X+1][Y] != 1)
        {
            X=X+1;
        }
    }
    else if(e->key()==Qt::Key_A)//左
    {
        if(Y>0 && mymaze->maze[X][Y-1] != 1)
        {
            Y=Y-1;
        }
    }
    else if(e->key()==Qt::Key_D)//右
    {

        if(Y<n-1 && mymaze->maze[X][Y+1] != 1)
        {
            Y=Y+1;
        }
    }
    //通过上下左右移动后,XY的值都在发生了变化
    int tmp = mymaze->maze[X][Y];
    if(tmp == 3){
        QMessageBox::information(this,"提示","朋友,恭喜你成功到达终点!",QMessageBox::Yes);
    }else{
        mymaze->maze[X][Y] = mymaze->maze[tx][ty];// /// 为什么要这么赋值???????????????????????????
        mymaze->maze[tx][ty] = tmp;
    }
    update();
}

4.Sources:maze.cpp

#include "maze.h"

Maze::Maze(QObject *parent) : QObject(parent)
{

}

void Maze::set_n(int tn)
{
    n = tn;
    nn = n/2;
}

int Maze::get_n()
{
    return n;
}


//绘制最短路径
void Maze::printPath()
{
    bfs();
    for(int i = len_path-1; i >= 0; i--) {
        if(maze[path[i].x][path[i].y]==0) {
            maze[path[i].x][path[i].y] = 6;
        }
    }
}

//清楚最短路径的痕迹,变为过道
void Maze::recoverPath()
{
    for(int i = len_path-1; i >= 0; i--)
    {
        if(maze[path[i].x][path[i].y]==6)
        {
            maze[path[i].x][path[i].y] = 0;
        }
    }
}

void Maze::mazescr()
{
    for(int i=0; i<=nn*2+2; ++i)
        for(int j=0; j<=nn*2+2; ++j)
            maze[i][j] = 1;

    for(int i=0, j=2*nn+2; i<=2*nn+2; ++i)
    {
        maze[i][0] = 0;
        maze[i][j] = 0;
    }
    for(int i=0, j=2*nn+2; i<=2*nn+2; ++i)
    {
        maze[0][i] = 0;
        maze[j][i] = 0;
    }

    maze[2][1] = 2;
    maze[2*nn][2*nn+1] = 3;//终点在第31行,32列

    //生成随机无符号数
    srand((unsigned)time(NULL));
    //生成的随机数在 [0, n]之间,生成路径
    searchPath(rand()%nn+1, rand()%nn+1);//nn+1为随机生成数的最大值//rand()%nn+1=2

    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        {
            maze[i][j] = maze[i+1][j+1];
        }
    }

    len_path = 0;
}

//prim算法创建路径
int Maze::searchPath(int x, int y)
{
    static int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
    int zx = x*2;//zx=4
    int zy = y*2;//zy=4
    int next, turn, i;
    maze[zx][zy] = 0;//制造随机的走道来打断原有的生成的迷宫的路径//maze[4][4] = 0

    //设置turn为[0, 4)之间的任意一个奇数,分别表示上下左右
    turn = rand()%2 ? 1 : 3;//

    //next=rand()%4 取值范围[0, 4)
    //next=(next+turn)%4 每个循环在奇数和偶数之间切换,[0, 4)遍历一遍
    //在迷宫地图里,随机选一个地方,开始挖路,4次循环,往4个方向挖(由(next+turn)%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)
            //判断上下左右的隔一个单位是否为1,为1则变为0
        {
            maze[zx+dir[next][0]][zy+dir[next][1]] = 0;
            searchPath(x+dir[next][0], y+dir[next][1]);
        }
    return 0;
}

void Maze::print()
{
    bfs();
}

void Maze::bfs()
{
    int front, tail, start_x, start_y;
    for(int i = 0; i < n; i++)
       for(int j = 0; j < n; j++)
           if(maze[i][j] == 2)//maze[][]为头文件maze.h中的二维整型数组
           {
               start_x = i; start_y = j;
           }
    front = tail = 0;
    q[tail].x = start_x;
    q[tail].y = start_y;
    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;
}

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;
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值