Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
*.exe
*.vcxproj.user
*.obj
*.log
*.pdb
*.idb
*.tlog
*.lastbuildstate
*.ilk
*.exe.recipe
*.vcxproj
*.sln
*.vcxproj.filters
12 changes: 12 additions & 0 deletions Practise_18.11.20/Practise_18.11.20/MCell.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once

class MCell {
public:
bool down() const { return m_down; }
bool right() const { return m_right; }
friend class Maze;
private:
MCell() = default;
bool m_down = false;
bool m_right = false;
};
78 changes: 78 additions & 0 deletions Practise_18.11.20/Practise_18.11.20/MTreeNode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#include <algorithm>
#include <iostream>
#include <queue>
#include "MTreeNode.h"
using namespace std;

This comment was marked as resolved.


MTreeNode* MTreeNode::beginTree(int i, int j) {
MTreeNode* node = new MTreeNode(nullptr);

This comment was marked as resolved.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут утечка, верно? Кстати говоря, я вызывал delete для корня дерева в practise_18.11.20.cpp в случае построения второго лабиринта (про третий благополучно забыл). Но я догадываюсь, что это не есть хорошо. Можете намекнуть на пример корректного поведения для beginTree?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Извиняюсь, запутался... Всё норм.

node->m_i = i;
node->m_j = j;
return node;
}

MTreeNode::MTreeNode(MTreeNode* parent) {
m_parent = parent;
if (parent) m_distance = parent->m_distance + 1;
}

MTreeNode::~MTreeNode() {
for (auto ptr : m_children)
delete ptr;

This comment was marked as resolved.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Речь о том, что я мог просто вызвать delete[] ? Или я оставляю в памяти висеть детей того родителя, у которого вызывается деструктор?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Сорян, всё норм. Я уже обревьювился в конец...

}

bool MTreeNode::addChild(int i, int j) {
if (abs(i - m_i + j - m_j) != 1)
return false;

for (auto &child : m_children)
if (child->m_i == i && child->m_j == j)
return false;
m_children.push_back(new MTreeNode(this));

This comment was marked as resolved.

m_children.back()->m_i = i;
m_children.back()->m_j = j;
return true;
}

MTreeNode* MTreeNode::hasChild(int i, int j) const{
for (auto child : m_children){
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Разумно не делать копии, то есть auto&
Хотя при нашем размере, можно и копию себе позволить...

if (child->m_i == i && child->m_j == j)
return child;
}
return nullptr;
}

//�����, ����������� ����� ���� � ������ ������� �� �����
const MTreeNode* MTreeNode::searchNode(const int i, const int j) const{
queue<MTreeNode*> nodes;
auto node = searchRoot(this);
while (true)
{
if (node->m_i == i && node->m_j == j) return node;
for (const auto child : node->m_children) {
if (child->i() == i && child->j() == j)
return child;
nodes.push(child);
}
if (nodes.size() == 0)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это можно вынести в while, так то!

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Я могу заблуждаться, но ведь есть ситуация при которой мы достанем новый узел из очереди и она опустеет, однако этот узел будет иметь детей, которых потом также потребуется обойти. Мы прервем цикл до их обхода.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ошибаетесь, подумайте...

break;
node = nodes.front();
nodes.pop();
}
}

//����� ������ ����� � �����
const MTreeNode* MTreeNode::searchRoot(const MTreeNode* node) const{
queue<MTreeNode*> nodes;
MTreeNode* parent = node->m_parent;
if (!parent)
return node;
else {
while (true) {
MTreeNode* temp = parent->m_parent;
if (!temp) break;
parent = temp;
}
return parent;
}
}
25 changes: 25 additions & 0 deletions Practise_18.11.20/Practise_18.11.20/MTreeNode.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once
#include <vector>

class MTreeNode
{
public:
~MTreeNode();
int i() const { return m_i; }
int j() const { return m_j; }
int distance() const { return m_distance; }
int childCount() const { return m_children.size(); }
bool addChild(int i, int j);
const MTreeNode* parent() const { return m_parent; }
MTreeNode* hasChild(int i, int j) const;
const MTreeNode* child(int i) const { return m_children[i]; }
static MTreeNode* beginTree(int i, int j);
const MTreeNode* searchNode(const int i, const int j) const;
const MTreeNode* searchRoot(const MTreeNode* node) const;
private:
int m_i, m_j = 0;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Что-то тут копипастой запахло.
Где-то уже видел...

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Вы сказали, что бы я исправил былое безобразие. Вы мне вариантом предложили сделать отдельный метод для поиска корня, если я хочу не зависеть от передаваемого узла. Я так и поступил.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Дык не про то речь... Ну и ладно...

int m_distance = 0;
MTreeNode* m_parent = nullptr;
std::vector<MTreeNode*> m_children;
MTreeNode(MTreeNode* parent);
};
113 changes: 113 additions & 0 deletions Practise_18.11.20/Practise_18.11.20/Maze.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#include <algorithm>
#include <iostream>
#include <map>
#include "Maze.h"
#include <cassert>
using namespace std;

