Не работает муравей ленгтона на c++

254
30 октября 2021, 06:30

Написал муравья ленгтона на c++, для визуализации использовал функции winapi.
Муравей ходит нормально ровно до того момента когда он должен начать рисовать магистраль, на этом моменте он останавливается и больше ничего не изменяется.
Пытался вывести вектор направления муравья, это показало что он бесконечно ходит по квадрату из 4 клеток.

Вот код программы:

#include <windows.h>
#include <iostream>
#include <time.h>
#include "lenghtonAnt.h"
using namespace std;
int main(void) {
    srand(time(NULL));
    COLORREF mainColor;
    int CountOfStep = 15000;
    mainColor = RGB(50, 50, 50);
    int width = GetSystemMetrics(SM_CXSCREEN);
    int height = GetSystemMetrics(SM_CYSCREEN);
    int SizeOfPart = 3;
    int padding = 1;
    int c = 0;
    int x_ = width / (SizeOfPart + padding), y_ = height / (SizeOfPart + padding);
    vectorAnt vect_mov;
    vect_mov.x = -1;
    vect_mov.y = 0;
    int buferSizeOfPart = SizeOfPart;
    while (((width % (SizeOfPart + padding)) != 0) & ((height % (SizeOfPart + padding)) != 0)) {
        if (SizeOfPart == 0) { break; }
        SizeOfPart -= 1;
    }
    if (SizeOfPart == 0) {
        while (((width % (SizeOfPart + padding)) != 0) & ((height % (SizeOfPart + padding)) != 0)) {
            if ((SizeOfPart == (SizeOfPart * 2))) { break; }
            SizeOfPart += 1;
        }
    }
    HDC dc = GetDC(NULL);
    HWND hWnd = GetDesktopWindow();

    HDC dcCompatible = CreateCompatibleDC(dc);
    HBITMAP hbm = CreateCompatibleBitmap(dc, width, height);
    SelectObject(dcCompatible, hbm);
    HBRUSH hBrush;
    //color = RGB(226, 124, 62);
    hBrush = CreateSolidBrush(mainColor);
    SelectObject(dcCompatible, hBrush);
    for (size_t y = 0; y < y_; y++) {
        for (size_t x = 0; x < x_; x++) {
            CreatRect(dcCompatible, x, y, SizeOfPart, width, height, padding, hbm);
        }
    }
    lengtonAnt Ant(dc, dcCompatible, hbm, x_ / 2.5, y_ / 2.5, vect_mov, width, height, padding, SizeOfPart, mainColor);
    for (int i = 0; i < 100 / (SizeOfPart / 2); i++) {
        BitBlt(dc, 0, 0, width, height, dcCompatible, 0, 0, SRCCOPY);
    }
    for (int i = 0; i < CountOfStep; i++) {
        Ant.makeMov();
    }
    return 0;
}

Вот код описания функций, и самого класа для муравья :

