Написал муравья ленгтона на 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; }
}
};
Ну так а кто за вас будет освобождать ресурсы?
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
.
Раз уж вы определили структуру, описывающую точку/вектор, то почему бы не использовать ее для представления всех точек/векторов в программе?
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Рекомендуемая литература и документация по знаниям и навыкам разработки, не привязанным к конкретным языкам и платформам
Подскажите, пожалуйста, отрисовывает ли SFML то, что находится за пределами используемого вида?
Мне нужно создать тип данных Percent, который бы хранил в себе только целые числа от 0 до 100, и чтобы логика была такая: