基于QT的贪吃蛇(打包成可以运行在安卓系统下的apk文件)
写在前面:
1.QT程序下的安卓开发。可以将QT的代码编译成apk文件。
2.在QT上开发安卓,需要搭建环境。记得需要下几件东西,相当麻烦。可以搜索其他文章了解
3.QT上开发安卓,需要注意的是,界面布局问题。否则移植到安卓设备上后界面比例很难看
先看看截图
全部代码(本人的Qt环境是 QT5.9.3)
qtsnake.h文件
#ifndef QTSNAKE_H
#define QTSNAKE_H
#include<QPainter>
#include<QList>
#include<QTimer>
#include<QKeyEvent>
#include<QRectF>//矩形类
#include<QPen>
#include<QBrush>
#include<QDebug>
#include<QTime>
#include <QWidget>
#include<QFrame>
#include<QPushButton>
#include<QMessageBox>
namespace Ui {
class QtSnake;
}
class QtSnake : public QWidget
{
Q_OBJECT
public:
explicit QtSnake(QWidget *parent = 0);
~QtSnake();
protected:
void paintEvent(QPaintEvent *);//绘图事件
//void keyPressEvent(QKeyEvent *);//鼠标点击事件
private:
void addTopRectF();//向上按
void addLeftRectF();//向左按
void addDownRectF();//向下按
void addRightRectF();//向右按
bool snakeStrike();//蛇撞到自己
void deleteLastRectF();
void gameEnd();//游戏结束
enum Move{Up,Down,Left,Right};//移动的方向
private slots:
void timeOut();
void rewardTimeOut();
void btn_start_fun();
void btn_up_fun();
void btn_down_fun();
void btn_left_fun();
void btn_right_fun();
void btn_about_fun();
private:
//Ui::QtSnake *ui;
QList<QRectF>snake;//蛇本体
int snakeNodeWidth = 20;// 蛇的每一节都是正方形的格子边长为10
int snakeNodeHeight = 20;
QTimer*timer;
QTimer*rewardTimer;
int time =100;
int moveFlag =Up;
bool gameOver =false;
bool gameStart = false;
QList<QRectF>rewardNode;//奖励节点
//void Painter();
//bool eventFilter(QObject *watched, QEvent *event);
QPushButton*btn_start;
QPushButton*btn_up;
QPushButton*btn_down;
QPushButton*btn_left;
QPushButton*btn_right;
QPushButton*btn_about;
};
#endif // QTSNAKE_H
qtsnake.cpp文件
#include "qtsnake.h"
QtSnake::QtSnake(QWidget *parent) :
QWidget(parent)
{
this->setFixedSize(400,800);
this->setWindowTitle("山寨版贪吃蛇");
//设置窗口为黑色
//setStyleSheet("QWidget{background:black}");
snake.append(QRectF(200,550,snakeNodeWidth,snakeNodeHeight));
addTopRectF();
addTopRectF();
//生成第一个奖励节点(食物)
rewardNode.append(QRectF(200,400,snakeNodeWidth,snakeNodeHeight));
btn_start=new QPushButton("开始游戏",this);
connect(btn_start,SIGNAL(clicked()),this,SLOT(btn_start_fun()));
btn_up =new QPushButton("上",this);
//btn_up->move(this->width()/4,this->height()*39/48);
connect(btn_up,SIGNAL(clicked()),this,SLOT(btn_up_fun()));
btn_left =new QPushButton("左",this);
connect(btn_left,SIGNAL(clicked()),this,SLOT(btn_left_fun()));
btn_down =new QPushButton("下",this);
connect(btn_down,SIGNAL(clicked()),this,SLOT(btn_down_fun()));
btn_right =new QPushButton("右",this);
connect(btn_right,SIGNAL(clicked()),this,SLOT(btn_right_fun()));
btn_about =new QPushButton("关于",this);
connect(btn_about,SIGNAL(clicked()),this,SLOT(btn_about_fun()));
timer = new QTimer;
connect(timer,SIGNAL(timeout()),this,SLOT(timeOut()));
rewardTimer = new QTimer;
connect(rewardTimer,SIGNAL(timeout()),this,SLOT(rewardTimeOut()));
}
void QtSnake::btn_start_fun()
{
if(!gameStart && !gameOver) {
timer->start(time);
rewardTimer->start(time*30);
gameStart = true;
} else if(gameOver&&gameStart) {
timer->start(time);
rewardTimer->start(time*30);
//gameStart = true;
}
/*timer->start(time);
rewardTimer->start(time*30);
gameStart=true;*/
}
void QtSnake::btn_up_fun()
{
if(moveFlag !=Down) {
moveFlag =Up;
}
}
void QtSnake::btn_left_fun()
{
if(moveFlag != Right) {
moveFlag = Left;
}
}
void QtSnake::btn_down_fun()
{
if(moveFlag !=Up) {
moveFlag = Down;
}
}
void QtSnake::btn_right_fun()
{
if(moveFlag !=Left) {
moveFlag = Right;
}
}
void QtSnake::btn_about_fun()
{
QMessageBox::information(this,"开发者信息","完成日期:2020/02/21\n名称:山寨版贪吃蛇\n作者:Edison\n开发工具:QT5.9.3\n",QMessageBox::Ok|QMessageBox::Cancel,QMessageBox::Ok);
}
//界面刷新
void QtSnake::timeOut()
{
int flag =1;
for(int i =0;i<rewardNode.length();i++)
{
if(rewardNode.at(i).contains(snake.at(0).topLeft()
+QPointF(snakeNodeWidth/2,snakeNodeHeight/2))) {
if(rewardNode.at(i).width()>snakeNodeWidth) {//大食物
flag+=2;
}
flag++;//正常食物
rewardNode.removeAt(i);
break;
}
}
while(flag--){
switch(moveFlag) {
case Up:
addTopRectF();
break;
case Down:
addDownRectF();
break;
case Left:
addLeftRectF();
break;
case Right:
addRightRectF();
break;
default:
break;
}
}
deleteLastRectF();
update();
}
// 随机食物生成
void QtSnake::rewardTimeOut()
{
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
if(rewardNode.length() > 5) {
rewardNode.removeAt(qrand()%5);
}
rewardNode.append(QRectF(qrand()%(this->width()*17/20)+this->width()/20,qrand()%(this->height()*3/4-(this->width()/20))+this->width()/20,snakeNodeWidth,snakeNodeHeight));
if(qrand()%5 == 3) {
rewardNode.append(QRectF(qrand()%(this->width()*17/20)+this->width()/20,qrand()%(this->height()*3/4-(this->width()))+this->width(),snakeNodeWidth*2,snakeNodeHeight*2));
}
}
//向上移动吃食物增加蛇身体
void QtSnake::addTopRectF()
{
snake.insert(0,QRectF(snake.at(0).topLeft()+QPointF(0,-snakeNodeHeight),snake.at(0).topRight()));
}
//向下
void QtSnake::addDownRectF()
{
snake.insert(0,QRectF(snake.at(0).bottomLeft(),snake.at(0).bottomRight()+QPointF(0,snakeNodeHeight)));
}
//向左
void QtSnake::addLeftRectF()
{
snake.insert(0,QRectF(snake.at(0).topLeft()+QPointF(-snakeNodeWidth,0),snake.at(0).bottomLeft()));
}
//向右
void QtSnake::addRightRectF()
{
snake.insert(0,QRectF(snake.at(0).topRight(),snake.at(0).bottomRight()+QPointF(snakeNodeWidth,0)));
}
//绘图事件
void QtSnake::paintEvent(QPaintEvent *event)
{
btn_start->move(this->width()*95/400,this->height()*21/24);
btn_about->move(this->width()*75/100,this->height()*20/24);
btn_right->move(this->width()/2,this->height()*21/24);
btn_left->move(this->width()/80,this->height()*21/24);
btn_down->move(this->width()/4,this->height()*45/48);
btn_up->move(this->width()/4,this->height()*39/48);
QPainter painter(this);//创建画家对象
QPen pen;//创建画笔对象(一般用来绘制轮廓)
QBrush brush;//创建笔刷对象(一般用来填充)
QFont font("方正舒体",12,QFont::ExtraLight,false);//字体样式
//反锯齿(这种就要记住如何使用)
painter.setRenderHint(QPainter::Antialiasing);
pen.setColor(Qt::black);//设置画笔颜色
brush.setColor(Qt::black);//设置笔刷颜色
brush.setStyle(Qt::SolidPattern);//填充模式
painter.setPen(pen);
painter.setBrush(brush);
painter.drawRect(QRect(this->width()/20,this->width()/20,this->width()*9/10,this->height()*3/4));//画矩形方框
pen.setColor(Qt::green);//设置画笔颜色
brush.setColor(Qt::black);//设置笔刷颜色
painter.setPen(pen);
painter.setBrush(brush);
//画蛇
for(int i =0;i<snake.length();i++)
{
if(i == 0) {
painter.drawEllipse(snake.at(i));
} else {
painter.drawRect(snake.at(i));
}
}
brush.setColor(Qt::red);
painter.setBrush(brush);
//画食物
for(int i=0;i<rewardNode.length();i++)
{
painter.drawEllipse(rewardNode.at(i)); //画椭圆
}
pen.setColor(Qt::red);
painter.setPen(pen);
painter.setFont(font);
painter.drawText(this->width()*9/200,this->width()*9/200,QString("当前分数: ")+QString("%1").arg(snake.length()));
if(snakeStrike()||(snake.at(0).x()-snakeNodeWidth <this->width()/20-snakeNodeWidth*3/4)//向左边撞墙
||(snake.at(0).x()+snakeNodeWidth*2 > this->width()*9/10+snakeNodeWidth*2)//向右边撞墙
||(snake.at(0).y()+snakeNodeHeight*2 > this->height()*3/4+2*snakeNodeHeight)//向下撞墙
||(snake.at(0).y()-snakeNodeHeight < this->width()/20-snakeNodeWidth)){//向上撞墙
gameEnd();
painter.setFont(font);
painter.drawText((this->width()-40)/2,(this->height()-30)/2,QString("GAME OVER!"));
}
QWidget::paintEvent(event);
}
// 删除蛇本体最后一个数据
void QtSnake::deleteLastRectF()
{
snake.removeLast();
}
//判断蛇是否与身体相撞
bool QtSnake::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;
}
// 游戏结束
void QtSnake::gameEnd()
{
timer->stop();
rewardTimer->stop();
gameOver = true;
}
QtSnake::~QtSnake()
{
//delete ui;
}
代码还有很多不足之处,就是边缘撞墙死亡的可能有点小bug,因为我是按照固定尺寸设计单个格子大小的,但是不影响使用。主要是设计思想