我正在修补一种从这个问题打印房间的方法。我使用来自扩展 ASCII的方框绘图字符来测试它,所以我认识到这限制了我的代码将在其上编译的范围。
如果您不想在那里阅读,请快速解释问题:
房间被定义为一个 4 位整数,使得
- 最高位代表房间是否有西墙
- 房间是否有北墙的下一个最重要的位
- 房间是否有东墙的最不重要的一点
- 最低位表示房间是否有南墙
例如,由0b1101表示的房间将有西墙、北墙和南墙:
┌─
│
└─
还有额外的限制:
- 房间的外墙总是有一堵墙
- 内墙将始终在两个房间中表示(示例0b1101有一面墙向南,所以它下面的房间必须设置次高有效位来指示北墙)
- 永远不会超过
numeric_limits<int>::max()
房间
我的问题是选择交叉字符。我的蛮力算法必须访问每个房间两次(第一行/列中的房间除外)。有没有办法找到每个房间只有一次内存访问的交叉点?
如果您想查看我的代码以供参考;它包含:
- A
vector<char>
的房间信息 - A
size_t
给出行宽 - A
vector<int>
带有每个房间的标签(这可以设置vector(size(testValues), -17)
为只打印没有标签的房间结构
string printArray(const vector<char>& testValues, const size_t width, const vector<int>& indexes) {
if (empty(testValues)) {
return string();
} else {
string result;
auto prevLine = "\xC9\xCD"s;
prevLine.reserve(2U * (1U + width));
for (auto i = 0U; i + 1 < width; ++i) {
if ((testValues[i] & 0b10) != 0) {
prevLine += "\xD1\xCD"s;
} else {
prevLine += "\xCD\xCD"s;
}
}
prevLine += "\xBB\n"s;
result.reserve(size(prevLine) * (1U + 2U * size(testValues) / width));
for (auto i = 0U; i < size(testValues) - width; ++i) {
const auto x = i % width;
const auto isBottomSet = (testValues[i] & 0b1) != 0;
if (x == 0) {
result += (prevLine + '\xBA') + static_cast<char>('0' + indexes[i]);
prevLine = isBottomSet ? "\xC7\xC4"s : "\xBA "s;
}
if (x + 1U == width) {
result += "\xBA\n"s;
prevLine += isBottomSet ? "\xB6\n"s : "\xBA\n"s;
} else {
const auto isRightSet = (testValues[i] & 0b10) != 0;
const size_t index = static_cast<int>(isRightSet) << 3 | testValues[i + width + 1] & 0b100 | (testValues[i + width + 1] & 0b1000) >> 2 | static_cast<int>(isBottomSet);
// MSB: isAboveIntersectionSet
// isRightOfIntersectionSet
// isBelowIntersectionSet
// LSB: isLeftOfIntersectionSet
constexpr const char* getIntersection[] = { " ", // 0b0
" ", // 0b1
" ", // 0b10
"\xBF ", // 0b11
" \xC4", // 0b100
"\xC4\xC4", // 0b101
"\xDA\xC4", // 0b110
"\xC2\xC4", // 0b111
" ", // 0b1000:
"\xD9 ", // 0b1001
"\xB3 ", // 0b1010
"\xB4 ", // 0b1011
"\xC0\xC4", // 0b1100
"\xC1\xC4", // 0b1101
"\xC3\xC4", // 0b1110
"\xC5\xC4" }; // 0b1111
result += { isRightSet ? '\xB3' : ' ', static_cast<char>('0' + indexes[i + 1]) };
prevLine += getIntersection[index];
}
}
result += (prevLine + '\xBA') + static_cast<char>('0' + indexes[size(testValues) - width]);
prevLine = "\xC8\xCD"s;
for (auto i = size(testValues) - width; i + 1 < size(testValues); ++i) {
if ((testValues[i] & 0b10) != 0) {
result += { '\xB3', static_cast<char>('0' + indexes[i + 1]) };
prevLine += "\xCF\xCD"s;
} else {
result += { ' ', static_cast<char>('0' + indexes[i + 1]) };
prevLine += "\xCD\xCD"s;
}
}
return result + "\xBA\n"s + prevLine + '\xBC';
}
}
如果您对此的简单测试感兴趣,您可以这样做:
const vector<char> rooms = { 0b1101, 0b110, 0b1101, 0b110, 0b1100, 0b101, 0b110,
0b1110, 0b1001, 0b110, 0b1011, 0b1010, 0b1111, 0b1010,
0b1000, 0b101, 0b11, 0b1110, 0b1011, 0b1110, 0b1010,
0b1011, 0b1101, 0b101, 0b1, 0b101, 0b11, 0b1011 };
const vector<int> indexes = { 1, 1, 2, 2, 3, 3, 3,
1, 1, 1, 2, 3, 5, 3,
1, 1, 1, 6, 3, 6, 3,
1, 6, 6, 6, 6, 6, 3 };
cout << printArray(rooms, width, indexes) << endl;