-
- 大體思路
- 用畫矩形的方式循環繪制網格
- 通過紅色小正方形表示蛇頭 黑色表示蛇身 綠色表示食物
- 通過二維數組表示對應的蛇頭蛇身對應的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.操作界面效果圖
2.運作時效果圖
3.撞到邊界效果圖
安卓手機版
1.手機版操作界面
2.手機版遊戲界面
3.手機版邊界處理