QT实现贪吃蛇
1.Snake类
#define SNAKE_H
#include <mutex>
#include <iostream>
#include <stdlib.h>
#include <list>
#include <QRect>
using namespace std;
class Snake
{
public:
static Snake* instandite();//顺便做了一个单例
void setBody(int count){
}
void setSpeed(int speed){
//this->m_speed = speed;
}
public:
list<QRect> list_body;//蛇身
QRect m_head; //蛇头
int GetLenth();
int m_direction;//运动方向 1234 上下左右
private:
Snake();
Snake(Snake&)=delete;
Snake &operator= (Snake&)=delete;
static Snake* p;
static mutex tex;
private:
int m_lenth;
int int_speed;//设置速度,调节难度 1~5,也就是定时器刷新得时间
};
#endif // SNAKE_H
/*************下面是cpp*****************/
#include "snake.h"
mutex Snake::tex;
Snake* Snake::p=nullptr;
Snake::Snake()
{
m_head = QRect(300,330,10,10);
list_body.push_back(QRect(300,320,10,10));
list_body.push_back(QRect(300,310,10,10));
list_body.push_back(QRect(300,300,10,10));
m_direction = 2; //初始默认向下运动
}
Snake* Snake::instandite()//顺便做的单例,练练手
{
if(nullptr == p)
{
tex.lock();
p = new Snake();
tex.unlock();
}
return p;
}
int Snake::GetLenth()
{
list<QRect>::iterator p = this->list_body.begin();
int count = 0;
for(p;p!=this->list_body.end();p++)
{
count++;
}
return count;
}
MainWindow界面
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPainter>
#include <QMessageBox>
#include <QKeyEvent>
#include <stdlib.h>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
psnake = Snake::instandite();
ptime = new QTimer;
connect(ptime,SIGNAL(timeout()),this,SLOT(refresh())); //启动定时器,每秒刷新snake
randRect = QRect(300,400,10,10);
srand((unsigned)time(NULL));
ptime->start(200);
num = 0;
}
通过定时器实现蛇得运动
void MainWindow::refresh()
{
list<QRect>::iterator pbegin = psnake->list_body.begin();
QRect rect;
QRect temprect = *pbegin;
QRect temphead = psnake->m_head;
psnake->list_body.pop_back();//删除最后一节身体
if(psnake->m_direction == 1)//向上运动
{
rect = QRect(psnake->m_head);
psnake->m_head = QRect(temphead.left(),temphead.top()-10,10,10);
psnake->list_body.push_front(rect);
}
else if(psnake->m_direction == 2)//向下运动
{
rect = QRect(psnake->m_head);
psnake->m_head = QRect(temphead.left(),temphead.top()+10,10,10);
psnake->list_body.push_front(rect);
}
else if(psnake->m_direction == 3)//向左运动
{
rect = QRect(psnake->m_head);
psnake->m_head = QRect(temphead.left()-10,temphead.top(),10,10);
psnake->list_body.push_front(rect);
}
else//向右运动
{
rect = QRect(psnake->m_head);
psnake->m_head = QRect(temphead.left()+10,temphead.top(),10,10);
psnake->list_body.push_front(rect);
}
if(temphead.left()==randRect.left()&&temphead.top()==randRect.top())
{
psnake->list_body.push_front(randRect);
num++;
QString text =QString("当前得分:%1").arg(num);
ui->label->setText(text);
randRect = QRect((rand() % 50)*10,(rand() % 40)*10,10,10);
}
if(isLose()==0)
return;
update();
}
重写paintevent,绘制蛇身蛇头和奖励点
void MainWindow::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setPen(Qt::black);
painter.setBrush(Qt::green);
list<QRect>::iterator p = psnake->list_body.begin();
painter.drawRect(psnake->m_head);
for(p;p!=psnake->list_body.end();p++)
{
painter.drawRect(*p);
}
painter.fillRect(randRect,Qt::red);
}
控制蛇得运动,重写键盘控制事件
void MainWindow::keyPressEvent(QKeyEvent *ev)//键盘按下事件
{
if(ev->key() == Qt::Key_D)
{
if(psnake->m_direction == 3)//判断如果蛇向右运动,那么屏蔽向左得按键
return ;
psnake->m_direction = 4;
return;
}
if(ev->key() == Qt::Key_A)
{
if(psnake->m_direction == 4)
return ;
psnake->m_direction = 3;
return;
}
if(ev->key() == Qt::Key_S)
{
if(psnake->m_direction == 1)
return ;
psnake->m_direction = 2;
return;
}
if(ev->key() == Qt::Key_W)
{
if(psnake->m_direction == 2)
return ;
psnake->m_direction = 1;
return;
}
}
判断是否游戏失败,1.碰到身体,2.碰到墙壁
int MainWindow::isLose()
{
QRect rect = psnake->m_head;
if(rect.left()>600||rect.left()<=-1||rect.bottom()<=-1||rect.bottom()>500)//碰到边界
{
ptime->stop();
QMessageBox::information(NULL, "Title", "Game Over", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
return 0;
}
if(isTouchBody())//碰到身体
{
ptime->stop();
QMessageBox::information(NULL, "Title", "Game Over", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
return 0;
}
return 1;
}
bool MainWindow::isTouchBody()
{
list<QRect>::iterator pbegin = psnake->list_body.begin();
for(pbegin;pbegin!=psnake->list_body.end();pbegin++)
{
if(psnake->m_head==*pbegin)
return true;//碰到身体
}
return false;
}
这里得messageBox可以自己重写,失败后可以重新开始游戏,可以用回调函数得思想写messageBox。
写这个得目的主要是为了锻炼面向对象,这里面向对象思想用的不好,很多地方需要改善,只有去练习,才能知道哪里做的不好。