1.snake.pro
QT += core gui network widgets
TEMPATE = app
TARGET = snake
DEPENDPATH += .
INCLUDEPATH += .
HEADERS += mainwindow.h snake.h
SOURCES += main.cpp mainwindow.cpp snake.cpp
2.main.cpp
#include <QApplication>
#include <QTextCodec>
#include "mainwindow.h"
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QTextCodec::setCodecForLocale(QTextCodec::codecForName("utf-8"));
QWidget *pWidget = new MainWindow();
pWidget->setFixedSize(440, 320);
pWidget->show();
return app.exec();
}
3.mainwindow.h
#ifndef _SNAKE_MAIN_WINDOW_H_
#define _SNAKE_MAIN_WINDOW_H_
#include <QtGlobal>
#include <QApplication>
#include <QDesktopWidget>
#include <QMainWindow>
#include <QWidget>
#include <QKeyEvent>
#include <QLabel>
#include <QPushButton>
#include <QSlider>
#include <QPainter>
#include <QTimer>
#include <QTime>
#include <QDebug>
#include "snake.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void changeScore(int score);
signals:
void sig_snake_key_press(int key);
void sig_snake_restart();
void sig_snake_start_or_pause();
void sig_snake_speed(int);
protected:
void keyPressEvent(QKeyEvent *event);
private slots:
void restartGame();
void startGame();
void setSpeed(int value);
private:
void align();
Snake *snake;
QWidget *header;
QPushButton *restart;
QPushButton *start;
QLabel *lab[3];
QSlider *speed;
bool pause;
};
#endif
4.mainwindow.cpp
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
QFont font;
font.setPointSize(12);
align();
pause = true;
header = new QWidget(this);
snake = new Snake(this);
restart = new QPushButton(header);
start = new QPushButton(header);
lab[0] = new QLabel(header);
lab[1] = new QLabel(header);
lab[2] = new QLabel(header);
speed = new QSlider(Qt::Horizontal, header);
speed->setValue(10);
restart->setFocusPolicy(Qt::ClickFocus);
start->setFocusPolicy(Qt::ClickFocus);
speed->setFocusPolicy(Qt::ClickFocus);
setFocusPolicy(Qt::ClickFocus);
setFocus();
header->setFixedSize(460, 60);
restart->setText("重新开始");
restart->resize(80, 30);
restart->move(20, 20);
restart->setFont(font);
lab[0]->setFont(font);
lab[0]->setText("速度: ");
lab[0]->resize(40, 30);
lab[0]->move(160, 20);
lab[1]->setFont(font);
lab[1]->setText("得分: ");
lab[1]->resize(40, 30);
lab[1]->move(350, 20);
lab[2]->setFont(font);
lab[2]->setText("0");
lab[2]->resize(40, 30);
lab[2]->move(395, 20);
speed->setMinimum(0);
speed->setMaximum(100);
if(pause)
{
start->setText("开始");
}
else
{
start->setText("暂停");
}
start->resize(40, 30);
start->move(110, 20);
start->setFont(font);
speed->move(205, 27);
snake->move(0, 60);
connect(restart, SIGNAL(clicked()), this, SLOT(restartGame()));
connect(start, SIGNAL(clicked()), this, SLOT(startGame()));
connect(speed, SIGNAL(valueChanged(int)), this, SLOT(setSpeed(int)));
connect(this, SIGNAL(sig_snake_key_press(int)), snake, SLOT(keyPress(int)));
connect(this, SIGNAL(sig_snake_restart()), snake, SLOT(restart()));
connect(this, SIGNAL(sig_snake_start_or_pause()), snake, SLOT(startorpause()));
connect(this, SIGNAL(sig_snake_speed(int)), snake, SLOT(setSpeed(int)));
connect(snake, SIGNAL(sig_change_score(int)), this, SLOT(changeScore(int)));
}
MainWindow::~MainWindow()
{
}
void MainWindow::restartGame()
{
setFocus();
pause = false;
if(pause)
{
start->setText("开始");
}
else
{
start->setText("暂停");
}
emit sig_snake_restart();
}
void MainWindow::startGame()
{
if(pause)
{
start->setText("暂停");
pause = false;
}
else
{
start->setText("开始");
pause = true;
}
setFocus();
emit sig_snake_start_or_pause();
}
void MainWindow::setSpeed(int value)
{
emit sig_snake_speed(value);
}
void MainWindow::align()
{
this->move((QApplication::desktop()->width()-this->width())/2, (QApplication::desktop()->height()-this->height())/2);
}
void MainWindow::keyPressEvent(QKeyEvent *event)
{
emit sig_snake_key_press(event->key());
}
void MainWindow::changeScore(int score)
{
//qDebug() << "change score";
lab[2]->setText(QString::number(score));
lab[2]->repaint();
}
5.snake.h
#ifndef _SNAKE_GAME_WINDOW_H_
#define _SNAKE_GAME_WINDOW_H_
#include <QtGlobal>
#include <QApplication>
#include <QDesktopWidget>
#include <QMainWindow>
#include <QWidget>
#include <QKeyEvent>
#include <QLabel>
#include <QPushButton>
#include <QPainter>
#include <QTimer>
#include <QTime>
#include <QDebug>
class Snake : public QWidget
{
Q_OBJECT
public:
explicit Snake(QWidget *parent = 0);
~Snake();
signals:
void sig_change_score(int);
public slots:
void restart();
void startorpause();
void setSpeed(int speed);
void keyPress(int key);
protected:
void paintEvent(QPaintEvent *);
void keyPressEvent(QKeyEvent *event);
private slots:
void updateFrame();
private:
void align();
void generateSnake();
void generateFood();
bool verifyinbody(const QPoint &pos);
bool verifyheadinbody();
bool verifyboundary(const QPoint &pos);
bool gameover;
bool pause;
int score;
int interval;
QTimer *timer;
QVector<QPoint> snake;
QPoint food;
QPoint lastDirect;
QPoint keyDirect;
};
#endif
6.snake.cpp
#include "snake.h"
Snake::Snake(QWidget *parent) : QWidget(parent)
{
setFixedSize(440, 260);
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
interval = 1000;
//align();
score = 0;
generateSnake();
//qDebug() << "generate snake success";
gameover = false;
generateFood();
timer = new QTimer(this);
timer->setInterval(interval);
pause = true;
if(pause == false)
{
timer->start();
}
connect(timer, SIGNAL(timeout()), this, SLOT(updateFrame()));
}
Snake::~Snake()
{
}
void Snake::generateSnake()
{
QPoint pos;
int x, y, z;
int i;
int j = 0;
redo:
j = 0;
snake.clear();
x = qrand()%(20);
y = qrand()%(11);
pos = QPoint(x, y);
snake.push_back(pos);
for(i=0; i<8; i++)
{
do
{
z = qrand() % 4;
if(z % 4 == 0)
{
x = -1;
y = 0;
}
else if(z % 4 == 1)
{
x = 1;
y = 0;
}
else if(z % 4 == 2)
{
x = 0;
y = -1;
}
else if(z % 4 == 3)
{
x = 0;
y = 1;
}
pos = snake[i] + QPoint(x, y);
j++;
if(j > 100)
goto redo;
}
while(verifyinbody(pos) || verifyboundary(pos));
snake.push_back(pos);
}
do
{
z = qrand() % 4;
if(z % 4 == 0)
{
x = -1;
y = 0;
}
else if(z % 4 == 1)
{
x = 1;
y = 0;
}
else if(z % 4 == 2)
{
x = 0;
y = -1;
}
else if(z % 4 == 3)
{
x = 0;
y = 1;
}
pos = snake[0] + QPoint(x, y);
j++;
if(j > 100)
goto redo;
}
while(verifyinbody(pos) || verifyboundary(pos));
lastDirect = QPoint(x, y);
keyDirect = lastDirect;
}
bool Snake::verifyinbody(const QPoint &pos)
{
for(int i=0; i<snake.size(); i++)
{
if(snake[i] == pos)
{
return true;
}
}
return false;
}
bool Snake::verifyheadinbody()
{
for(int i=1; i<snake.size(); i++)
{
if(snake[i] == snake[0])
{
return true;
}
}
return false;
}
bool Snake::verifyboundary(const QPoint &pos)
{
if(pos.x() > 19 || pos.x() < 0 || pos.y() > 10 || pos.y() < 0)
return true;
else
return false;
}
void Snake::generateFood()
{
QPoint pos;
do
{
int x = qrand()%(20);
int y = qrand()%(11);
pos = QPoint(x, y);
}
while(verifyinbody(pos));
food = pos;
}
void Snake::align()
{
this->move((QApplication::desktop()->width()-this->width())/2, (QApplication::desktop()->height()-this->height())/2);
}
void Snake::updateFrame()
{
if(gameover)
return;
if(snake[0] + keyDirect == snake[1])
{
keyDirect = lastDirect;
}
else
{
lastDirect = keyDirect;
}
if(snake[0] + lastDirect != food)
{
QPoint pos = snake[snake.size()-1];
for(int i=snake.size()-1; i>0; i--)
{
snake[i] = snake[i-1];
}
snake[0] = snake[0] + lastDirect;
for(int i=0; i<snake.size(); i++)
{
if(verifyboundary(snake[i]) || verifyheadinbody())
{
gameover = true;
for(int i=0; i<snake.size()-1; i++)
{
snake[i] = snake[i+1];
}
snake[snake.size()-1] = pos;
timer->stop();
return;
}
}
}
else
{
snake.push_back(QPoint(0, 0));
for(int i=snake.size(); i>0; i--)
{
snake[i] = snake[i-1];
}
snake[0] = food;
score += 10;
emit sig_change_score(score);
generateFood();
}
repaint();
}
void Snake::paintEvent(QPaintEvent *)
{
QPainter painter(this);
QBrush brush(QColor(0, 255, 0, 255));
QBrush brush2(QColor(255, 0, 0, 255));
QBrush brush3(QColor(255, 255, 0, 255));
painter.drawRect(20, 20, 400, 220);
painter.setBrush(brush3);
painter.drawRect(20+snake[0].x()*20, 20+snake[0].y()*20, 20, 20);
//qDebug() << "size: " << snake.size();
painter.setBrush(brush);
for(int i=1; i<snake.size(); i++)
{
painter.drawRect(20+snake[i].x()*20, 20+snake[i].y()*20, 20, 20);
}
painter.setBrush(brush2);
painter.drawRect(20+food.x()*20, 20+food.y()*20, 20, 20);
}
void Snake::keyPressEvent(QKeyEvent *event)
{
switch(event->key())
{
case Qt::Key_Down:
keyDirect = QPoint(0, 1);
break;
case Qt::Key_Up:
keyDirect = QPoint(0, -1);
break;
case Qt::Key_Left:
keyDirect = QPoint(-1, 0);
break;
case Qt::Key_Right:
keyDirect = QPoint(1, 0);
break;
}
}
void Snake::keyPress(int key)
{
switch(key)
{
case Qt::Key_Down:
keyDirect = QPoint(0, 1);
break;
case Qt::Key_Up:
keyDirect = QPoint(0, -1);
break;
case Qt::Key_Left:
keyDirect = QPoint(-1, 0);
break;
case Qt::Key_Right:
keyDirect = QPoint(1, 0);
break;
}
}
void Snake::restart()
{
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
//align();
generateSnake();
//qDebug() << "generate snake success";
pause = false;
gameover = false;
score = 0;
emit sig_change_score(score);
generateFood();
//timer->clearInterval();
timer->setInterval(interval);
timer->start();
}
void Snake::startorpause()
{
if(pause == true)
{
timer->start();
pause = false;
}
else
{
timer->stop();
pause = true;
}
}
void Snake::setSpeed(int speed)
{
interval = 10000 / speed;
}
7.编译源码
$ qmake
$ make
8.界面效果
snake.png
网友评论