您的位置:首页 > 编程语言 > Qt开发

QT 简单编写贪吃蛇

2016-03-29 23:09 573 查看
大体思路
用画矩形的方式循环绘制网格

通过红色小正方形表示蛇头 黑色表示蛇身 绿色表示食物

通过二维数组表示对应的蛇头蛇身对应的xy坐标

蛇的移动主要是吃食后的移动

部分代码展示
主要游戏相关文件

进行选择文件代码

对应效果图
pc版

安卓手机版

大体思路

用画矩形的方式,循环绘制网格。

//画游戏盘
QPainter painter(this);
for(int x = 0; x < COL; ++x) {
for(int y = 0; y < ROW; ++y) {
painter.drawRect(QRect(x*RectWidth, y*RectHeight, RectHeight, RectHeight));
}
}


通过红色小正方形表示蛇头, 黑色表示蛇身, 绿色表示食物

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

//画蛇头
painter.fillRect(QRect(snake[0][0]*RectWidth, snake[0][1]*RectHeight, RectHeight, RectHeight), Qt::red);

//画蛇身
for(int snakeBoy = 1; snakeBoy <= m_foodCount; ++snakeBoy) {
painter.fillRect(QRect(snake[snakeBoy][0]*RectWidth, snake[snakeBoy][1]*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 = 0);
~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 = 0; x < COL; ++x) {
for(int y = 0; y < ROW; ++y) {
painter.drawRect(QRect(x*RectWidth, y*RectHeight, RectHeight, RectHeight));
}
}

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

//画蛇头
painter.fillRect(QRect(snake[0][0]*RectWidth, snake[0][1]*RectHeight, RectHeight, RectHeight), Qt::red);

//画蛇身
for(int snakeBoy = 1; snakeBoy <= m_foodCount; ++snakeBoy) {
painter.fillRect(QRect(snake[snakeBoy][0]*RectWidth, snake[snakeBoy][1]*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[0][0] == foodPosition[0] && snake[0][1] == foodPosition[1]){
++ m_foodCount;
upgrade();
flashScore();
creatFood(); //产生一个新的食物
}

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

snakeHeadRun();
}

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

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

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

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

return false;
}

void Widget::drawSnakeHead()
{
//画蛇头
snake[0][0] = qrand() % COL;
snake[0][1] = qrand() % ROW;

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

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

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()) / (72*1.5);

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(100, 60));
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 = 0;
m_foodCount = 0;
m_currentGrade = 1;
m_upgradeScore = 100;
m_currentSpeed = 500;
}

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

void Widget::snakeHeadRun()
{
//蛇根据方向游动
switch(m_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;
}
}

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 *= 2;
++ m_currentGrade;
if(m_currentSpeed > 50){
m_currentSpeed -= 10;
}
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 = 0);
~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(0);
}

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(240, 240));
ui->startButton->setFlat(true);

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

}

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


对应效果图

pc版

1.操作界面效果图



2.运行时效果图



3.撞到边界效果图



安卓手机版

1.手机版操作界面



2.手机版游戏界面





3.手机版边界处理

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: