①计算器
#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;
}
}