#pragma once
#include <QGraphicsView>
#include <QKeyEvent>
#include <QTimer>
class SheItem;
class Viewer :public QGraphicsView
{
Q_OBJECT
public:
enum class State
{
PAUSE,
START
};
enum class Direction
{
UP,
DOWN,
LEFT,
RIGHT
};
Viewer(QWidget* parent = nullptr);
~Viewer();
void keyPressEvent(QKeyEvent* event);
void showMessage(const QString& message, int timeout = 0);
void scored(int x = 1);
void gameStart();
void gamePause();
void gameOver();
int getSheWidth() { return _sheDiameter; }
signals:
void mainWindowMessage(const QString&, int);
void updateScoreLabel(int);
void updateLevelLabel(int);
private:
void start();
void stop();
void update();
Direction _direction;
QTimer* _timer;
SheItem* _sheItem;
State _state;
int _sheDiameter;
int _width;
int _score;
int _timeout;
int _level;
QGraphicsSimpleTextItem* _text;
};
#include <qDebug>
#include <windows.h>
#include "viewer.h"
#include "sheItem.h"
Viewer::Viewer(QWidget* parent) :
QGraphicsView(parent),
_direction(Direction::RIGHT),
_width(50),
_timeout(400),
_sheDiameter(10),
_state(State::PAUSE),
_score(0),
_level(0)
{
_sheItem = new SheItem(_sheDiameter, _width, this);
this->grabKeyboard();
_timer = new QTimer(this);
QGraphicsScene* scene = new QGraphicsScene(this);
scene->setBackgroundBrush(Qt::gray);
scene->setSceneRect(0, 0, (double)_width * _sheDiameter, (double)_width * _sheDiameter);
this->setScene(scene);
qDebug() << connect(_timer, &QTimer::timeout, this, &Viewer::update);
QFont font;
font.setFamily("微软雅黑");
font.setPointSize(30);
font.setCapitalization(QFont::Capitalize);
_text = new QGraphicsSimpleTextItem();
_text->setFont(font);
_text->setZValue(10);
this->scene()->addItem(_sheItem);
this->scene()->addItem(_text);
}
Viewer::~Viewer()
{
}
void Viewer::keyPressEvent(QKeyEvent* event)
{
if (_state != State::START) {
event->ignore();
return;
}
switch (event->key())
{
case Qt::Key_Left:
if (_direction == Direction::RIGHT) {
event->ignore();
return;
}
_direction = Direction::LEFT;
this->update();
if (_state != State::START) {
event->accept();
return;
}
this->stop();
this->start();
event->accept();
break;
case Qt::Key_Right:
if (_direction == Direction::LEFT) {
event->ignore();
return;
}
_direction = Direction::RIGHT;
this->update();
if (_state != State::START) {
event->accept();
return;
}
this->stop();
this->start();
event->accept();
break;
case Qt::Key_Up:
if (_direction == Direction::DOWN) {
event->ignore();
return;
}
_direction = Direction::UP;
this->update();
if (_state != State::START) {
event->accept();
return;
}
this->stop();
this->start();
event->accept();
break;
case Qt::Key_Down:
if (_direction == Direction::UP) {
event->ignore();
return;
}
_direction = Direction::DOWN;
this->update();
if (_state != State::START) {
event->accept();
return;
}
this->stop();
this->start();
event->accept();
break;
}
}
void Viewer::showMessage(const QString& message, int timeout)
{
emit this->mainWindowMessage(message, timeout);
}
void Viewer::scored(int x)
{
_score += x;
while (_score >= (_level + 1) * 10) {
_level++;
emit updateLevelLabel(_level + 1);
}
emit updateScoreLabel(_score);
}
void Viewer::gameStart()
{
emit updateLevelLabel(1);
emit updateScoreLabel(0);
_state = State::START;
_direction = Direction::RIGHT;
_text->setText("");
this->start();
}
void Viewer::gamePause()
{
_text->setText("pause!");
_state = State::PAUSE;
_timer->stop();
}
void Viewer::start()
{
float timeout = _timeout;
int i = _level;
while (i){
timeout *= 0.8;
i--;
}
_timer->start(timeout);
}
void Viewer::gameOver()
{
_text->setText("game over!");
_state = State::PAUSE;
_timer->stop();
_sheItem->initialize();
_level = 0;
_score = 0;
}
void Viewer::stop()
{
_timer->stop();
}
void Viewer::update()
{
int k = _sheItem->move(_direction);
switch (k)
{
case 0:break;
case 1:this->scored(); break;
case -1:
case -2:this->gameOver(); break;
}
}
#pragma once
#include <QGraphicsItem>
#include <QObject>
#include <list>
#include "viewer.h"
class SheItem :public QObject, public QGraphicsItem
{
Q_OBJECT
Q_INTERFACES(QGraphicsItem)
public:
SheItem(int diameter, int width, Viewer* parent = nullptr);
int move(Viewer::Direction direction);
~SheItem();
void initialize();
QRectF boundingRect() const;
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0);
void generateFood();
protected:
std::list<QPoint> _path;
QPoint _food;
int _width;
int _diameter;
};
#include <random>
#include <ctime>
#include <algorithm>
#include "sheItem.h"
int SheItem::move(Viewer::Direction direction)
{
QPoint point;
switch (direction)
{
case Viewer::Direction::UP:
point = QPoint(_path.front().x(), _path.front().y() - 1);
break;
case Viewer::Direction::DOWN:
point = QPoint(_path.front().x(), _path.front().y() + 1);
break;
case Viewer::Direction::LEFT:
point = QPoint(_path.front().x() - 1, _path.front().y());
break;
case Viewer::Direction::RIGHT:
point = QPoint(_path.front().x() + 1, _path.front().y());
break;
default:
return 0;
}
if (point.x() < 0 || point.x() >= _width || point.y() < 0 || point.y() >= _width) {
return -1;
}
if (point == _food) {
_path.push_front(point);
generateFood();
update();
return 1;
}
if (std::find(_path.begin(), _path.end(), point) != _path.end()) {
return -2;
}
_path.push_front(point);
_path.pop_back();
update();
return 0;
}
SheItem::SheItem(int diameter, int width, Viewer* parent) :
QObject(parent),
_diameter(diameter),
_width(width)
{
srand(std::clock());
_path.push_front(QPoint(_width / 2 - 1, _width / 2));
_path.push_front(QPoint(_width / 2, _width / 2));
_path.push_front(QPoint(_width / 2 + 1, _width / 2));
this->generateFood();
this->setPos(QPoint());
}
SheItem::~SheItem()
{
}
void SheItem::initialize()
{
_path.clear();
_path.push_front(QPoint(_width / 2 - 1, _width / 2));
_path.push_front(QPoint(_width / 2, _width / 2));
_path.push_front(QPoint(_width / 2 + 1, _width / 2));
this->generateFood();
}
QRectF SheItem::boundingRect() const
{
return QRectF(0, 0, (double)_width * _diameter, (double)_width * _diameter);
}
void SheItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
QPen pen(Qt::black, (double)_diameter - 1);
painter->setPen(pen);
for (const auto& point : _path) {
painter->drawPoint(point * _diameter);
}
pen.setColor(Qt::red);
painter->setPen(pen);
painter->drawPoint(_food * _diameter);
pen.setColor(Qt::green);
pen.setWidth(1);
painter->setPen(pen);
QRectF rect = this->boundingRect();
rect = QRectF(rect.x() - 3, rect.y() - 3, rect.width() + 6 - _diameter, rect.height() + 6 - _diameter);
painter->drawRect(rect);
}
void SheItem::generateFood()
{
QPoint point(rand() % _width, rand() % _width);
while (std::find(_path.begin(), _path.end(), point) != _path.end()) {
point = QPoint(rand() % _width, rand() % _width);
}
_food = point;
}
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_tanchishe.h"
class tanchishe : public QMainWindow
{
Q_OBJECT
public:
tanchishe(QWidget *parent = Q_NULLPTR);
private:
Ui::tanchisheClass ui;
};
#include <QDebug>
#include "tanchishe.h"
tanchishe::tanchishe(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
QFont font;
font.setFamily("微软雅黑");
font.setPointSize(28);
ui.scoreLabel->setFont(font);
ui.levelLabel->setFont(font);
qDebug() << connect(ui.view, &Viewer::updateScoreLabel, ui.scoreLabel, static_cast<void (QLabel::*)(int)>(&QLabel::setNum));
qDebug() << connect(ui.view, &Viewer::updateLevelLabel, ui.levelLabel, static_cast<void (QLabel::*)(int)>(&QLabel::setNum));
qDebug() << connect(ui.startButton, &QPushButton::clicked, ui.view, &Viewer::gameStart);
qDebug() << connect(ui.pauseButton, &QPushButton::clicked, ui.view, &Viewer::gamePause);
}