受Doug T. 的解决方案的启发,我自己编写了以下内容。
基本上我两次遍历矩阵(性能不佳:/)。我第一次在矩阵中的每个1 周围画墙,我用位掩码来做这个。第二次我清理了所有“向内”的墙壁。
示例设置:
// Add padding to output-matrix
int owidth = width+2;
int oheight = height+2;
// 4-bit value: 0bWSEN
static char N = 0x1; // The dash that goes from the center to the north
static char E = 0x2; // The dash that goes from the center to the east
static char S = 0x4; // ...
static char W = 0x8;
// This is what I will draw around every tile
char box[] =
{S|E, E|W, W|S,
N|S, 0 , N|S,
N|E, E|W, W|N };
围墙循环:
for(unsigned int y = 0; y < height; y++)
for(unsigned int x = 0; x < width; x++)
{
// We ignore walls
if (! isOne(x, y)) // isOne takes care of out-of-bounds
continue;
// Go through neighbourhood
for(int dy = -1; dy <= 1; dy++)
for(int dx = -1; dx <= 1; dx++)
{
if (dy == 0 && dx == 0) // Ignore self
continue;
if (! isOne(x+dx, y+dy))
{
// Draw part of box
int ox = x+1, oy = y+1; // output-x and y
out[(oy+dy)*owidth+(ox+dx)] |= box[(dy+1)*3 + (dx+1)];
}
}
}
清理循环:
// Clean up "pointing edges"
for(unsigned int y = 0; y < height; y++)
for(unsigned int x = 0; x < width; x++)
{
// We ignore zero's since we're only cleaning walls.
if (isOne(x, y))
continue;
int ox = x+1, oy = y+1; // output-x and y
// Remove edges that points to 'zero'-cells.
if (! isOne(x , y-1)) out[y*width+x] &= ~N;
if (! isOne(x , y+1)) out[y*width+x] &= ~S;
if (! isOne(x-1, y )) out[y*width+x] &= ~W;
if (! isOne(x+1, y )) out[y*width+x] &= ~E;
}
然后我将有一个 16 大小(每个符号一个)的查找列表,每个字符一个条目。
map<unsigned int, wchar_t> p;
p[0] = ' ';
p[N] = '.';
// ...
p[N|S] = L'\u2502'; // │
p[E|W] = L'\u2500'; // ─
// ...
p[N|E|S|W] = L'\u253C'; // ┼
这个算法无论如何都不是有效的,O(2*width*height) 不好......它可以通过生成一个 256 大小的循环表来改进,就像其他人建议的那样,这会给我们 O( 1) 执行时。