运用Qt实现贪吃蛇小游戏的具体代码
游戏大厅
hall.h
c
#ifndef HALL_H
#define HALL_H
#include <QWidget>
#include <QPaintEvent>
QT_BEGIN_NAMESPACE
namespace Ui { class Hall; }
QT_END_NAMESPACE
class Hall : public QWidget
{
Q_OBJECT
public:
Hall(QWidget *parent = nullptr);
~Hall();
//重写绘图事件
void paintEvent(QPaintEvent *event);
private:
Ui::Hall *ui;
};
#endif // HALL_H
hall.cpp
c
#include "hall.h"
#include "ui_hall.h"
#include <QPainter>
#include <QPixmap>
#include <QPushButton>
#include <QIcon>
#include <QFont>
#include <QDialog>
#include <QVBoxLayout>
#include <QSound>
#include <QLabel>
#include "game_select.h"
#include "hint.h"
Hall::Hall(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Hall)
{
ui->setupUi(this);
this->setFixedSize(1200,800);//设置窗口初始大小
this->setWindowIcon(QIcon(":res/ico.png"));// 窗口图标
this->setWindowTitle("贪吃蛇");
QFont font("华文隶书",40);
QPushButton* start=new QPushButton(this);
start->move(440,630);
start->setText("开始游戏");
start->setFont(font);
start->setStyleSheet("QPushButton{border-radius: 10px; background-color: green;}"
"QPushButton:pressed{background-color: white}");
Game_select* gameselect=new Game_select;
connect(start,&QPushButton::clicked,[=](){
this->close();
QSound::play(":res/clicked.wav");
gameselect->setGeometry(this->geometry());
gameselect->show();
});
QPushButton* hint=new QPushButton(this);
Hint* H_t=new Hint;
connect(hint,&QPushButton::clicked,[=](){
H_t->show();
});
hint->move(20,20);
hint->setIconSize(QSize(50,50));
hint->setText("免责声明");
hint->setFont(QFont("宋体",24));
hint->setIcon(QIcon(":res/tishi.png"));
}
Hall::~Hall()
{
delete ui;
}
void Hall::paintEvent(QPaintEvent *event)
{
(void) event;
QPainter painter(this);
QPixmap pixmap(":res/game_hall.png");
painter.drawPixmap(0,0,this->width(),this->height(),pixmap);
}
选关界面
game_select.h
c
#ifndef GAME_SELECT_H
#define GAME_SELECT_H
#include <QWidget>
class Game_select : public QWidget
{
Q_OBJECT
public:
explicit Game_select(QWidget *parent = nullptr);
void paintEvent(QPaintEvent *event);
signals:
};
#endif // GAME_SELECT_H
game_select.cpp
c
#include "game_select.h"
#include "game_room.h"
#include "hall.h"
#include <QIcon>
#include <QPushButton>
#include <QSound>
#include <QPainter>
#include <QPixmap>
#include <QFont>
#include <QTextEdit>
#include <QFile>
#include <QTextStream>
Game_select::Game_select(QWidget *parent) : QWidget(parent)
{
this->setFixedSize(800,900);
this->setWindowIcon(QIcon(":res/ico.png"));// 窗口图标
this->setWindowTitle("关卡选择");
QPushButton* ret=new QPushButton(this);
ret->resize(80,80);
ret->setIcon(QIcon(":res/back.png"));
ret->move(this->width()-100,this->height()-100);
connect(ret,&QPushButton::clicked,[=](){
this->close();
Hall* hall=new Hall;
hall->show();
QSound::play(":res/eatfood.wav");
});
QFont font("华文隶书",40);
Game_room* gameroom=new Game_room;
QPushButton* simplebutt=new QPushButton(this);
simplebutt->move(350,200);
simplebutt->setText("简单模式");
simplebutt->setFont(font);
connect(simplebutt,&QPushButton::clicked,[=](){
this->close();
gameroom->setFixedSize(1200,800);
gameroom->setWindowIcon(QIcon(":res/ico.png"));// 窗口图标
gameroom->setWindowTitle("贪吃蛇: 简单模式");
gameroom->show();
gameroom->setTimeOut(300);//设置不同难度的速度
});
QPushButton* normalbutt=new QPushButton(this);
normalbutt->move(350,400);
normalbutt->setText("普通模式");
normalbutt->setFont(font);
connect(normalbutt,&QPushButton::clicked,[=](){
this->close();
gameroom->setFixedSize(1200,800);
gameroom->setWindowIcon(QIcon(":res/ico.png"));// 窗口图标
gameroom->setWindowTitle("贪吃蛇: 普通模式");
gameroom->show();
gameroom->setTimeOut(200);//设置不同难度的速度
});
QPushButton* hardbutt=new QPushButton(this);
hardbutt->move(350,600);
hardbutt->setText("困难模式");
hardbutt->setFont(font);
connect(hardbutt,&QPushButton::clicked,[=](){
this->close();
gameroom->setFixedSize(1200,800);
gameroom->setWindowIcon(QIcon(":res/ico.png"));// 窗口图标
gameroom->setWindowTitle("贪吃蛇: 困难模式");
gameroom->show();
gameroom->setTimeOut(100);//设置不同难度的速度
});
QPushButton* history=new QPushButton(this);
history->move(60,80);
history->setText("历史记录");
history->setFont(font);
connect(history,&QPushButton::clicked,[=](){
QWidget* widget=new QWidget;
widget->setWindowTitle("历史战绩");
widget->setFixedSize(500,400);
widget->setWindowIcon(QIcon(":res/ico.png"));
QTextEdit* edit=new QTextEdit(widget);
edit->setFont(QFont("黑体",30));
edit->setFixedSize(500,400);
QFile file("C:/Users/xcj/Desktop/snake/snake/his.txt");
file.open(QIODevice::ReadOnly);
QTextStream in(&file);
int data=in.readLine().toInt();
edit->setText("上一次得分为:");
edit->append(QString::number(data));//追加
widget->show();
});
}
void Game_select::paintEvent(QPaintEvent *event)
{
(void) event;
QPainter painter(this);
QPixmap pix(":res/game_select.png");
painter.drawPixmap(0,0,this->width(),this->height(),pix);
}
游戏界面
game_room
c
#ifndef GAME_ROOM_H
#define GAME_ROOM_H
#include <QWidget>
#include <QSound>
//枚举蛇的移动方向
enum class SnakeDirect
{
UP=0,
DOWN,
LEFT,
RIGHT
};
class Game_room : public QWidget
{
Q_OBJECT
public:
explicit Game_room(QWidget *parent = nullptr);
void paintEvent(QPaintEvent *event);
void moveUp();//向上移动
void moveDOWN();//向下移动
void moveLEFT();//向左移动
void moveRIGHT();//向右移动
bool isOver();//检测是否结束
void createNewFood();//创建新的食物
void setTimeOut(int timeout)
{
moveTimeout =timeout;
}
private:
const int kSnakeNodeWidth =20;//定义蛇节点的宽度
const int kSnakeNodeHeight =20;//定义蛇节点的高度
const int kDefaultTimeout = 200;//蛇的移动速度
QList<QRectF> snakeList; //表示贪吃蛇链表
QRectF foodRect; //食物节点
SnakeDirect moveDirect=SnakeDirect::UP; //蛇默认移动方向位向上
QTimer* timer;//定时器
bool isGameStart = false;//是否开始游戏
QSound * sound;//bgm
int moveTimeout = kDefaultTimeout;
};
#endif // GAME_ROOM_H
game_room.cpp
c
#include "game_room.h"
#include <QPushButton>
#include <QPainter>
#include <QPixmap>
#include <QTimer>
#include <QMessageBox>
#include <QFile>
#include <QTextStream>
#include "game_select.h"
Game_room::Game_room(QWidget *parent) : QWidget(parent)
{
//初始化蛇
snakeList.push_back(QRectF(this->width()*0.5,this->height()*0.5,kSnakeNodeWidth,kSnakeNodeHeight));
moveUp();
moveUp();
//创建食物
createNewFood();
timer=new QTimer(this);
connect(timer,&QTimer::timeout,[=](){
int cnt=1;
// 通过intersects方法来判断蛇头与食物是否相交
if(snakeList.front().intersects(foodRect))
{
QSound::play(":res/eatfood.wav");
createNewFood();
cnt++;
}
while(cnt--)
{
switch (moveDirect)
{
case SnakeDirect::UP:
moveUp();
break;
case SnakeDirect::DOWN:
moveDOWN();
break;
case SnakeDirect::LEFT:
moveLEFT();
break;
case SnakeDirect::RIGHT:
moveRIGHT();
break;
}
}
snakeList.pop_back();
update();//更新链表
});
//开始与暂停按钮
QPushButton* startb=new QPushButton(this);
QPushButton* stopb=new QPushButton(this);
QFont font("华文隶书",20);
startb->move(980,150);
stopb->move(980,225);
startb->setText("开始游戏");
stopb->setText("暂停游戏");
startb->setFont(font);
stopb->setFont(font);
connect(startb,&QPushButton::clicked,[=](){
isGameStart=true;
timer->start(moveTimeout);
sound=new QSound(":res/BGM.wav");
sound->play();
sound->setLoops(-1);//只要是真就循环播放
});
connect(stopb,&QPushButton::clicked,[=](){
isGameStart=false;
timer->stop();
sound->stop();
});
//控制方向
QPushButton* up=new QPushButton(this);
QPushButton* down=new QPushButton(this);
QPushButton* left=new QPushButton(this);
QPushButton* right=new QPushButton(this);
up->move(1020,372);
down->move(1020,440);
left->move(952,440);
right->move(1088,440);
up->setText("↑");
down->setText("↓");
left->setText("←");
right->setText("→");
up->setStyleSheet("QPushButton{border-radius: 10px; background-color: green;}"
"QPushButton:pressed{background-color: white}");
down->setStyleSheet("QPushButton{border-radius: 10px; background-color: green;}"
"QPushButton:pressed{background-color: white}");
left->setStyleSheet("QPushButton{border-radius: 10px; background-color: green;}"
"QPushButton:pressed{background-color: white}");
right->setStyleSheet("QPushButton{border-radius: 10px; background-color: green;}"
"QPushButton:pressed{background-color: white}");
up->setShortcut(QKeySequence(Qt::Key_Up));
down->setShortcut(QKeySequence(Qt::Key_Down));
left->setShortcut(QKeySequence(Qt::Key_Left));
right->setShortcut(QKeySequence(Qt::Key_Right));
QFont FF("宋体",40);
up->setFont(FF);
down->setFont(FF);
left->setFont(FF);
right->setFont(FF);
//控制蛇的方向
connect(up,&QPushButton::clicked,[=](){
if(moveDirect != SnakeDirect::DOWN)
moveDirect=SnakeDirect::UP;
});
connect(down,&QPushButton::clicked,[=](){
if(moveDirect != SnakeDirect::UP)
moveDirect=SnakeDirect::DOWN;
});
connect(left,&QPushButton::clicked,[=](){
if(moveDirect != SnakeDirect::RIGHT)
moveDirect=SnakeDirect::LEFT;
});
connect(right,&QPushButton::clicked,[=](){
if(moveDirect != SnakeDirect::LEFT)
moveDirect=SnakeDirect::RIGHT;
});
//退出游戏
QPushButton* exit =new QPushButton(this);
exit->move(935,690);
exit->setText("退出");
exit->setFont(QFont("华文琥珀",15));
exit->setStyleSheet("QPushButton{border-radius: 10px;background-color: pink;}"
"QPushButton:pressed{background-color: blue;}");
QMessageBox* msg=new QMessageBox(this);
QPushButton* ok=new QPushButton("确认");
QPushButton* cancel=new QPushButton("取消");
msg->addButton(ok,QMessageBox::AcceptRole);
msg->addButton(cancel,QMessageBox::RejectRole);
msg->setWindowTitle("退出游戏");
msg->setText("是否"
"退出游戏?");
msg->setFont(QFont("隶书",12));
msg->setIconPixmap(QPixmap(":res/exit.png"));
connect(exit,&QPushButton::clicked,[=](){
QSound::play(":res/clicked.wav");
msg->show();
msg->exec();//事件轮询 等待用户输入
Game_select* select=new Game_select;
if(msg->clickedButton()==ok)
{
this->close();
select->show();
}
else
{
msg->close();
}
});
}
void Game_room::paintEvent(QPaintEvent *event)
{
(void) event;
QPainter painter(this);
QPixmap pix;
pix.load(":res/game_room.png");
painter.drawPixmap(0,0,900,this->height(),pix);
pix.load(":res/game_room.2.png");
painter.drawPixmap(900,0,300,this->height(),pix);
//绘制蛇
//蛇头
if(moveDirect ==SnakeDirect::UP)
{
pix.load(":res/up.png");
}
else if(moveDirect == SnakeDirect::DOWN)
{
pix.load(":res/down.png");
}
else if(moveDirect == SnakeDirect::LEFT)
{
pix.load(":res/left.png");
}
else if(moveDirect == SnakeDirect::RIGHT)
{
pix.load(":res/right.png");
}
auto snakeHead=snakeList.front();
painter.drawPixmap(snakeHead.x(),snakeHead.y(),kSnakeNodeWidth,kSnakeNodeHeight,pix);
//绘制身体
if(moveDirect ==SnakeDirect::UP)
{
pix.load(":res/bd.png");
}
else if(moveDirect == SnakeDirect::DOWN)
{
pix.load(":res/bd_D.png");
}
else if(moveDirect == SnakeDirect::LEFT)
{
pix.load(":res/bd_L.png");
}
else if(moveDirect == SnakeDirect::RIGHT)
{
pix.load(":res/bd_R.png");
}
for (int i=1;i<snakeList.size()-1;i++)
{
auto node = snakeList.at(i);
painter.drawPixmap(node.x(),node.y(),node.width(),node.height(),pix);
}
//绘制尾部
if(moveDirect ==SnakeDirect::UP)
{
pix.load(":res/tail.png");
}
else if(moveDirect == SnakeDirect::DOWN)
{
pix.load(":res/tail_D.png");
}
else if(moveDirect == SnakeDirect::LEFT)
{
pix.load(":res/tail_L.png");
}
else if(moveDirect == SnakeDirect::RIGHT)
{
pix.load(":res/tail_R.png");
}
auto snakeTail = snakeList.back();
painter.drawPixmap(snakeTail.x(),snakeTail.y(),snakeTail.width(),snakeTail.height(),pix);
//绘制食物
pix.load(":res/food.png");
painter.drawPixmap(foodRect.x(),foodRect.y(),kSnakeNodeWidth,kSnakeNodeHeight,pix);
//绘制分数
pix.load(":res/scores_bg.png");
painter.drawPixmap(920,4,230,150,pix);
QPen pen;
pen.setColor(Qt::black);
painter.setPen(pen);
QFont num("方正舒体",30);
painter.setFont(num);
painter.drawText(1000,95,QString("%1").arg(snakeList.size()));
//写入分数;
int n=snakeList.size();
QFile file("C:/Users/xcj/Desktop/snake/snake/his.txt");
if(file.open(QIODevice::WriteOnly))
{
QTextStream out(&file);
int num=n;
out<<num;//把num写入文件
file.close();
}
//绘制游戏结束
if(isOver())
{
pen.setColor(Qt::green);
painter.setPen(pen);
QFont over("华文琥珀",80);
painter.setFont(over);
painter.drawText(80,this->height()*0.5,QString("GAME OVER!"));
timer->stop();
QSound::play(":res/gameover.wav");
sound->stop();
}
}
void Game_room::moveUp()
{
QPointF leftTop;//左上角坐标
QPointF rightbutt;//右下角坐标
auto snakeNode = snakeList.front();//表示蛇头
int headx = snakeNode.x();
int heady = snakeNode.y();
if(heady<0)//穿墙时
{
leftTop = QPointF(headx,this->height()-kSnakeNodeHeight);
}
else
{
leftTop = QPointF(headx,heady-kSnakeNodeHeight);
}
rightbutt=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight);
snakeList.push_front(QRectF(leftTop,rightbutt));
}
void Game_room::moveDOWN()
{
QPointF leftTop;//左上角坐标
QPointF rightbutt;//右下角坐标
auto snakeNode = snakeList.front();//表示蛇头
int headx = snakeNode.x();
int heady = snakeNode.y();
if(heady>this->height())//穿墙时
{
leftTop = QPointF(headx,0);
}
else
{
leftTop = snakeNode.bottomLeft();//获取矩形左下角坐标
}
rightbutt=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight);
snakeList.push_front(QRectF(leftTop,rightbutt));
}
void Game_room::moveLEFT()
{
QPointF leftTop;//左上角坐标
QPointF rightbutt;//右下角坐标
auto snakeNode = snakeList.front();//表示蛇头
int headx = snakeNode.x();
int heady = snakeNode.y();
if(headx<0)//穿墙时
{
leftTop = QPointF(900-kSnakeNodeWidth,heady);
}
else
{
leftTop = QPointF(headx-kSnakeNodeWidth,heady);
}
rightbutt=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight);
snakeList.push_front(QRectF(leftTop,rightbutt));
}
void Game_room::moveRIGHT()
{
QPointF leftTop;//左上角坐标
QPointF rightbutt;//右下角坐标
auto snakeNode = snakeList.front();//表示蛇头
int headx = snakeNode.x();
int heady = snakeNode.y();
if(headx+kSnakeNodeWidth>880)//穿墙时
{
leftTop = QPointF(0,heady);
}
else
{
leftTop = snakeNode.topRight();
}
rightbutt=leftTop+QPointF(kSnakeNodeWidth,kSnakeNodeHeight);
snakeList.push_front(QRectF(leftTop,rightbutt));
}
bool Game_room::isOver()
{
for(int i=0;i<snakeList.size();i++)
{
for(int j=i+1;j<snakeList.size();j++)
{
if(snakeList.at(i) == snakeList.at(j))
{
return true;
}
}
}
return false;
}
void Game_room::createNewFood()
{
foodRect = QRectF(qrand()%(900/kSnakeNodeWidth)*kSnakeNodeWidth,
qrand()%(this->height()/kSnakeNodeHeight)*kSnakeNodeHeight,
kSnakeNodeWidth,kSnakeNodeHeight);
}