#include <QtWidgets>

class GameWidget : public QWidget
{
public:
    void resetGame()
    {
        // Создаем машинку
        carRect = QRect(width() / 2 - carWidth / 2, height() * 0.8,
                        carWidth, 50);
        // Обнуляем счет
        score = 0;

        // Создаем препятствия
        obstacleRects.clear();
        for (int i = 0; i < numObstacles; i++)
        {
            obstacleRects.push_back(QRect(qrand() % ((width() - 25) + 1), qrand() % height() - height(),
                                          30, 50));
        }
    }

    GameWidget(QWidget *parent = 0) : QWidget(parent)
    {
        // Устанавливаем размер окна
        setFixedSize(500, 1200);
        // Устанавливаем цвет заднего фона
        setBackgroundRole(QPalette::Base);
        setAutoFillBackground(true);

        // Создаем таймер обновления игры
        timer = new QTimer(this);
        connect(timer, &QTimer::timeout, this, &GameWidget::advance);

        resetGame();
    }

protected:
    void paintEvent(QPaintEvent * /*event*/) override
    {
        // Создаем кисти для рисования
        QPainter p(this);
        QBrush greenBrush(Qt::green);
        QBrush blackBrush(Qt::black);
        QPen outlinePen(Qt::black);
        outlinePen.setWidth(2);
        p.setPen(outlinePen);


        // Рисуем машинку
        p.fillRect(carRect, greenBrush);
        p.drawRect(carRect);

        // Рисуем препятствия
        for (int i = 0; i < obstacleRects.size(); i++)
        {
            QRect obstacleRect = obstacleRects[i];
            p.fillRect(obstacleRect, blackBrush);
            p.drawRect(obstacleRect);
        }

        // Рисуем счет очков
        p.setFont(QFont("Arial", 16));
        p.drawText(QRect(0, 0, width(), 50), Qt::AlignCenter, "Score: " + QString::number(score));
    }

    void keyPressEvent(QKeyEvent *event) override
    {
        if (event->key() == Qt::Key_Left)
            carDirection = -1;
        else if (event->key() == Qt::Key_Right)
            carDirection = 1;
        else if (event->key() == Qt::Key_Space)
        {
            if (timer->isActive())
            {
                timer->stop();
            }
            else
            {
                timer->start(1000 / 60);
            }
        }
    }

private:
    void advance()
    {
        // Двигаем препятствия
        for (int i = 0; i < obstacleRects.size(); i++)
        {
            QRect &obstacleRect = obstacleRects[i];
            // Если препятствие ушло за границу экрана, удаляем его и добавляем новое
            if (obstacleRect.top() > height())
            {
                score++;
                obstacleRect.moveTo(qrand() % ((width() - 25) + 1), qrand() % height() - height());
            }

            // Если машинка врезалась в препятствие, останавливаем игру
            if (obstacleRect.intersects(carRect))
            {
                timer->stop();
                QMessageBox::information(this, "Game over!", "Your score: " + QString::number(score));
                resetGame();
                return;
            }

            obstacleRect.translate(0, 15);
        }
        // Двигаем машинку
        int carSpeed = carDirection * 10;
        if (carRect.x() + carSpeed >= 0 && carRect.x() + carWidth + carSpeed <= width())
            carRect.moveTo(carRect.x() + carSpeed, carRect.y());

        // Перерисовываем окно
        update();
    }

private: // Объекты для игры
    QTimer *timer;
    QRect carRect;
    QVector<QRect> obstacleRects;
    int score = 0;
    const int numObstacles = 7 ;
    const int carWidth = 30;
    int carDirection = 0;
};

int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    GameWidget gameWidget;
    gameWidget.show();

    return app.exec();
}
