widget.cpp #include "widget.h"
#include "ui_widget.h"
#include<QPainter>
#include<QIcon>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
setWindowTitle("贪吃蛇");
setFixedSize(600,360);
setWindowIcon(QIcon(":/img/snake.png"));
// 使用定时器
timer = new QTimer();
// 信号槽
connect(timer,SIGNAL(timeout()),this,SLOT(timeout()));
//设置窗口大小
resize(600,368);
//初始化蛇身
QRectF rect(300,180,nodewidth,nodeheight);
snake.append(rect);
addTop();
addTop();
//初始化奖品
addNewReword();
}
Widget::~Widget()
{
delete ui;
}
//控制方向
void Widget::keyPressEvent(QKeyEvent *event)
{
switch (event->key()) {
case Qt::Key_Up:
if(moveFlag != DIR_DOWN){
moveFlag = DIR_UP;
}
break;
case Qt::Key_Down:
if(moveFlag != DIR_UP){
moveFlag = DIR_DOWN;
}
break;
case Qt::Key_Right:
if(moveFlag != DIR_LEFT){
moveFlag = DIR_RIGHT;
}
break;
case Qt::Key_Left:
if(moveFlag!=DIR_RIGHT){
moveFlag = DIR_LEFT;
}
break;
case Qt::Key_Space:
if(!gamestart){
gamestart = true;
//启动定时器
timer->start(time);
}
else {
gamestart = false;
timer->stop();
}
break;
default:
break;
}
}
void Widget::timeout()
{
int count = 1;
//判断有没有重合
if(snake[0].intersects(rewardNode)){
count++;
addNewReword();
}
while(count--) {
switch (moveFlag) {
case DIR_UP:
//顶部加一个方块尾部删一个
addTop();
break;
case DIR_DOWN:
addDown();
break;
case DIR_LEFT:
addLeft();
break;
case DIR_RIGHT:
addRight();
break;
default:
break;
}
}
deleteLast();
update();
}
void Widget::addTop()
{
QPointF lefttop;
QPointF rightbotom;
if(snake[0].y()-nodeheight < 0)
{
lefttop=QPoint(snake[0].x(),this->height()-nodeheight);
rightbotom = QPointF(snake[0].x()+nodewidth,this->height());
}
else {
lefttop = QPointF(snake[0].x(),snake[0].y()-nodeheight);
rightbotom = snake[0].topRight();
}
snake.insert(0,QRectF(lefttop,rightbotom));
}
void Widget::addDown()
{
QPointF lefttop;
QPointF rightbotom;
if(snake[0].y()+nodeheight+nodeheight > this->height()){
lefttop = QPointF(snake[0].x(),0);
rightbotom = QPointF(snake[0].x()+nodewidth,nodeheight);
}else {
lefttop = snake[0].bottomLeft();
rightbotom = snake[0].bottomRight()+QPointF(0,nodeheight);
}
snake.insert(0,QRectF(lefttop,rightbotom));
}
void Widget::addLeft()
{
QPointF lefttop;
QPointF rightbotom;
if(snake[0].x()-nodewidth<0){
lefttop = QPointF(this->width()-nodewidth,snake[0].y());
} else {
lefttop = snake[0].topLeft()-QPointF(nodewidth,0);
}
rightbotom = lefttop+QPointF(nodewidth,nodeheight);
snake.insert(0,QRectF(lefttop,rightbotom));
}
void Widget::addRight()
{
QPointF lefttop;
QPointF rightbotom;
if(snake[0].x()+nodewidth+nodewidth>this->width()){
lefttop = QPointF(0,snake[0].y());
} else {
lefttop = snake[0].topRight();
}
rightbotom = lefttop+QPointF(nodewidth,nodeheight);
snake.insert(0,QRectF(lefttop,rightbotom));
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
QPen pen;
QBrush brush;
//设置背景图片
QPixmap pix;
pix.load("D:/Picture/aa.jpg");
painter.drawPixmap(0,0,600,368,pix);
//画蛇
pen.setColor(Qt::black);
brush.setColor(Qt::green);
brush.setStyle(Qt::SolidPattern); //实心填充
painter.setPen(pen);
painter.setBrush(brush);
for(int i=0;i<snake.length();i++)
{
painter.drawRect(snake[i]);
}
//画奖品
pen.setColor(Qt::red);
brush.setColor(Qt::red);
brush.setStyle(Qt::SolidPattern); //实心填充
painter.setPen(pen);
painter.setBrush(brush);
//painter.drawRect(rewardNode);
painter.drawEllipse(rewardNode);
if(checkcontact()){
pen.setColor(Qt::black);
QFont font("微软雅黑",30,QFont::ExtraLight,false);
painter.setFont(font);
painter.setPen(pen);
painter.drawText((this->width()-300)/2,
(this->height()-30)/2,
QString("GAME OVER!"));
timer->stop();
}
QWidget::paintEvent(event);
}
void Widget::deleteLast()
{
snake.removeLast();
}
void Widget::addNewReword()
{
rewardNode = QRectF(
qrand()%(this->width()/20)*20,
qrand()%(this->height()/20)*20,
nodewidth,nodeheight);
}
bool Widget::checkcontact()
{
for(int i=0;i<snake.length();i++)
for(int j=i+1;j<snake.length();j++)
{
if(snake[i] == snake[j])
{
return true;
}
}
return false;
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QKeyEvent>
#include<QTimer>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
//蛇的表示
//
// 按键处理
// 使用定时器
//关联信号槽
//启动定时器
//实现槽函数
// 渲染
enum Direc{
DIR_LEFT,
DIR_RIGHT,
DIR_UP,
DIR_DOWN
};
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
protected:
//渲染,绘图
void paintEvent(QPaintEvent *event);
void addTop();
void addDown();
void addLeft();
void addRight();
void addNewReword();
bool checkcontact();
//按键处理
void keyPressEvent(QKeyEvent *event);
//删除小方块
void deleteLast();
private:
Ui::Widget *ui;
int moveFlag = DIR_UP;
bool gamestart = false;
//定时器
QTimer *timer;
int time=100; //超时时间,毫秒
//蛇的表示
QList <QRectF> snake; //QRectF表示一块区域
//奖品
QRectF rewardNode;
//小方块宽高
int nodewidth = 20;
int nodeheight = 20;
protected slots: //槽函数
void timeout();
};
#endif // WIDGET_H
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}