start.h
#ifndef START_H
#define START_H
#include <QWidget>
#include <QPushButton>
#include "widget.h"
class start : public QWidget
{
Q_OBJECT
public:
explicit start(QWidget *parent = nullptr);
signals:
public slots:
void changeWin();
private:
QPushButton b;
Widget sub;
protected:
void paintEvent(QPaintEvent*);
};
#endif // START_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QStackedWidget>
#include <QPaintEvent>
#include <QKeyEvent>
#include <QPainter>
#include <QDebug>
#include <QIcon>
#include <QTimer>
#include <QPushButton>
#include <QLineEdit>
#include <QGridLayout>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
void layout();
void game();
void keyPressEvent(QKeyEvent *event);
void keyReleaseEvent(QKeyEvent *event);
void paintEvent(QPaintEvent *);
void init(); //初始化
void start(); //开始游戏
void move(int len); //蛇身的行动逻辑
void food(); //食物的生成与获得判定
void is_dead(); //死亡判定
private slots:
void auto_move(); //蛇的自动行动
private:
QPainter Painter;
QTimer *timer;
QImage image_background;
QImage image_character1;
QImage image_character2;
QImage image_character3;
QImage image_character4;
QImage image_sword;
QImage image_gold;
int w; //画面的宽度
int h; //画面的高度
int speed; //刷新一次画面所需要的时间
int StartX; //蛇头的横坐标
int StartY; //蛇头的纵坐标
int X[1000]; //每个蛇身的横坐标
int Y[1000]; //每个蛇身的纵坐标
int LastX[1000]; //每个蛇身的前驱的横坐标
int LastY[1000]; //每个蛇身的前驱的纵坐标
int len = 0; //蛇的总长度
int flag = 1; //判断是否开始
int dead_flag = 0; //判断蛇是否死亡
int step=50; //地图每一格的边长
char dir; //当前蛇的前进方向
char next_dir; //下一时刻蛇的前进方向
int dir_flag = 0; //判断是否转向
int food_x; //食物横坐标
int food_y; //食物纵坐标
int food_flag = 0; //判断场上是否有食物
};
#endif // WIDGET_H
main.cpp
#include "widget.h"
#include "start.h"
#include <QApplication>
#include <QtMultimedia/QMediaPlayer>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
start w;
w.show();
return a.exec();
}
start.cpp
#include "start.h"
#include <QPainter>
#include <QSound>
start::start(QWidget *parent) : QWidget(parent)
{
this->setWindowTitle("开始界面");
b.setParent(this);
b.setGeometry(250,200,400,150);
b.setStyleSheet("QPushButton{border-image:url(:/Images/start.png);border-radius:5px;}");
QSound *sound=new QSound(":/Images/bgm.wav",this);
sound->setLoops(-1);
sound->play();
this->setFixedSize(900,600);
connect(&b,&QPushButton::released,this,&start::changeWin);
}
void start::changeWin()
{
sub.show();
this->hide();
}
void start::paintEvent(QPaintEvent *)
{
QPainter p(this);
p.drawPixmap(0,0,width(),height(),QPixmap(":/Images/background.jpg"));
}
widget.cpp
#include "widget.h"
#include <QMainWindow>
#include <QMessageBox>
#include <QSound>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
setWindowTitle(QString("贪吃蛇 当前得分:%1").arg(0));
this -> setFixedSize(1200,800);
image_character1.load(":/Images/LV1.png");
image_character2.load(":/Images/LV2.png");
image_character3.load(":/Images/LV3.png");
image_character4.load(":/Images/LV4.png");
image_sword.load(":/Images/sword.png");
image_gold.load(":/Images/gold.png");
image_background.load(":/Images/background.jpg");
image_character1 = image_character1.scaled(step,step);
image_character2 = image_character2.scaled(step,step);
image_character3 = image_character3.scaled(step,step);
image_character4 = image_character4.scaled(step,step);
image_sword = image_sword.scaled(step,step);
image_gold = image_gold.scaled(step,step);
image_background = image_background.scaled(1200,800);
}
Widget::~Widget(){}
void Widget::auto_move() //蛇的自动行动
{
if(dir_flag==1)
{
dir = next_dir;
dir_flag=0;
}
switch(dir)
{
case 'u': StartY-=step; if(StartY<0) StartY = h-step; break;
case 'd': StartY+=step; if(StartY>h-step) StartY = 0; break;
case 'l': StartX-=step; if(StartX<0) StartX = w-step; break;
case 'r': StartX+=step; if(StartX>w-step) StartX = 0; break;
}
move(len);
is_dead();
food();
update();
}
void Widget::food() //食物的生成与获得判定
{
int rand_x;
int rand_y;
if(StartX==food_x && StartY==food_y)
{
food_flag = 0;
len++;
if(len-1==15 || len-1==30 || len-1==45)
{
QSound *sound=new QSound(":/Images/levelup.wav",this);
sound->setLoops(1);
sound->play();
}
setWindowTitle(QString("贪吃蛇 当前得分:%1").arg(len-1));
}
while(food_flag==0)
{
int break_flag = 0;
rand_x = qrand()%(w/step)*step;
rand_y = qrand()%(h/step)*step;
if(rand_x==StartX && rand_y==StartY) continue;
for(int i=1; i<=len; i++)
{
if(rand_x==X[i] && rand_y==Y[i])
{
break_flag = 1;
break;
}
}
if(break_flag) continue;
food_x = rand_x;
food_y = rand_y;
food_flag = 1;
}
}
void Widget::start() //开始游戏
{
flag = 1;
dead_flag = 0;
}
void Widget::is_dead() //死亡判定
{
for(int i=1; i<=len-1; i++)
{
if(StartX==X[i] && StartY==Y[i])
{
timer -> stop();
dead_flag = 1;
int re = QMessageBox::information(this,"游戏结束!","您最终的得分为"+QString::number(len-1)+"。\n点击确认键重新开始游戏!",QMessageBox::Yes);
if(re==QMessageBox::Yes)
{
this -> start();
setWindowTitle(QString("贪吃蛇 当前得分:%1").arg(0));
}
}
}
}
void Widget::game()
{
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(auto_move()));
timer -> start(speed);
}
void Widget::init() //初始化
{
speed = 239;
w = width();
h = height();
StartX = 6*step;
StartY = 4*step;
game();
food();
dir = 'r';
len = 1;
LastX[0] = StartX;
LastY[0] = StartY;
}
void Widget::move(int len) //蛇身的行动逻辑
{
for(int i=1; i<=len; i++)
{
LastX[i] = X[i];
LastY[i] = Y[i];
X[i] = LastX[i-1];
Y[i] = LastY[i-1];
}
LastX[0] = StartX;
LastY[0] = StartY;
}
void Widget::keyPressEvent(QKeyEvent *event)
{
if(event->key()==Qt::Key_Left && dir!='r' && dir_flag==0)
{
next_dir = 'l';
dir_flag=1;
if(dir=='l' && dead_flag==0) //长按加速
{
timer -> stop();
timer -> start(speed/12);
}
}
if(event->key()==Qt::Key_Right && dir!='l' && dir_flag==0)
{
next_dir = 'r';
dir_flag=1;
if(dir=='r' && dead_flag==0)
{
timer -> stop();
timer -> start(speed/12);
}
}
if(event->key()==Qt::Key_Up && dir!='d' && dir_flag==0)
{
next_dir = 'u';
dir_flag=1;
if(dir=='u' && dead_flag==0)
{
timer -> stop();
timer -> start(speed/12);
}
}
if(event->key()==Qt::Key_Down && dir!='u' && dir_flag==0)
{
next_dir = 'd';
dir_flag=1;
if(dir=='d' && dead_flag==0)
{
timer -> stop();
timer -> start(speed/12);
}
}
update();
}
void Widget::keyReleaseEvent(QKeyEvent *event) //停止长按,变回原速度
{
if((event->key()==Qt::Key_Left || event->key()==Qt::Key_Right || event->key()==Qt::Key_Up || event->key()==Qt::Key_Down) && dead_flag==0)
{
timer -> stop();
timer -> start(speed);
}
}
void Widget::paintEvent(QPaintEvent *)
{
QPen Pen(Qt::DotLine);
Pen.setColor(Qt::blue);
Painter.begin(this);
Painter.drawImage(QPoint(0,0),image_background);
Painter.end();
for (int i=step;i<this->rect().width();i=i+step)
{
Painter.begin(this);
Painter.setPen(Pen);
Painter.drawLine(QPoint(i,0),QPoint(i,this->rect().height()));
Painter.end();
}
for (int j=step;j<this->rect().height();j=j+step)
{
Painter.begin(this);
Painter.setPen(Pen);
Painter.drawLine(QPoint(0,j),QPoint(this->rect().width(),j));
Painter.end();
}
if(flag==1)
{
init();
flag = 0;
}
Painter.begin(this);
if(len-1<15)
{
Painter.drawImage(QPoint(StartX,StartY),image_character1);
}
else if(len-1<30)
{
Painter.drawImage(QPoint(StartX,StartY),image_character2);
}
else if(len-1<45)
{
Painter.drawImage(QPoint(StartX,StartY),image_character3);
}
else
{
Painter.drawImage(QPoint(StartX,StartY),image_character4);
}
for(int i=1; i<=len-1; i++)
{
Painter.drawImage(QPoint(X[i],Y[i]),image_sword);
}
Painter.drawImage(QPoint(food_x,food_y),image_gold);
Painter.end();
}