windworld-18984 发表于 2017-2-20 17:45:31

【UP-Board试用】+基于Qt的贪吃蛇小游戏设计

本帖最后由 windworld-1898442 于 2017-2-20 18:10 编辑

   前面再系统上搭建了Qt的开发环境,所以这里和大家一个分享一个关于贪吃蛇的Qt小游戏。
运行硬件:Upboard
运行环境:Ubuntu+Qt
这里界面部分比较简单,主要通过代码实现,UI如下

思路是用画矩形的方式绘制网格 用黑色正方形方块表示蛇,蛇长度,初始为3。通过二维数组表示对应的蛇头蛇身,对应的xy坐标。蛇的移动主要是吃食后的移动 即为蛇头向前移动一格后蛇头坐标变了原蛇头的坐标为第一节身体的坐标 原第一节身体坐标为现在第二节的坐标即所有坐标向前移动一格代码如下:#include "snake.h"
#include "ui_snake.h"
#include <QPainter>
#include <QMessageBox>
#include <QTime>
#include<QDebug>
Snake::Snake(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Snake)
{
    ui->setupUi(this);

    SnakeNum=3;      //蛇长度,初始为3
    SnakeFX=3;      //蛇头方向
    Block=20;
    level=1;
    temp=0;
    this->setWindowTitle(tr("贪吃蛇-->[关卡:%1-分数:%2]").arg(level).arg(Score));
    //初始化蛇
    for(int i=0;i<SnakeNum;i++)
    {
      xSnake.X=400;xSnake.Y=200+i*Block;xSnake.Snake_fx=SnakeFX;
    }

    creFOOD(); //随机生成食物
    Score=0;

    timer.start(timeoutTime(), this);
}

Snake::~Snake()
{
    delete ui;
    timer.stop();
}

void Snake::keyPressEvent(QKeyEvent *e)
{
    switch(e->key())
    {
    case Qt::Key_Left:
      SnakeFX = 1;
      break;
    case Qt::Key_Right:
      SnakeFX = 2;
      break;
    case Qt::Key_Up:
      SnakeFX = 3;
      break;
    case Qt::Key_Down:
      SnakeFX = 4;
      break;
    }
}

void Snake::paintEvent(QPaintEvent *e)
{
    int i;
    QPainter painter(this);
    QPen pen;
    pen.setColor(QColor(255,0,0));//设置画笔为红色
    painter.setPen(pen);//选择画笔
    //画网格地图
    for(i=0;i<=this->height();i=i+Block)
    {
      painter.drawLine(0,i,this->width(),i);
    }
    for(i=0;i<=this->width();i=i+Block)
    {
      painter.drawLine(i,0,i,this->height());
    }
    for(i=0;i<SnakeNum;i++)
    {
      painter.fillRect(QRect(xSnake.X,xSnake.Y,Block,Block),QColor(0,0,0));
    }

    painter.fillRect(QRect(Food.x()*Block,Food.y()*Block,Block,Block),QColor(0,0,0));

    painter.end();
}
bool Snake::isCONFINE(int x,int y)
{
    if((x<0 || x>this->width()) || (y<0 || y>this->height()))
      return true;
    return false;
}

bool Snake::isFOOD(int x,int y)
{
    if(Food.x()*Block==x && Food.y()*Block==y)
      return true;
    return false;
}
bool Snake::isOWN(int x,int y)
{
    int i;
    for(i=0;i<SnakeNum;i++)
    {
      if(xSnake.X==x && xSnake.Y==y)
            return true;
    }
    return false;
}
void Snake::eatFOOD()
{
    SnakeNum++;
    switch(xSnake.Snake_fx)
    {
      case 1:
            xSnake.X=xSnake.X+Block;
            xSnake.Y=xSnake.Y;
            xSnake.Snake_fx=xSnake.Snake_fx;
            break;
      case 2:
            xSnake.X=xSnake.X-Block;
            xSnake.Y=xSnake.Y;
            xSnake.Snake_fx=xSnake.Snake_fx;
            break;
      case 3:
            xSnake.X=xSnake.X;
            xSnake.Y=xSnake.Y+Block;
            xSnake.Snake_fx=xSnake.Snake_fx;
            break;
      case 4:
            xSnake.X=xSnake.X;
            xSnake.Y=xSnake.Y-Block;
            xSnake.Snake_fx=xSnake.Snake_fx;
            break;
    }

    Score+=10;
    temp+=10;
    if(temp==50)
    {
      level++;
      temp=0;
    }
    if(level<20)
    {
      timer.start(timeoutTime(), this);
    }
    this->setWindowTitle(tr("贪吃蛇-->[关卡:%1-分数:%2]").arg(level).arg(Score));

    creFOOD();//吃完食物后再随机生成食物

}

