1

我正在修补一种从这个问题打印房间的方法。我使用来自扩展 ASCII的方框绘图字符来测试它,所以我认识到这限制了我的代码将在其上编译的范围。

如果您不想在那里阅读,请快速解释问题:

房间被定义为一个 4 位整数,使得

  • 最高位代表房间是否有西墙
  • 房间是否有北墙的下一个最重要的位
  • 房间是否有东墙的最不重要的一点
  • 最低位表示房间是否有南墙

例如,由0b1101表示的房间将有西墙、北墙和南墙:

┌─
│
└─

还有额外的限制:

  1. 房间的外墙总是有一堵墙
  2. 内墙将始终在两个房间中表示(示例0b1101有一面墙向南,所以它下面的房间必须设置次高有效位来指示北墙)
  3. 永远不会超过numeric_limits<int>::max()房间

我的问题是选择交叉字符。我的蛮力算法必须访问每个房间两次(第一行/列中的房间除外)。有没有办法找到每个房间只有一次内存访问的交叉点?


如果您想查看我的代码以供参考;它包含:

  1. Avector<char>的房间信息
  2. Asize_t给出行宽
  3. Avector<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;

Live Example

4

0 回答 0