源码素材下载:http://download.csdn.net/download/u011314012/10191968
1、开机界面 第一个按键为开始按键,第二个按键为退出按键,当点击时提示是否退出。
2、点击开始按键时进入游戏界面,游戏的等级和分数可以自己去设置,细节问题,自己可以去调试。
贪吃蛇的难点,就是蛇的移动,与绘制蛇身蛇尾。代码里面有备注。
main.cpp
#include "mainwidget.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
mainWidget w;
w.show();
return a.exec();
}
mainwidget.h
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include
#include
#include//调色板
#include//笔刷
#include
#include
#include
#include "gamewidget.h"
class mainWidget : public QWidget
{
Q_OBJECT
public:
mainWidget(QWidget *parent = 0);
~mainWidget();
/*只能在类的成员函数中访问*/
private:
QPushButton *startbtn;
QPushButton *exitbtn;
GameWidget *gamewidget; //游戏区
public slots:
void startbtn_click();
void exitbtn_click();
};
#endif // MAINWIDGET_H
mainwidget.cpp
#include "mainwidget.h"
mainWidget::mainWidget(QWidget *parent)
: QWidget(parent)
{
//设置主窗口大小
this->resize (480, 310);
//设置标题
this->setWindowIcon (QIcon("img/icon.png"));
this->setWindowTitle (tr("贪吃蛇"));
//设置背景色(并且对图片进行缩放)
QPalette palette;
palette.setBrush (QPalette::Background, QBrush(QPixmap("img/back.jpg").scaled (this->size ())));
this->setPalette (palette);
startbtn = new QPushButton(this);
//开始按钮图标
startbtn->setIcon (QIcon("img/start.png"));
startbtn->setIconSize (QSize(80, 80));
//设置按键的坐标x, y, w, h
startbtn->setGeometry (QRect(250, 190, 72, 72));
//消除按钮的边框
startbtn->setFlat (true);
exitbtn = new QPushButton(this);
//退出按钮图标
exitbtn->setIcon (QIcon("img/quit.png"));
exitbtn->setIconSize (QSize(70, 70));
//设置按钮的坐标x, y, w, h
exitbtn->setGeometry (QRect(350, 190, 70, 70));
//消除按钮的边框
exitbtn->setFlat (true);
this->connect(startbtn, SIGNAL(clicked(bool)), this, SLOT(startbtn_click()));
this->connect (exitbtn, SIGNAL(clicked(bool)), this, SLOT(exitbtn_click()));
}
/*对象消耗完自动调用析构函数*/
mainWidget::~mainWidget()
{
/*释放空间防止内存泄露*/
delete startbtn;
delete exitbtn;
}
/*按键控制开始函数*/
void mainWidget::startbtn_click ()
{
gamewidget = new GameWidget(this);
gamewidget->show ();
}
/*按键控制退出函数*/
void mainWidget::exitbtn_click ()
{
/*静态成员函数,可以用::直接引用*/
if(QMessageBox::question (this, tr("提示"), tr("您是否要退出?"),
QMessageBox::Ok | QMessageBox::Yes) == QMessageBox::Yes)
{
delete this; //释放自己的资源
exit(0);
}
}
gamewidget.h
#ifndef GAMEWIDGET_H
#define GAMEWIDGET_H
#include
#include
#include
#include//调色板
#include//笔刷
#include
#include
#include//引用画笔
#include
#include
#include
#include
#include
#include
#include
#include
class GameWidget : public QWidget
{
Q_OBJECT
public:
explicit GameWidget(QWidget *parent = 0);
//重载虚函数
void paintEvent(QPaintEvent *);
private:
QLabel *score_label;
QLabel *level_label;
QLineEdit *score_lineEdit;
QLineEdit *level_lineEdit;
QPushButton *leftbtn;
QPushButton *rightbtn;
QPushButton *upbtn;
QPushButton *downbtn;
QPushButton *startbtn;
QPushButton *returnbtn;
QPushButton *stopbtn;
QPushButton *gameoverbtn;
QFont ft;
int direction; //蛇移动的方向
//画食物
int foodx;
int foody;
int foodcount;
int score;
int level;
QTimer *timer;
int snake[100][2]; //保存蛇的每个节点的坐标
int snake1[100][2]; //备份坐标数组
void change_score(int count);
public slots:
void leftbtn_click();
void rightbtn_click();
void upbtn_click();
void downbtn_click();
void startbtn_click();
void stopbtn_click();
void returnbtn_click();
void timeroutslot();
void change_level();
};
#endif // GAMEWIDGET_H
gamewidget.cpp
#include "gamewidget.h"
#define ROW 15
#define COL 15
#define UP 0
#define DOWN 1
#define LEFT 2
#define RIGHT 3
GameWidget::GameWidget(QWidget *parent)
: QWidget(parent)
, direction(0)
, foodx(0)
, foody(0)
, foodcount(0)
, score(0)
, level(1)
{
this->setAutoFillBackground (true);//覆盖父窗口
//设置主窗口大小
this->resize (480, 310);
//设置标题
this->setWindowIcon (QIcon("img/icon.png"));
this->setWindowTitle (tr("贪吃蛇"));
//设置背景色(并且对图片进行缩放)
QPalette palette;
palette.setBrush (QPalette::Background, QBrush(QPixmap("img/green.jpg").scaled (this->size ())));
this->setPalette (palette);
//分数
score_label = new QLabel("score:", this);
ft.setPointSize (16);
score_label->setFont (ft);
score_label->setGeometry (310, 8, 80, 35);
score_lineEdit = new QLineEdit(this);
ft.setPointSize (16);
score_lineEdit->setFont (ft);
score_lineEdit->setAlignment (Qt::AlignRight);
score_lineEdit->setGeometry (390, 8, 80, 35);
//等级
level_label = new QLabel("level:", this);
ft.setPointSize (16);
level_label->setFont (ft);
level_label->setGeometry (310, 50, 80, 35);
level_lineEdit = new QLineEdit(this);
ft.setPointSize (16);
level_lineEdit->setFont (ft);
level_lineEdit->setAlignment (Qt::AlignRight);
level_lineEdit->setGeometry (390, 50, 80, 35);
//按钮
upbtn = new QPushButton("↑", this);
upbtn->setGeometry (373, 115, 40, 30);
leftbtn = new QPushButton("←", this);
leftbtn->setGeometry (328, 155, 40, 30);
downbtn = new QPushButton("↓", this);
downbtn->setGeometry (373, 195, 40, 30);
rightbtn = new QPushButton("→", this);
rightbtn->setGeometry (418, 155, 40, 30);
startbtn = new QPushButton("开始", this);
startbtn->setGeometry (315, 245, 50, 30);
stopbtn = new QPushButton("停止", this);
stopbtn->setGeometry (370, 245, 50, 30);
returnbtn = new QPushButton("返回", this);
returnbtn->setGeometry (425, 245, 50, 30);
connect (leftbtn, SIGNAL(clicked(bool)), this, SLOT(leftbtn_click()));
connect (rightbtn, SIGNAL(clicked(bool)), this, SLOT(rightbtn_click()));
connect (upbtn, SIGNAL(clicked(bool)), this, SLOT(upbtn_click()));
connect (downbtn, SIGNAL(clicked(bool)), this, SLOT(downbtn_click()));
connect (returnbtn, SIGNAL(clicked(bool)), this, SLOT(returnbtn_click()));
connect (startbtn, SIGNAL(clicked(bool)), this, SLOT(startbtn_click()));
connect (stopbtn, SIGNAL(clicked(bool)), this, SLOT(stopbtn_click()));
connect (level_lineEdit, SIGNAL(textEdited(QString)), this, SLOT(change_level()));
//产生行列存储坐标
snake[0][0] = qrand () % COL; //行存储
snake[0][1] = qrand () % ROW; //列存储
direction = qrand () % 4; //方向控制
//产生食物
int i;
do{
i++;
foodx = qrand () % COL;
foody = qrand() % ROW;
}while(foodx == snake[i][0] && foody == snake[i][1]);
timer = new QTimer(this);
connect (timer, SIGNAL(timeout()), this, SLOT(timeroutslot()));
}
//绘图事件
void GameWidget::paintEvent (QPaintEvent *)
{
int i, j;
QPainter painter(this);
//绘制游戏区
for(i = 0; i < ROW; i++)
{
for(j = 0; j < COL; j++)
{
painter.drawRect (QRect(i * 20, j * 20, 20, 20));
}
}
painter.drawImage (QRectF(foodx*20, foody*20, 20, 20), QImage("img/apple.png"));
//蛇头
switch(direction)
{
case UP:
painter.drawImage (QRectF(snake[0][0] * 20, snake[0][1] * 20, 20, 20), QImage("img/headup.png"));
break;
case DOWN:
painter.drawImage (QRectF(snake[0][0] * 20, snake[0][1] * 20, 20, 20), QImage("img/headdown.png"));
break;
case LEFT:
painter.drawImage (QRectF(snake[0][0] * 20, snake[0][1] * 20, 20, 20), QImage("img/headleft.png"));
break;
case RIGHT:
painter.drawImage (QRectF(snake[0][0] * 20, snake[0][1] * 20, 20, 20), QImage("img/headright.png"));
break;
default: break;
}
//画蛇身
for(i = 1; i < foodcount; i++)
{
//右下
if((snake[i][1] == snake[i - 1][1] && snake[i - 1][0] < snake[i][0] &&
snake[i + 1][0] == snake[i][0] && snake[i + 1][1] < snake[i][1]) ||
(snake[i - 1][0] == snake[i][0] && snake[i - 1][1] < snake[i][1] &&
snake[i][1] == snake[i + 1][1] && snake[i + 1][0] < snake[i][0] ))
{
painter.drawImage (QRectF(snake[i][0] * 20, snake[i][1] * 20, 20, 20), QImage("img/br_corner.png"));
}//右上
else if((snake[i][0] == snake[i - 1][0] && snake[i][1] < snake[i - 1][1] &&
snake[i + 1][1] == snake[i][1] && snake[i + 1][0] < snake[i][0]) ||
(snake[i - 1][1] == snake[i][1] && snake[i - 1][0] < snake[i][0] &&
snake[i][0] == snake[i + 1][0] && snake[i][1] < snake[i + 1][1] ))
{
painter.drawImage (QRectF(snake[i][0] * 20, snake[i][1] * 20, 20, 20), QImage("img/tr_corner.png"));
}//左下
else if((snake[i][0] < snake[i - 1][0] && snake[i][1] == snake[i - 1][1] &&
snake[i + 1][1] < snake[i][1] && snake[i][0] == snake[i + 1][0]) ||
(snake[i - 1][1] < snake[i][1] && snake[i][0] == snake[i - 1][0] &&
snake[i][0] < snake[i + 1][0] && snake[i][1] == snake[i + 1][1] ))
{
painter.drawImage (QRectF(snake[i][0] * 20, snake[i][1] * 20, 20, 20), QImage("img/bl_corner.png"));
}
//左上
else if((snake[i][0] == snake[i - 1][0] && snake[i][1] < snake[i - 1][1] &&
snake[i][1] == snake[i + 1][1] && snake[i][0] < snake[i + 1][0]) ||
(snake[i][1] == snake[i - 1][1] && snake[i][0] < snake[i - 1][0] &&
snake[i][0] == snake[i + 1][0] && snake[i][1] < snake[i + 1][1] ))
{
painter.drawImage (QRectF(snake[i][0] * 20, snake[i][1] * 20, 20, 20), QImage("img/tl_corner.png"));
}/*水平方向*/
else if(snake[i][1] == snake[i - 1][1] && snake[i][0] != snake[i - 1][0])
{
painter.drawImage (QRectF(snake[i][0] * 20, snake[i][1] * 20, 20, 20), QImage("img/h_body.png"));
}/*垂直方向*/
else if(snake[i][1] != snake[i - 1][1] && snake[i][0] == snake[i - 1][0])
{
painter.drawImage (QRectF(snake[i][0] * 20, snake[i][1] * 20, 20, 20), QImage("img/v_body.png"));
}
}
//蛇尾
if((snake[foodcount][1] == snake[foodcount - 1][1] && snake[foodcount][0] < snake[foodcount - 1][0]) )
{
painter.drawImage (QRectF(snake[foodcount][0] * 20, snake[foodcount][1] * 20, 20, 20), QImage("img/tailright.png"));
}
else if(snake[foodcount][1] == snake[foodcount - 1][1] && snake[foodcount - 1][0] < snake[foodcount][0])
{
painter.drawImage (QRectF(snake[foodcount][0] * 20, snake[foodcount][1] * 20, 20, 20), QImage("img/tailleft.png"));
}
else if((snake[foodcount][0] == snake[foodcount - 1][0] && snake[foodcount][1] < snake[foodcount - 1][1]))
{
painter.drawImage (QRectF(snake[foodcount][0] * 20, snake[foodcount][1] * 20, 20, 20), QImage("img/taildown.png"));
}
else if((snake[foodcount][0] == snake[foodcount - 1][0] && snake[foodcount - 1][1] < snake[foodcount][1]))
{
painter.drawImage (QRectF(snake[foodcount][0] * 20, snake[foodcount][1] * 20, 20, 20), QImage("img/tailup.png"));
}
}
//时间到的槽函数
void GameWidget::timeroutslot ()
{
int i = 0;
//是否吃到食物
if(snake[0][0] == foodx && snake[0][1] == foody)
{
//更新食物坐标
do{
i++;
foodx = qrand () % COL;
foody = qrand() % ROW;
}while(foodx == snake[i][0] && foody == snake[i][1]);
//改变分数函数
change_score(++foodcount);
}
//保存数据
memcpy (snake1, snake, sizeof(snake));
//改变蛇的每一节身子坐标
for(i = foodcount; i > 0; i--)
{
snake[i][0] = snake[i - 1][0];
snake[i][1] = snake[i - 1][1];
}
switch(direction)
{
case UP:
snake[0][1]--;
break;
case DOWN:
snake[0][1]++;
break;
case LEFT:
snake[0][0]--;
break;
case RIGHT:
snake[0][0]++;
break;
default: break;
}
//蛇边界检测
if(snake[0][0] < 0 || snake[0][0] >= COL || snake[0][1] < 0 || snake[0][1] >= ROW)
{
//恢复数据
memcpy (snake, snake1, sizeof(snake));
/*静态成员函数,可以用::直接引用*/
if(QMessageBox::question (this, tr("提示"), tr("GAME OVER"),
QMessageBox::Yes) == QMessageBox::Yes)
{
this->close ();
delete this; //释放自己的资源
return; //结束这个函数
}
}
//蛇自杀检测
if(foodcount >= 3)
{
for(i = 3; i <= foodcount; i++)
{
if(snake[0][0] == snake[i][0] && snake[0][1] == snake[i][1])
{
//恢复数据
memcpy (snake, snake1, sizeof(snake));
/*静态成员函数,可以用::直接引用*/
if(QMessageBox::question (this, tr("提示"), tr("GAME OVER"),
QMessageBox::Yes) == QMessageBox::Yes)
{
this->close ();
delete this; //释放自己的资源
return; //结束这个函数
}
}
}
}
this->update ();
}
void GameWidget::upbtn_click ()
{
direction = UP;
}
void GameWidget::downbtn_click ()
{
direction = DOWN;
}
void GameWidget::leftbtn_click ()
{
direction = LEFT;
}
void GameWidget::rightbtn_click ()
{
direction = RIGHT;
}
void GameWidget::startbtn_click ()
{
//这个地方可以设置级别(通过改变蛇的移动时间)
if(level == 1)
{
timer->start (800);
}
else if(level == 2)
{
timer->start (600);
}else if(level == 3)
{
timer->start(400);
}else if(level == 4)
{
timer->start (200);
}
level_lineEdit->setText (QString(tr("%1")).arg (level));
}
void GameWidget::returnbtn_click ()
{
//删除GameWidget的this指针
delete this;
}
void GameWidget::stopbtn_click ()
{
timer->stop ();
}
void GameWidget::change_level ()
{
bool ok;
int level1 = QInputDialog::getInt (this, tr("标准int类型输入对话框"),
tr("请输入等级1-3"), level_lineEdit->text ().toInt (&ok), 1, 4, 1, &ok);
if(ok)
{
level = level1;
level_lineEdit->setText (QString(tr("%1")).arg (level));
}
else
{
level_lineEdit->setText (QString(tr("%1")).arg (level));
}
}
/*计算成绩*/
void GameWidget::change_score (int count)
{
/*foodcount = 10 一级
foodcount = 15 二级
foodcount = 20 三级
foodcount = 25 四级*/
if(count >= 1 && count <= 10)
{
level = 1;
score = count * 10;
level_lineEdit->setText (QString(tr("%1")).arg (level));
score_lineEdit->setText (QString(tr("%1")).arg (score));
}
else if(count > 10 && count <= 15)
{
level = 2;
score = (count - 10) * 15 + 100 ;
level_lineEdit->setText (QString(tr("%1")).arg (level));
score_lineEdit->setText (QString(tr("%1")).arg (score));
}
else if(count > 15 && count <= 20)
{
level = 3;
score = (count - 15) * 20 + 175 ;
level_lineEdit->setText (QString(tr("%1")).arg (level));
score_lineEdit->setText (QString(tr("%1")).arg (score));
}
else if(count > 20 && count <= 25)
{
level = 4;
score = (count - 20) * 20 + 275 ;
level_lineEdit->setText (QString(tr("%1")).arg (level));
score_lineEdit->setText (QString(tr("%1")).arg (score));
} /*静态成员函数,可以用::直接引用*/
else if(QMessageBox::question (this, tr("提示"), tr("You are very good!"),
QMessageBox::Yes) == QMessageBox::Yes)
{
this->close ();
delete this; //释放自己的资源
return; //结束这个函数
}
}