bool Snake::isOver(int x,int y)
{
    if((isCONFINE(x,y)) || (isOWN(x,y)))
    {
      timer.stop();
      QMessageBox::information(this,tr("提示"),tr("游戏结束!!!"));
      return true;
    }

    return false;
}

void Snake::creFOOD()
{
FOOD:
    Food.setX(qrand()%(this->width()/Block));
    Food.setY(qrand()%(this->height()/Block));
    for(int i=0;i<SnakeNum;i++)
    {
      if(xSnake.X==Food.x() && xSnake.Y==Food.y())
      {
            goto FOOD;
      }
    }
}

void Snake::timerEvent(QTimerEvent *e)
{
    int i,TempFX1,TempFX2;

    if((SnakeFX==1 && xSnake.Snake_fx==2) || (SnakeFX==2 && xSnake.Snake_fx==1)) goto xx;
    if((SnakeFX==3 && xSnake.Snake_fx==4) || (SnakeFX==4 && xSnake.Snake_fx==3)) goto xx;

    switch(SnakeFX)
    {
    case 1:
      if(isOver(xSnake.X-Block,xSnake.Y)) break;

      if(isFOOD(xSnake.X-Block,xSnake.Y))
      {
            eatFOOD();
      }
      xSnake.Snake_fx=1;
      break;
    case 2:
      if(isOver(xSnake.X+Block,xSnake.Y)) break;

      if(isFOOD(xSnake.X+Block,xSnake.Y))
      {
            eatFOOD();
      }
      xSnake.Snake_fx=2;
      break;
    case 3:
      if(isOver(xSnake.X,xSnake.Y-Block)) break;

      if(isFOOD(xSnake.X,xSnake.Y-Block))
      {
            eatFOOD();
      }
      xSnake.Snake_fx=3;
      break;
    case 4:
      if(isOver(xSnake.X,xSnake.Y+Block)) break;

      if(isFOOD(xSnake.X,xSnake.Y+Block))
      {
            eatFOOD();
      }
      xSnake.Snake_fx=4;
      break;
    }

    //蛇前进
xx:
    for(i=0;i<SnakeNum;i++)
    {
      switch(xSnake.Snake_fx)
      {
      case 1:
            xSnake.X=xSnake.X-Block;
            break;
      case 2:
            xSnake.X=xSnake.X+Block;
            break;
      case 3:
            xSnake.Y=xSnake.Y-Block;
            break;
      case 4:
            xSnake.Y=xSnake.Y+Block;
            break;
      }

    }
    TempFX1=xSnake.Snake_fx;
    for(i=1;i<SnakeNum;i++)
    {
      TempFX2=xSnake.Snake_fx;
      xSnake.Snake_fx=TempFX1;
      TempFX1=TempFX2;
    }
    update();
}
运行实现的效果如下图所示


简单视频如下


总结:这里主要通过键盘上的方向键来控制贪吃蛇的移动方向,当遇到自身身体或是边缘则游戏结束,实现了贪吃蛇基本的功能。当然Upboard用来做这种小游戏有些大材小用,不过大家用于学习还是不错的!


jackten 发表于 2017-2-21 09:04:23

谢谢分享                     

jialichuang 发表于 2018-7-17 10:48:25

感谢LZ分享:)
页: [1]
查看完整版本: 【UP-Board试用】+基于Qt的贪吃蛇小游戏设计