天天看點

QT 簡單編寫貪吃蛇

    • 大體思路
      • 用畫矩形的方式循環繪制網格
      • 通過紅色小正方形表示蛇頭 黑色表示蛇身 綠色表示食物
      • 通過二維數組表示對應的蛇頭蛇身對應的xy坐标
      • 蛇的移動主要是吃食後的移動
    • 部分代碼展示
      • 主要遊戲相關檔案
      • 進行選擇檔案代碼
    • 對應效果圖
      • pc版
      • 安卓手機版

大體思路

用畫矩形的方式,循環繪制網格。

//畫遊戲盤
    QPainter painter(this);
    for(int x = ; x < COL; ++x) {
      for(int y = ; y < ROW; ++y) {
          painter.drawRect(QRect(x*RectWidth, y*RectHeight, RectHeight, RectHeight));
      }
    }
           

通過紅色小正方形表示蛇頭, 黑色表示蛇身, 綠色表示食物

//畫食物
    painter.fillRect(QRect(foodPosition[]*RectWidth, foodPosition[]*RectHeight, RectHeight, RectHeight), Qt::green);

    //畫蛇頭
    painter.fillRect(QRect(snake[][]*RectWidth, snake[][]*RectHeight, RectHeight, RectHeight), Qt::red);

    //畫蛇身
    for(int snakeBoy = ; snakeBoy <= m_foodCount; ++snakeBoy) {
        painter.fillRect(QRect(snake[snakeBoy][]*RectWidth, snake[snakeBoy][]*RectHeight, RectHeight, RectHeight), Qt::black);
    }
           

通過二維數組表示對應的蛇頭,蛇身對應的x,y坐标

int snake[100][2]; //儲存蛇每個結點坐标

這裡定義的蛇總長方格不超過100, 當然可以增加, 2表示x 和y ,snake[0][0] 表示蛇頭x坐标, snake[0][1]表示蛇頭y坐标。 相應的蛇身用snake[k][0] 表示x, snake[k][1]為y , k在1到99之間。

蛇的移動,主要是吃食後的移動。

即為蛇頭向前移動一格後,蛇頭坐标變了,原蛇頭的坐标為第一節身體的坐标, 原第一節身體坐标為現在第二節的坐标,即所有坐标向前移動一格

部分代碼展示

主要遊戲相關檔案

由于用的mark寫的是以有“#”的地方作了一下處理。

.h檔案

"ifndef WIDGET_H
"define WIDGET_H

"include <QWidget>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = );
    ~Widget();

protected:
    virtual void paintEvent(QPaintEvent* event);
    virtual void resizeEvent(QResizeEvent* event);


private:
    bool checkEatFood();
    void creatFood();
    bool dealGuoJie();
    void drawSnakeHead();
    void flashScore();
    void gameOver();
    void init();
    void initData();
    void initAndiroStyle();
    void initBackground();
    void initConnect();
    void initWindows();
    void snakeHeadRun();
    void snakeRun();
    void upgrade();

private slots:
    void slotTimeOut();

    void on_upButton_clicked();

    void on_leftButton_clicked();

    void on_downButton_clicked();

    void on_rightButton_clicked();

    void on_returnButton_clicked();

private:
    Ui::Widget *ui;
    QTimer *m_timer;
    int snake[100][2]; //儲存蛇每個結點坐标
    int *snakeBody[100][2];
    int m_direction;
    int foodPosition[2];
    int m_foodCount;
    int m_currentGrade;
    int m_upgradeScore;
    int m_currentSpeed;
};

#endif // WIDGET_H
           

.cpp 檔案

include "widget.h"
include "ui_widget.h"
include "QKeyEvent>
include "QPainter>
include "QTimer>
include "QDebug>
include "QMessageBox>
include "QEvent>
include "QMenu>
include "QContextMenuEvent>
include "QApplication>
include "QScreen>
include "QDesktopWidget>

ifndef COL
define COL 30
endif

ifndef ROW
define ROW 22
endif

ifndef RectWidth
define RectWidth 45
endif

ifndef RectHeight
define RectHeight 45
endif

define UP 0
define DOWN 1
define LEFT 2
define RIGHT 3

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget),
    m_timer(new QTimer(this)),
    m_direction(0),
    m_foodCount(0),
    m_currentGrade(1),
    m_upgradeScore(100),
    m_currentSpeed(500)
{
    ui->setupUi(this);
    init();
}

Widget::~Widget()
{
    delete ui;
}

