Russian Qt Forum

Qt => Кладовая готовых решений => Тема начата: alexu007 от Май 19, 2022, 19:00



Название: Змейка.
Отправлено: alexu007 от Май 19, 2022, 19:00
Код:
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTime>
#include <QTimer>


QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    QTimer *timer;

    struct segm
    {
        int pos_x;
        int pos_y;
        int clr;
    };

    int table_row;
    int table_col;

    int pole[30][50];

    QList<segm> zmeyka;

    void make_zmeyka();
    void print_zmeyka();
    bool move_zmeyka(int);


private:
    Ui::Widget *ui;


public slots:
    void press_pbtn_01();

    void onTimer();

};
#endif // WIDGET_H

Код:
#include "widget.h"
#include "ui_widget.h"


Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // инициализация ГСЧ
    qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));

    timer = new QTimer();

    table_row = ui->tableWidget->rowCount();        // 30
    table_col = ui->tableWidget->columnCount();     // 50

    for(int row = 0; row < table_row; row++)
        for(int col = 0; col < table_col; col++)
        {
            pole[row][col] = 0;

            QTableWidgetItem *it = new QTableWidgetItem;
            it->setTextAlignment(Qt::AlignCenter);
            ui->tableWidget->setItem(row, col, it);
        }


    // лабиринт
    for(int i = 0; i < 3; i++)
        for(int j = 5; j < 15; j++)
        {
            pole[j][i+10] = 1;
            pole[j+10][i+10] = 1;

            ui->tableWidget->item(j, i+10)->setBackgroundColor(Qt::gray);
            ui->tableWidget->item(j+10, i+10)->setBackgroundColor(Qt::gray);

            pole[j][i+37] = 1;
            pole[j+10][i+37] = 1;

            ui->tableWidget->item(j, i+37)->setBackgroundColor(Qt::gray);
            ui->tableWidget->item(j+10, i+37)->setBackgroundColor(Qt::gray);
        }


    make_zmeyka();
    print_zmeyka();

    QObject::connect(ui->pbtn_01, SIGNAL(clicked()), this, SLOT(press_pbtn_01()));
    connect(timer,SIGNAL(timeout()),this,SLOT(onTimer()));
}




Widget::~Widget()
{
    delete ui;
}




void Widget::press_pbtn_01()
{
    timer->start(60);

}




bool Widget::move_zmeyka(int k)
{

    QList<segm> sg;

    int lng = zmeyka.length();

    for(int i = 0; i < lng; i++)
    {
        sg << zmeyka.at(i);
    }

    int x = sg.at(0).pos_x;
    int y = sg.at(0).pos_y;

    if(k == 1) sg[0].pos_y--;
    if(k == 2 )sg[0].pos_x--;
    if(k == 3 )sg[0].pos_y++;
    if(k == 4 )sg[0].pos_x++;


    if((sg[0].pos_x < 0) ||
            (sg[0].pos_y < 0) ||
                (sg[0].pos_x > table_row-1) ||
                    (sg[0].pos_y > table_col-1))
                        return true;

    // обход препятствий
    if(pole[sg[0].pos_x][sg[0].pos_y]) return true;


    sg[0].clr = 2;
    zmeyka[0] = sg.at(0);

    sg[0].pos_x = x;
    sg[0].pos_y = y;

    sg[0].clr = 1;


    for(int i = 1; i < lng; i++)
    {
        sg[i] = zmeyka.at(i);

        // последний сегмент белого цвета стирает след змейки
        if(i == lng-1) sg[i-1].clr = 0;

        zmeyka[i] = sg.at(i-1);
    }

    print_zmeyka();
    return false;
}




void Widget::make_zmeyka()
{
    segm sg;

    // длина змейки
    for(int i = 20; i < 30; i++)
    {
        sg.pos_x = 15;
        sg.pos_y = i;

        sg.clr = 1;
        if(i == 20) sg.clr = 2;
        if(i == 29) sg.clr = 0;

        zmeyka << sg;
    }
}




void Widget::print_zmeyka()
{
    segm sg;
    QColor sclr;

    sg = zmeyka.at(zmeyka.size()-1);
    ui->tableWidget->item(sg.pos_x, sg.pos_y)->setBackgroundColor(Qt::white);


    for(int i = 0; i < zmeyka.size(); i++)
    {
        sg = zmeyka.at(i);

        if(sg.clr == 0) sclr = Qt::white;
        if(sg.clr == 1) sclr = Qt::green;
        if(sg.clr == 2) sclr = Qt::red;

        ui->tableWidget->item(sg.pos_x, sg.pos_y)->setBackgroundColor(sclr);
    }
}




void Widget::onTimer()
{
    static int cx = 0;
    static int napr = 3;
    static int oldnapr = 1;

    if(!(cx % 7))
    {
    met_10:

        napr = (qrand() % 4) + 1;

        // запрет возврата в саму себя
        if(napr == 2 && oldnapr == 4)  goto met_10;
        if(napr == 4 && oldnapr == 2)  goto met_10;
        if(napr == 1 && oldnapr == 3)  goto met_10;
        if(napr == 3 && oldnapr == 1)  goto met_10;
    }

    // обход препятствий
    if(move_zmeyka(napr)) goto met_10;

    oldnapr = napr;
    cx++;
}


Название: Re: Змейка.
Отправлено: qtkoder777 от Май 19, 2022, 20:56
У меня в мобиле змейка умирает при самопересечении. Поддерживается ли это?


Название: Re: Змейка.
Отправлено: kambala от Май 19, 2022, 23:03
змейка на QTableWidget — это сильно :)


Название: Re: Змейка.
Отправлено: alexu007 от Май 20, 2022, 00:02
У меня в мобиле змейка умирает при самопересечении. Поддерживается ли это?
Нет. Она не самопересекается.


Название: Re: Змейка.
Отправлено: alexu007 от Май 20, 2022, 00:07
змейка на QTableWidget — это сильно :)
Почему нет? Таблицу для многого приспособить можно - все игры, где есть сетка, и не требуется большого быстродействия. Морской бой, например. Шахматы. И т.п.



Название: Re: Змейка.
Отправлено: qtkoder777 от Май 20, 2022, 11:02
Какая-то насмешка над легендарной игрой.

Играть в змейку нельзя. Только смотреть.

Змейка должна есть предметы в ячейках и увеличивать длину.

Ввод в ячейки стоит заблокировать.

Запуск стоит сделать с клавиатуры.



Название: Re: Змейка.
Отправлено: alexu007 от Май 20, 2022, 12:18
Да это не игра. Это просто реализация самой змейки.


Название: Re: Змейка.
Отправлено: tux от Май 20, 2022, 20:10
Ну, люди в своё время в Excel картины рисовали. Одна ячейка - одна точка. Вроде как даже продали одну из таких картин. :D
Так что змейка в QTableWidget - вполне себе. Голову размять.


Название: Re: Змейка.
Отправлено: qtkoder777 от Май 23, 2022, 17:22
Голова вовсе не разминается. Написав алгоритм змейки переделка на QTableWidget делается автозаменой по тексту операции закраски.