#pragma once
#include <windows.h>
using namespace std;
struct vectorAnt {
    int x;
    int y;
};
void CreatRect(HDC dc, int nx, int ny, int SizeOfPart, int width, int height, int padding, HBITMAP hbm) {
    const int size = 4;
    POINT p[size];
    p[0] = { nx + (padding * nx + nx * SizeOfPart), ny + (padding * ny + ny * SizeOfPart) };
    p[1] = { nx + SizeOfPart + (padding * nx + nx * SizeOfPart), ny + (padding * ny + ny * SizeOfPart) };
    p[2] = { nx + SizeOfPart + (padding * nx + nx * SizeOfPart), ny + SizeOfPart + (padding * ny + ny * SizeOfPart) };
    p[3] = { nx + (padding * nx + nx * SizeOfPart), ny + SizeOfPart + (padding * ny + ny * SizeOfPart) };
    Polygon(dc, p, size);
}
class lengtonAnt {
public:
    lengtonAnt(HDC mainDc_, HDC buferDC_, HBITMAP hbm_, int xn_, int yn_, vectorAnt vect_, int width_, int height_, int padding_, int sizeOfPart, COLORREF MainColor) {
        mainDc = mainDc_;
        buferDC = buferDC_;
        hbm = hbm_;
        xn = xn_;
        yn = yn_;
        width = width_;
        height = height_;
        padding = padding_;
        SizeOfPart = sizeOfPart;
        vect = vect_;
        mainColor = MainColor;
    }
    void makeMov() {
        if (WhatColor()) {
            switch (vect.x) {
            case -1:
                vect.x = 0;
                vect.y = -1;
                break;
            case 1:
                vect.x = 0;
                vect.y = 1;
                break;
            case 0:
                switch (vect.y) {
                case -1:
                    vect.y = 0;
                    vect.x = 1;
                    break;
                case 1:
                    vect.y = 0;
                    vect.x = -1;
                    break;
                }
            }
            SelectObject(buferDC, hbm);
            color = RGB(226, 124, 62);
            hBrush = CreateSolidBrush(color);
            SelectObject(buferDC, hBrush);
            CreatRect(buferDC, xn, yn, SizeOfPart, width, height, padding, hbm);
            BitBlt(mainDc, 0, 0, width, height, buferDC, 0, 0, SRCCOPY);
        }
        else {
            switch (vect.x) {
            case -1:
                vect.x = 0;
                vect.y = 1;
                break;
            case 1:
                vect.x = 0;
                vect.y = -1;
                break;
            case 0:
                switch (vect.y) {
                case -1:
                    vect.y = 0;
                    vect.x = -1;
                    break;
                case 1:
                    vect.y = 0;
                    vect.x = 1;
                    break;
                }
            }
            SelectObject(buferDC, hbm);
            color = mainColor;
            hBrush = CreateSolidBrush(color);
            SelectObject(buferDC, hBrush);
            CreatRect(buferDC, xn, yn, SizeOfPart, width, height, padding, hbm);
            BitBlt(mainDc, 0, 0, width, height, buferDC, 0, 0, SRCCOPY);
        }
        switch (vect.x) {
        case -1:
            xn -= 1;
            break;
        case 1:
            xn += 1;
            break;
        case 0:
            switch (vect.y) {
            case -1:
                yn -= 1;
                break;
            case 1:
                yn += 1;
                break;
            }
        }
        BitBlt(mainDc, 0, 0, width, height, buferDC, 0, 0, SRCCOPY);
    }
private:
    HDC mainDc;
    HDC buferDC;
    HBITMAP hbm;
    COLORREF color, mainColor;
    HBRUSH hBrush;
    vectorAnt vect;
    int xn, yn, width, height, padding, SizeOfPart;
    bool WhatColor() {
        if (GetPixel(buferDC, xn + (SizeOfPart / 2) + (padding * xn + xn * SizeOfPart), yn + (SizeOfPart / 2) + (padding * yn + yn * SizeOfPart)) == RGB(50, 50, 50)) {
            return 1;
        }
        else { return 0; }
    }
};
Answer 1

Ну так а кто за вас будет освобождать ресурсы?

hBrush = CreateSolidBrush(color);

Если вы будете вот так смело создавать кисть за кистью на каждой итерации цикла, не заботясь об их освобождении, то ресурсы GDI быстро переполнятся, кисти перестанут создаваться и рисование перестанет работать. А у вас вся программа построена на обратной связи от рисования через GetPixel.

Реализация, построенная на обратной связи от рисования - это криво. Но если вы почините утечку ресурсов, то все будет работать

  • Повороты на 90 градусов реализуются просто как

    std::swap(vect.x, vect.y);
    vect.x = -vect.x; 
    // или vect.y = -vect.y
    

    Не нужно городить шестиэтажный switch. Надо только внимательно проследить, куда у вас направлена ось Y и, соответственно, где у вас лево и право.

  • Перемещение точки по направлению реализуется как

    xn += vect.x;
    yn += vect.y;
    

    то есть и здесь не нужен трехэтажный switch.

  • Раз уж вы определили структуру, описывающую точку/вектор, то почему бы не использовать ее для представления всех точек/векторов в программе?

READ ALSO
Книги и учебные ресурсы по фундаментальным знаниям и навыкам разработчика

Книги и учебные ресурсы по фундаментальным знаниям и навыкам разработчика

Рекомендуемая литература и документация по знаниям и навыкам разработки, не привязанным к конкретным языкам и платформам

157
SFML, View и отрисовка

SFML, View и отрисовка

Подскажите, пожалуйста, отрисовывает ли SFML то, что находится за пределами используемого вида?

81
Свой тип данных с границами в C++

Свой тип данных с границами в C++

Мне нужно создать тип данных Percent, который бы хранил в себе только целые числа от 0 до 100, и чтобы логика была такая:

103