- 非常简单的一个贪吃蛇程序设计,程序最终效果如图所示:
- 首先设计好UI界面,并设置各个按键的功能。
- 设置贪吃蛇速度的两个控件:滑动器和微调框是相互关联的,程序实现代码如下:
//关联速度的两个控件
void(QSpinBox:: *spsignal)(int)=&QSpinBox::valueChanged;
connect(ui->spinBox,spsignal,ui->horizontalSlider,&QSlider::setValue);
connect(ui->horizontalSlider,&QSlider::valueChanged,ui->spinBox,&QSpinBox::setValue);
connect(ui->horizontalSlider,&QSlider::valueChanged,[=](){
speed=ui->spinBox->value();
});//关联速度调节
- 选择颜色按键的设计代码:
//按下颜色按钮选择颜色
QColorDialog *colordig=new QColorDialog;
connect(ui->pushButton_color,&QPushButton::clicked,this,[=](){
colordig->show();
});
//点击了颜色全局的颜色就会改变
connect(colordig,&QColorDialog::currentColorChanged,this,[=](){
QBrush brush(col,Qt::SolidPattern);
col=colordig->currentColor();
QString text = QString("RGB: %1, %2, %3").arg(col.red()).arg(col.green()).arg(col.blue());
//qDebug() << text;
update();
});
- 用STL的随机数生成函数生成食物
food_x=ui->frame_3->x()+((rand()%(ui->frame_3->width()))/12)*12;
food_y=ui->frame_3->y()+((rand()%(ui->frame_3->height()))/12)*12;
- 蛇即是一连串的存储在一个deque容器的坐标点,这种容器可以非常方便的在头部和尾部插入和删除数据,坐标点经x*1000+y运算后转换为一个数存入容器中,每次定时器溢出时,根据方向变量在容器头部插入下一个点的坐标,并删除掉尾部的数据,以此模拟移动,蛇死亡时会弹出设定好的另一个ui,弹出结束时的ui及定时器溢出时的代码:
gameoverform *over_dialog=new gameoverform;
over_dialog->setWindowTitle("game over");//设置游戏结束弹窗的标题
//设置游戏结束窗口下,两个按键的功能
connect(over_dialog->ui->pushButton_restart,&QPushButton::clicked,[=](){
over_dialog->close();
snake=snake_init;
direction=4;
});
connect(over_dialog->ui->pushButton_over,&QPushButton::clicked,this,[=](){
over_dialog->close();
this->close();
});
connect(timerid,&QTimer::timeout,[=](){
last_food_x=snake.front()/1000;
last_food_y=snake.front()%1000;
last_snake_back=snake.back();
switch (direction) {
case 1:{snake.pop_back();snake.push_front(last_food_x*1000+last_food_y-12);break;}
case 2:{snake.pop_back();snake.push_front(last_food_x*1000+last_food_y+12);break;}
case 3:{snake.pop_back();snake.push_front((last_food_x-12)*1000+last_food_y);break;}
case 4:{snake.pop_back();snake.push_front((last_food_x+12)*1000+last_food_y);break;}
}//蛇移动
//qDebug()<<"坐标x"<<food_x<<"坐标y"<<food_y;
if(snake.front()==(food_x*1000)+food_y)
{
food_x=ui->frame_3->x()+12+((rand()%(ui->frame_3->width()-12))/12)*12;
food_y=ui->frame_3->y()+12+((rand()%(ui->frame_3->height()-12))/12)*12;
snake.push_back(last_snake_back);
}//判断蛇吃到了食物
if((((snake.front()/1000)<(ui->frame_3->x()))||((snake.front()/1000)>=(ui->frame_3->x()+ui->frame_3->width()))||
((snake.front()%1000)<(ui->frame_3->y()))||((snake.front()%1000)>=(ui->frame_3->y()+ui->frame_3->height()))))
{
timerid->stop();
over_dialog->show();
}//判断蛇撞墙
for (unsigned long long k=snake.size();k>1;k--) {
if(snake.front()==snake[k])
{
timerid->stop();
over_dialog->show();
}
}//判断蛇是否咬到自己
update();//更新画面
});
- 在绘图事件中定义一个QPainterPath用于画蛇,以容器中的每一个坐标点为圆心按固定半径画圆并添加的定义的QPainterPath对象中,在定时器溢出时更新绘图;绘图事件代码:
//画图事件
void MainWindow::paintEvent(QPaintEvent *)
{
QPainter painter_color(this);
QPen pen(col);
pen.setWidth(5);
pen.setStyle(Qt::DotLine);
painter_color.setPen(pen);
//设置画刷
QBrush brush(col,Qt::SolidPattern);
painter_color.setBrush(brush);
painter_color.fillRect(ui->label_color->x(),ui->label_color->y(),ui->label_color->height(),ui->label_color->width(),col);
//在颜色按钮右边的方框内显示颜色指示
QPainterPath food_path;
food_path.addEllipse(food_x,food_y,12,12);//画食物
painter_color.fillPath(food_path,col);
//画蛇,按蛇的每一个坐标点画r=6的圆
QPainterPath snake_path;
for(unsigned long i=0;i<snake.size();i++)
{
snake_path.addEllipse(snake[i]/1000,snake[i]%1000,12,12);
}
painter_color.fillPath(snake_path,col);
}
键盘事件代码:
void MainWindow::keyPressEvent(QKeyEvent *event)
{
if((event->key()==Qt::Key_Up)&&(direction!=2)) direction=1;
if((event->key()==Qt::Key_Down)&&(direction!=1)) direction=2;
if((event->key()==Qt::Key_Left)&&(direction!=4)) direction=3;
if((event->key()==Qt::Key_Right)&&(direction!=3)) direction=4;
qDebug()<<"方向键值"<<direction;
}
源代码下载链接:https://download.csdn.net/download/qq_41831273/11966724