enum MazeElem {
Up = 1 << 0,
Left = 1 << 1,
Down = 1 << 2,
Right = 1 << 3,
UpLeft = Up + Left,
UpDown = Up + Down,
UpRight = Up + Right,
LeftDown = Left + Down,
LeftRight = Left + Right,
RightDown = Right + Down,
UpLeftDown = Up + Left + Down,
UpLeftRight = Up + Left + Right,
UpDownRight = Up + Down + Right,
LeftDownRight = Left + Down + Right,
AllDirection = Up + Left + Down + Right,
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Наркота то какая.... Наркотаааааа....."
Ну я сам напросился. В целом грамотно, битовые флаги, все дела, енум. Всё как учили.
По хорошему, под это дело бы отдельный класс сделать. Но мы учимся, так что норм.

static map<int, char> m_dict = { {AllDirection, char(197)}, {UpLeftDown, char(180)}, {UpLeftRight, char(193)},
{UpDownRight, char(195)}, {LeftDownRight, char(194)}, {UpLeft, char(217)},
{UpDown, char(179)}, {UpRight, char(192)}, {LeftDown, char(191)},
{LeftRight, char(196)}, {RightDown, char(218)}, {Up, '0'}, {Down, '0'}, {Left, '0'}, {Right, '0'}, {0, '0'}
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Молодца! статик!


Maze::Maze(int n, int m) {
m_width = m;
m_height = n;
m_field = new MCell[m * n];
}

Maze::~Maze() { delete[] m_field; }

const MCell& Maze::cell(int i, int j) const {
assert(i >= 0 && i < m_height && j >= 0 && j < m_width);
return m_field[i * m_width + j];
}

bool Maze::checkConnection(int i1, int j1, int i2, int j2) const {
assert(i1 == i2 || j1 == j2);
if ((abs(i1 - i2) + abs(j1 - j2) != 1))
return false;
if (j2 < 0 || j2 >= m_width || i2 < 0 || i2 >= m_height)
return false;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Может вынести эти штучки отдельно. А то дублирование получается. Ниже то же самое написано...

}

bool Maze::hasConnection(int i1, int j1, int i2, int j2) const {
if (!checkConnection(i1, j1, i2, j2))
return false;
const int ind1 = min(i1, i2);
const int ind2 = min(j1, j2);
if (i1 == i2) {
return m_field[ind1 * m_width + ind2].right();
}
else if (j2 == j1) {
return m_field[ind1 * m_width + ind2].down();
}
}

bool Maze::makeConnection(int i1, int j1, int i2, int j2) {
if (!checkConnection(i1, j1, i2, j2))
return false;
const int ind1 = min(i1, i2);
const int ind2 = min(j1, j2);
if (i1 == i2) {
m_field[ind1 * m_width + ind2].m_right = true;
return true;
}
else if (j1 == j2) {
m_field[ind1 * m_width + ind2].m_down = true;
return true;
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут при неправильных индексах надо бы ассерт сделать. Хотя и не обязательно.
Ну и замечания выше.


bool Maze::removeConnection(int i1, int j1, int i2, int j2) {
if (!checkConnection(i1, j1, i2, j2))
return false;
int ind1 = min(i1, i2);
int ind2 = min(j1, j2);
if (i1 == i2) {
bool res = m_field[ind1 * m_width + ind2].m_right;
m_field[ind1 * m_width + ind2].m_right = false;
return res;
}
else if (j2 == j1) {
bool res = m_field[ind1 * m_width + ind2].m_down;
m_field[ind1 * m_width + ind2].m_down = false;
return res;
}
}

void Maze::printMaze() const {
for (int n = 0; n < m_width * m_height; ++n) {
int i = n / m_width;
int j = n % m_width;
int res = m_field[n].down() << 2 | m_field[n].right() << 3;
if (i - 1 >= 0)
res += m_field[(i - 1) * m_width + j].down() << 0;
if (j - 1 >= 0)
res += m_field[i * m_width + j - 1].right() << 1;

assert(typeid(m_dict.find(res)->second) == typeid(char));
cout << m_dict.find(res)->second;

if (j + 1 == m_width)
cout << endl;
}
}
18 changes: 18 additions & 0 deletions Practise_18.11.20/Practise_18.11.20/Maze.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once
#include "MCell.h"

class Maze {
public:
Maze(int n, int m);
~Maze();
const MCell& cell(int i, int j) const;
bool checkConnection(int i1, int j1, int i2, int j2) const;
bool hasConnection(int i1, int j1, int i2, int j2) const;
bool makeConnection(int i1, int j1, int i2, int j2);
bool removeConnection(int i1, int j1, int i2, int j2);
void printMaze() const;
private:
MCell* m_field = nullptr;
int m_width = 0;
int m_height = 0;
};
Loading