Qt版贪吃蛇游戏
转载请标明出处:牟尼的专栏 http://blog.csdn.net/u012027907
最近在学习Qt,用了一个多月的时间掌握了Qt中最基本的知识,也完成了《Qt版音乐播放器》、《Qt版贪吃蛇游戏》、《Qt版双人俄罗斯方块》以及《Qt版科学计算器》等,之前在VC下写过这些程序,所以在Qt下只是改变了显示等语句,我写过《C++版贪吃蛇游戏》、《VC版贪吃蛇游戏》,当时将与显示等无关的东西封装起来,在Qt下直接用,只改变了显示等语句。
以下是Windows 7下运行截图:
以下是Ubuntu下运行截图:
我在Windows下编写好之后,将源码在Ubuntu下重新编译运行,就可以在Ubuntu下运行,这也充分体现出Qt一次编写,到处运行的优势。
关于贪吃蛇游戏的设计原理就不讲了,具体可以参考我的博客《C++版贪吃蛇游戏》、《VC版贪吃蛇游戏》。
下面主要说一下Qt与VC不同的东西。
先看头文件中变量以及槽的定义:
class Snake : public QMainWindow
{
Q_OBJECT
public:
explicit Snake(QWidget *parent = 0);
~Snake();
private slots:
void gameStart();
void onPause();
void superSpeed();
void fastSpeed();
void midSpeed();
void slowSpeed();
void verySlowSpeed();
private:
Ui::Snake *ui;
int image[20][20]; //游戏面板,即小蛇活动范围
int FoodX; //事物出现的X坐标
int FoodY; //事物出现的Y坐标
int snakeX; //记录小蛇的头部X坐标
int snakeY; //记录小蛇的头部Y坐标
int head; //小蛇头部下标
int tail; //小蛇尾部下标
int snake[2][20000]; //记录小蛇所有身体的坐标
int node; //小蛇的节数
int direction; //小蛇头部的方向
int i,j;
int gamespeed; //速度
int score; //记录分数
bool IsPause; //暂停
bool p;
int GameOver; //使游戏结束的变量
int level; //设置等级
int length; //为了设置等级而与node一样记录设的长度
int timerID;
/////////////
void ReInit();
int DrawSnake(); //记录小蛇每次移动后头部及身体的下一坐标
void Automove(); //使小蛇自动移动
int Gameover(); //判断游戏是否结束
int Generatefood(); //产生食物
void shiftLeft(); //控制左移
void shiftRight(); //控制右移
void shiftDown(); //控制下移
void shiftUp(); //控制上移
protected:
void keyPressEvent(QKeyEvent *event);
void timerEvent(QTimerEvent *event);
void paintEvent(QPaintEvent *event);
};
void keyPressEvent(QKeyEvent *event);
void timerEvent(QTimerEvent *event);
void paintEvent(QPaintEvent *event);
三个槽的实现是Qt的方式。
转载请标明出处:牟尼的专栏 http://blog.csdn.net/u012027907
具体代码如下:
/////////////////////////////////////////////
void Snake::keyPressEvent(QKeyEvent *event)
{
if(direction == 2 || direction == 8)
{
if(event->key() == Qt::Key_Right)
shiftRight();
else if(event->key() == Qt::Key_Left)
shiftLeft();
else if(event->key() == Qt::Key_0)
onPause();
}
else if(direction == 4 || direction == 6)
{
if(event->key() == Qt::Key_Up)
shiftUp();
else if(event->key() == Qt::Key_Down)
shiftDown();
else if(event->key() == Qt::Key_0)
onPause();
}
}
void Snake::timerEvent(QTimerEvent *event)
{
if(event->timerId() == timerID)
{
if(!GameOver)
{
if(!IsPause)
Automove(); // 小蛇自动移动
Gameover(); //判断游戏是否结束
if(GameOver==1)
{
killTimer(timerID);
if(level>8)
if(QMessageBox::question(this,tr("提示"),tr("你一定是骨灰级玩家!小弟佩服!还想挑战吗?"),QMessageBox::Yes,QMessageBox::No) == QMessageBox::Yes)
{
ReInit();
gameStart();
}
else
close();
else if(level>5)
if(QMessageBox::question(this,tr("提示"),tr("你一定是高手!还想挑战吗?"),QMessageBox::Yes,QMessageBox::No) == QMessageBox::Yes)
{
ReInit();
gameStart();
}
else
close();
else if(QMessageBox::question(this,tr("提示"),tr("继续努力!还想挑战吗?"),QMessageBox::Yes,QMessageBox::No) == QMessageBox::Yes)
{
ReInit();
gameStart();
}
else
close();
}
DrawSnake(); //判断是否吃食物
}
this->repaint();
}
}
void Snake::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
int nSize = 20;
int offset = 1;
QImage img;
img.load(":/images/border.png");
QBrush brushborder(img);
painter.setBrush(brushborder);
QRect bottomrec(0,nSize*22+offset,nSize*22,nSize);
painter.fillRect(bottomrec,brushborder);
QRect toprec(0,20+offset,nSize*22,nSize);
painter.fillRect(toprec,brushborder);
QRect leftrec(0,20+offset,nSize,nSize*21);
painter.fillRect(leftrec,brushborder);
QRect rightrec(nSize*21,20+offset,nSize,nSize*21);
painter.fillRect(rightrec,brushborder);
QRect rect(20,40+offset,nSize*20,nSize*20);
QImage imageBack;
imageBack.load(":/images/grass.png");
QBrush brushBack(imageBack);
painter.setBrush(brushBack);
painter.drawRect(rect);
QRect rc;
QBrush brush(QColor(255,0,0));
painter.setBrush(brush);
QString Level = "Level:";
Level += QString::number(level);
ui->label_Level->setText(Level);
QString Score = "Score:";
Score += QString::number(score);
ui->label_Score->setText(Score);
for(i=0;i<20;i++)
{
for(j=0;j<20;j++)
{
rc = QRect(j*nSize+20,i*nSize+40+offset,nSize,nSize);
if(image[i][j]!=0)
{
if(image[i][j]==3)
{
QImage img;
img.load(":/images/body.png");
QBrush brush(img);
painter.setBrush(brush);
painter.fillRect(rc,brush);
}
else if(image[i][j] == 1)
{
if(direction==2)
{
QImage img;
img.load(":/images/headdown.png");
QBrush brush(img);
painter.setBrush(brush);
painter.fillRect(rc,brush);
}
else if(direction == 4)
{
QImage img;
img.load(":/images/headleft.png");
QBrush brush(img);
painter.setBrush(brush);
painter.fillRect(rc,brush);
}
else if(direction == 6)
{
QImage img;
img.load(":/images/headright.png");
QBrush brush(img);
painter.setBrush(brush);
painter.fillRect(rc,brush);
}
else
{
QImage img;
img.load(":/images/headup.png");
QBrush brush(img);
painter.setBrush(brush);
painter.fillRect(rc,brush);
}
}
else if(image[i][j] == 2)
{
QImage img;
img.load(":/images/apple.png");
QBrush brush(img);
painter.setBrush(brush);
painter.fillRect(rc,brush);
}
}
}
}
}
//////////////////////////////////////////////////////////////////////
/////////////////////////////////////////
connect(ui->action_startGame, SIGNAL(triggered()), this, SLOT(gameStart()));
connect(ui->action_pause, SIGNAL(triggered()) ,this, SLOT(onPause()));
connect(ui->action_quit, SIGNAL(triggered()), this, SLOT(close()));
connect(ui->action_veryFast, SIGNAL(triggered()), this, SLOT(superSpeed()));
connect(ui->action_fast, SIGNAL(triggered()), this, SLOT(fastSpeed()));
connect(ui->action_mid, SIGNAL(triggered()), this, SLOT(midSpeed()));
connect(ui->action_slow, SIGNAL(triggered()), this, SLOT(slowSpeed()));
connect(ui->action_verySlow, SIGNAL(triggered()), this, SLOT(verySlowSpeed()));
//产生食物
int Snake::Generatefood()
{
qsrand(QTime::currentTime().msec()); //以时间为种子生成随机序列
do{
FoodX=qrand()%20; //食物输出的X坐标
FoodY=qrand()%20; //食物输出的Y坐标
}while(image[FoodX][FoodY]!=0); //产生的食物坐标限定在游戏面板内,且食物坐标不与小蛇身体坐标重合
image[FoodX][FoodY]=2;
return image[FoodX][FoodY];
}