前言
为了进一步巩固Qt的知识,在完成五子棋小项目之后,在Qt方面我便开始着手了对贪吃蛇项目的设计,由于本人在51单片机的点阵上已经完成过贪吃蛇小游戏,所以,这一次有点巩固的感觉了。因为其思路和逻辑与我在单片机上的几乎一摸一样,所有前来总结一下。
一、贪吃蛇小项目的总体介绍
在这里简单介绍一下贪吃蛇项目的大概思路:首先,我们需要创建整体的路线框,以及设置具体的窗口大小。其次,就是蛇的身体的绘制以及蛇是如何运动的,我们知道,头才是真正控制走向的部位,所以我们可以让蛇身跟着蛇头运动,具体的话,请看以下步骤中的代码实现。在绘制完蛇身后,我们需要创建蛇的食物,食物是随机产生的,需要用到rand()函数。最后,还需有判断蛇头是否跑出布局和是否会咬到蛇身。实现这几步,基本上就完成了。
二、贪吃蛇项目的具体步骤
1.创建具体的路线框图(由于我也没想到该去什么名字)
代码如下:
#define board_num_x 40 //设置行数
#define board_num_y 40 //设置列数
#define board_width 20 //设置宽度
#define board_height 20 //设置高度
void MyWidget::Draw_board(){
QPainter painter(this); //创建画笔对象
for(int i=0;i<=board_num_x;i++)
{
for(int j=0;j<=board_num_y;j++){
painter.drawLine(i*board_width,0,i*board_width,j*board_height);//开始画
}
painter.drawLine(0,i*board_width,board_num_x*board_width,i*board_width);
}
}
我们绘制了一个40*40的表格,横向间距为20,纵向间距为20,这一步比较基础,所以就没过多介绍。里面的参数都是通过宏定义实现的。
2.创建蛇身
代码如下:
QPoint body[1600]; //存储蛇身
int length=2; //记录蛇身长度
void MyWidget::Snake_Init(){ //蛇身的初始化
body[0]=QPoint(0,1); //将body[0]设置为蛇头
body[1]=QPoint(0,0); //设置为蛇身
}
void MyWidget::Draw_Snake(){ //绘制蛇身
QPainter painter(this); //创建对象
QBrush brush;
brush.setColor(Qt::red); //设置画刷颜色
brush.setStyle(Qt::SolidPattern);//设置填充样式
painter.setBrush(brush);
Is_eat(); //该函数是判断蛇头有没有吃到食物的
for(int i=0;i<length;i++){ //从前往后依次遍历,及实现蛇身绘制
painter.drawRect(body[i].rx()*board_width,body[i].ry()*board_height,board_width,board_height); //绘制蛇的每一部分
}
}
在这一部分中,我通过一个QPoint数据类型的数组,来存储蛇头和蛇身。蛇的初始化,我简单的将蛇分为一个蛇头和一节身体,以后在蛇吃到食物后蛇身会加长,具体会在后文给出。
蛇的走向判断
代码如下:
void MyWidget::keyPressEvent(QKeyEvent *event){ //键盘按键检测事件
if(event->key()==Qt::Key_Down){ //当摁到向下的按钮时
if(flag!=2){ //判断当前方向是否和将要运动的方向相反,不相反则执行
flag=1;
}
}
if(event->key()==Qt::Key_Up){ //当摁到向上的按钮时
if(flag!=1){
flag=2;
}
}
if(event->key()==Qt::Key_Left){ //当摁到向左的按钮时
if(flag!=4){
flag=3;
}
}
if(event->key()==Qt::Key_Right){ //当摁到向右的按钮时
if(flag!=3){
flag=4;
}
}
}
上面这部分代码通过引入头文件 QKeyEvent 来实现,这是Qt自带的库,用于对键盘按键的检测。其中,flag为1时表示向下运动,为2时向上运动,为3时向左运动,为4时向右运动,该标志位用于后续运动时的走向。
void MyWidget::time_init(){ //创建定时器,并初始化
timer=new QTimer(this); //创建对象
timer->setInterval(1000); //设置定时时长为1000ms
timer->start(); //定时器开始运行
}
这部分代码为创建定时器,并初始化。设置定时器的定时周期为1000ms,并让起开始运行。
void MyWidget::on_timer_timeout(){ //定时器达到计时时会执行该函数
for(int i=length;i>0;i--){ //从后往前遍历,实现前文提到的蛇身跟随蛇头运动的行为
body[i]=body[i-1];
}
switch(flag){ //flag为走向标记位
case 1:
body[0]=QPoint(body[0].rx(),body[0].ry()+1); //向下运动
break;
case 2:
body[0]=QPoint(body[0].rx(),body[0].ry()-1); //向上运动
break;
case 3:
body[0]=QPoint(body[0].rx()-1,body[0].ry()); //向左运动
break;
case 4:
body[0]=QPoint(body[0].rx()+1,body[0].ry()); //向右运动
break;
}
Snake_Dead(); //蛇的死亡条件判断,后文会给出
}
在这一部分中,实现了对存储蛇身的数组的更新,并且每次更新时长都为1s,即蛇会在每过1s后进行移动。
食物创建
代码如下:
int food_flag=0; //食物有无标志位
int food_x; //食物生成的x坐标
int food_y; //食物生成的y坐标
void MyWidget::Creat_food(){
if(food_flag==0){ //当没有食物时,创建食物
food_x=rand()%board_width; //使用rand()函数,随机产生数字,作为食物的x坐标
food_y=rand()%board_height;//作为y坐标
food_flag=1; //将标志位设置为一,即存在食物
}
QPainter *painter=new QPainter(this);
QBrush brush;
brush.setColor(Qt::red); //设置画刷颜色
brush.setStyle(Qt::SolidPattern); //设置填充样式
painter->setBrush(brush);
painter->drawRect(food_x*board_width,food_y*board_height,board_width,board_height); //在食物的位置绘制食物
}
这一部分,通过随机产生一个二维坐标,并在该坐标处进行绘画食物的操作。
吃食物
代码如下:
void MyWidget::Is_eat(){ //判断是否吃到
if(body[0].rx()==food_x&&body[0].ry()==food_y){ //当蛇头的坐标等与食物的坐标时,就认为已经迟到食物了
length++; //蛇身长度加一
food_flag=0; //食物标志位置0,说明没有食物了
}
}
在这一部分就很简单了,通过判断蛇头的坐标是否与食物的坐标相等,相等的话就认为蛇吃到食物了,与此同时,将蛇身的长度加一,并把食物标志物置0,一遍在后续中在产生一个食物。
贪吃蛇的死亡判断
void MyWidget::Snake_Dead(){
for(int i=1;i<length;i++){ //这一部分用于判断蛇头是否撞到蛇身
if(body[0]==body[i]){
timer->stop(); //撞到的话,将定时器停止,即蛇静止,游戏结束
}
}
if(body[0].rx()==-1||body[0].rx()==41||body[0].ry()==-1||body[0].ry()==41){ //该部分用于判断蛇头坐标是否出界
timer->stop(); //如果出界,定时器停止
}
}
总结
以上就是今天要讲的内容,本文只是简简单单的对贪吃蛇项目进行讲解,如果有错误,还请各位大佬指出。另外,如有需要源码的,请留言。下次再见!