void Widget::paintEvent(QPaintEvent* event)
{
    //畫遊戲盤
    QPainter painter(this);
    for(int x = ; x < COL; ++x) {
      for(int y = ; y < ROW; ++y) {
          painter.drawRect(QRect(x*RectWidth, y*RectHeight, RectHeight, RectHeight));
      }
    }

    //畫食物
    painter.fillRect(QRect(foodPosition[]*RectWidth, foodPosition[]*RectHeight, RectHeight, RectHeight), Qt::green);

    //畫蛇頭
    painter.fillRect(QRect(snake[][]*RectWidth, snake[][]*RectHeight, RectHeight, RectHeight), Qt::red);

    //畫蛇身
    for(int snakeBoy = ; snakeBoy <= m_foodCount; ++snakeBoy) {
        painter.fillRect(QRect(snake[snakeBoy][]*RectWidth, snake[snakeBoy][]*RectHeight, RectHeight, RectHeight), Qt::black);
    }

}

void Widget::resizeEvent(QResizeEvent* event)
{
    initBackground();
    QSize size = qApp->desktop( )->screenGeometry( ).size( );
    resize(size);
}

bool Widget::checkEatFood()
{
    //如果蛇頭的X坐标等于食物的X坐标,并且蛇頭的Y坐标等于食物的Y坐标 表示吃到食物,否則表示沒有吃到。
    if(snake[][] == foodPosition[] && snake[][] == foodPosition[]){
        ++ m_foodCount;
        upgrade();
        flashScore();
        creatFood(); //産生一個新的食物
    }

    //蛇的身子添加
    for(int snId = m_foodCount; snId > ; --snId){
       snake[snId][] = snake[snId - ][];
       snake[snId][] = snake[snId - ][];
    }

    snakeHeadRun();
}

void Widget::creatFood()
{
    foodPosition[] = qrand() % COL;
    foodPosition[] = qrand() % ROW;

    //防止産生的食物在蛇的身上
    for(int bodyId = ; bodyId <= m_foodCount; ++ bodyId) {
        if(foodPosition[] == snake[bodyId][] && foodPosition[] == snake[bodyId][]) {
            foodPosition[] = qrand() % COL - ;
            foodPosition[] = qrand() % ROW - ;
        }
    }
}

bool Widget::dealGuoJie()
{
    if(snake[][] > (COL - ) || snake[][] <  || snake[][] > (ROW - ) || snake[][] < ) {
        gameOver();
        return true;
    }

    for(int i = ; i <= m_foodCount; ++i) {
        if(snake[][] == snake[i][] && snake[][] == snake[i][]) {
            gameOver();
            return true;
        }
    }

    return false;
}

void Widget::drawSnakeHead()
{
    //畫蛇頭
    snake[][] = qrand() % COL;
    snake[][] = qrand() % ROW;

    //方向
    m_direction = qrand() % ;
}

void Widget::flashScore()
{
    ui->levelEdit->setText(QString::number(m_currentGrade));
    ui->scoreEdit->setText(QString::number(m_foodCount*));
}

void Widget::gameOver()
{
    m_timer->stop();
    QMessageBox::information(this, QString::fromUtf8("Waring"), QString::fromUtf8("Game Over"));
    ui->levelEdit->setText(QLatin1String("1"));
    ui->scoreEdit->setText(QLatin1String("0"));
}

void Widget::init()
{
    initAndiroStyle();
    drawSnakeHead();
    creatFood();
    initBackground();
    initConnect();
    initWindows();
}

void Widget::initAndiroStyle()
{
    QScreen *screen = qApp->primaryScreen();
    QFont f = qApp->font();
    int pixelSize = (f.pointSize() * screen->logicalDotsPerInch()) / (*);

    QFont andiroFont;
    andiroFont.setPixelSize(pixelSize);

    ui->upButton->setFont(andiroFont);
    ui->leftButton->setFont(andiroFont);
    ui->downButton->setFont(andiroFont);
    ui->rightButton->setFont(andiroFont);

    ui->label->setFont(andiroFont);
    ui->label_2->setFont(andiroFont);

    ui->scoreEdit->setFont(andiroFont);
    ui->levelEdit->setFont(andiroFont);
}

void Widget::initBackground()
{
    setAutoFillBackground(true);
    QPalette palette;
    palette.setBrush(QPalette::Background, QBrush(QPixmap(":/images/background.png").scaled(this->size())));
    setPalette(palette);

    ui->returnButton->setIcon(QIcon(":/images/return_normal.png"));
    ui->returnButton->setIconSize(QSize(, ));
    ui->returnButton->setFlat(true);
}

void Widget::initConnect()
{
    connect(m_timer, SIGNAL(timeout()), this, SLOT(slotTimeOut()));
    m_timer->start(m_currentSpeed);
}

void Widget::initData()
{
    ui->levelEdit->setText(QLatin1String("1"));
    ui->scoreEdit->setText(QLatin1String("0"));

    m_direction = ;
    m_foodCount = ;
    m_currentGrade = ;
    m_upgradeScore = ;
    m_currentSpeed = ;
}

void Widget::initWindows()
{
    setWindowTitle("貪吃蛇");
    setWindowIcon(QIcon(":/images/ico.png"));
}

void Widget::snakeHeadRun()
{
    //蛇根據方向遊動
    switch(m_direction){
    case UP:
        -- snake[][];
        break;

    case DOWN:
        ++ snake[][];
        break;

    case LEFT:
        -- snake[][];
        break;

    case RIGHT:
        ++ snake[][];
        break;

    default:
        break;
    }
}

void Widget::snakeRun()
{
    //蛇根據方向遊動
    if(dealGuoJie())
        return;
    checkEatFood();
    update();
}

void Widget::upgrade()
{
    qDebug() << "the ui->scoreEdit->text().toInt() is:" << ui->scoreEdit->text().toInt()
                << "m_upgradeScore * m_currentGrade" << m_upgradeScore * m_currentGrade << m_upgradeScore << m_currentGrade;
    if(ui->scoreEdit->text().toInt() >=  m_upgradeScore * m_currentGrade) {
        m_upgradeScore *= ;
        ++ m_currentGrade;
        if(m_currentSpeed > ){
            m_currentSpeed -= ;
        }
        m_timer->stop();
        QMessageBox::information(this, QString::fromUtf8("Waring"), QString::fromUtf8("Upgrade success"));
        m_timer->start(m_currentSpeed);
    }
}

void Widget::slotTimeOut()
{
   snakeRun();
}

void Widget::on_upButton_clicked()
{
    m_direction = UP;
}

void Widget::on_leftButton_clicked()
{
    m_direction = LEFT;
}

void Widget::on_downButton_clicked()
{
    m_direction = DOWN;
}

void Widget::on_rightButton_clicked()
{
    m_direction = RIGHT;
}

void Widget::on_returnButton_clicked()
{
    initData();
    close();
}
           

進行選擇檔案代碼

.h

"ifndef MENUEWIDGET_H
"define MENUEWIDGET_H

"include <QWidget>

namespace Ui {
class MenueWidget;
}

class MenueWidget : public QWidget
{
    Q_OBJECT

public:
    explicit MenueWidget(QWidget *parent = );
    ~MenueWidget();

protected:
    virtual void paintEvent(QPaintEvent* event);

private slots:
    void on_startButton_clicked();

    void on_leaveButton_clicked();

private:
    void init();
    void initBackground();
    void initWindows();

private:
    Ui::MenueWidget *ui;
};

#endif // MENUEWIDGET_H
           

.cpp

#include "menuewidget.h"
#include "ui_menuewidget.h"
#include "widget.h"

MenueWidget::MenueWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MenueWidget)
{
    ui->setupUi(this);
    init();
}

MenueWidget::~MenueWidget()
{
    delete ui;
}

void MenueWidget::paintEvent(QPaintEvent* event)
{
    initBackground();
}

void MenueWidget::on_startButton_clicked()
{
    Widget *myWidget = new Widget(this);
   // myWidget->setWindowFlags(Qt::WindowMinMaxButtonsHint&Qt::WindowCloseButtonHint);
   // myWidget->showFullScreen();
    myWidget->show();
}

void MenueWidget::on_leaveButton_clicked()
{
    exit();
}

void MenueWidget::init()
{
    initBackground();
    initWindows();
}

void MenueWidget::initBackground()
{
    setAutoFillBackground(true);
    QPalette palette;
    palette.setBrush(QPalette::Background, QBrush(QPixmap(":/images/main_home_background.png").scaled(this->size())));
    setPalette(palette);

    ui->startButton->setIcon(QIcon(":/images/start_normal.png"));
    ui->startButton->setIconSize(QSize(, ));
    ui->startButton->setFlat(true);

    ui->leaveButton->setIcon(QIcon(":/images/quit_normal.png"));
    ui->leaveButton->setIconSize(QSize(, ));
    ui->leaveButton->setFlat(true);

}

void MenueWidget::initWindows()
{
    setWindowTitle("貪吃蛇");
    setWindowIcon(QIcon(":/images/ico.png"));
}
           

對應效果圖

pc版

1.操作界面效果圖

QT 簡單編寫貪吃蛇

2.運作時效果圖

QT 簡單編寫貪吃蛇

3.撞到邊界效果圖

QT 簡單編寫貪吃蛇

安卓手機版

1.手機版操作界面

QT 簡單編寫貪吃蛇

2.手機版遊戲界面

QT 簡單編寫貪吃蛇
QT 簡單編寫貪吃蛇

3.手機版邊界處理

QT 簡單編寫貪吃蛇

繼續閱讀