看了網路上一些錯覺圖後產生靈感,就隨手寫了個小程式來驗證想法,不過效果似乎不太好。我也不知道其他人看起來感覺如何,歡迎回饋意見讓我知道。
程式執行後會在同資料夾輸出 maze.bmp ,如下圖。 (滑鼠請點擊放大,才看得到效果)

 

重口味版本

因為是一邊產生一邊寫檔,所以一些圖形細節的部分就懶得處理了。
程式碼草稿如下,因為只是驗證概念,程式碼寫得比較隨性。

#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <algorithm>

using namespace std;

const int W = 55, H = 37;
const int BSIZE = 16, DEPTH = 2;
const int FACE[][3] = { {210, 210, 0}, {0, 102, 255} };
const int EDGE[][3] = { {255, 255, 255}, {0, 0, 0}, {100, 128, 128} };

const int *lColor = EDGE[0], *rColor = EDGE[1];
const int *tColor = EDGE[1], *bColor = EDGE[0];
char mz[(W+1) * (H+2)] = {0};

void Gen(int p, int d)
{
if (mz[p] == 1) {
int v[] = {-1, 1, -(W + 1), W + 1};
random_shuffle(v, v + 4);
mz[p] = mz [p - d] = 0;
for (int i = 0; i < 4; ++i) Gen(p + 2 * v[i], v[i]);
}
}

inline void PushWord(char*& buf, unsigned w)
{
buf[0] = w;
buf[1] = w >> 8;
buf[2] = w >> 16;
buf[3] = w >> 24;
buf += 4;
}

char* FillRGB(char* buf, int r, int g, int b, int count = 1)
{
for (int i = 0; i < count; ++i) {
buf[0] = b;
buf[1] = g;
buf[2] = r;
buf += 3;
}
return buf;
}

void DrawSeg(char* buf, const int* c0, const int* c1, const int* c2)
{
buf = FillRGB(buf, c0[0], c0[1], c0[2], DEPTH);
buf = FillRGB(buf, c1[0], c1[1], c1[2], BSIZE-2*DEPTH);
buf = FillRGB(buf, c2[0], c2[1], c2[2], DEPTH);
}

void DrawBox(char** buf, int offset, int curr, int left, int right, int top, int bot)
{
if (curr) {
const int *c0, *c1, *c2;
c0 = (lColor != tColor) && !(top ^ left)? EDGE[2] : (top? lColor : tColor);
c1 = top? FACE[1] : tColor;
c2 = (rColor != tColor) && !(top ^ right)? EDGE[2] : (top? rColor: tColor);
DrawSeg(buf[0] + offset, c0, c1, c2);

c0 = left? FACE[1] : lColor;
c2 = right? FACE[1] : rColor;
DrawSeg(buf[1] + offset, c0, FACE[1], c2);

c0 = (lColor != bColor) && !(bot ^ left)? EDGE[2] : (bot? lColor : bColor);
c1 = bot? FACE[1] : bColor;
c2 = (rColor != bColor) && !(bot ^ right)? EDGE[2] : (bot? rColor: bColor);
DrawSeg(buf[2] + offset, c0, c1, c2);
} else {
for (int i = 0; i < 3; ++i)
FillRGB(buf[i] + offset, 210, 210, 0, BSIZE);
}
}

void WriteBMP()
{
size_t width = (W+2) * BSIZE, height = (H+2) * BSIZE;
size_t rowSize = width * 3;
size_t pad = (4 - (rowSize & 0x03)) & 0x03;
size_t dataSize = (rowSize + pad) * height;

char header[54] = "BM";
char* ph = header + 2;
PushWord(ph, dataSize + 54);
PushWord(ph, 0);
PushWord(ph, 54);
PushWord(ph, 40);
PushWord(ph, width);
PushWord(ph, height);
PushWord(ph, 0x00180001);
PushWord(ph, 0);
PushWord(ph, dataSize);
PushWord(ph, 0);
PushWord(ph, 0);
PushWord(ph, 0);
PushWord(ph, 0);

FILE* fout = fopen("maze.bmp", "wb");
fwrite(header, 1, 54, fout);

char* rowBuf[3];
rowBuf[0] = new char[3 * (rowSize + pad)];
rowBuf[1] = rowBuf[0] + rowSize + pad;
rowBuf[2] = rowBuf[1] + rowSize + pad;

for (int i = 0; i < 3; ++i)
FillRGB(rowBuf[i], 210, 210, 0, width);
for (int i = 0; i < BSIZE; ++i)
fwrite(rowBuf[0], 1, rowSize + pad, fout);

for (int j = 0; j < H; ++j) {
char* prev = mz + j * (W+1);
char* curr = mz + (j+1) * (W+1);
char* next = mz + (j+2) * (W+1);

if (((H-1-j) % (H/4)) == (H/8)) swap(tColor, bColor);
for (int i = 0; i < W; ++i) {
if ((i % (W/4)) == (W/8)) swap(lColor, rColor);
DrawBox(rowBuf, (i+1)*BSIZE*3, curr[i],
curr[i-1], curr[i+1], prev[i], next[i]);
}
for (int i = 0; i < DEPTH; ++i)
fwrite(rowBuf[0], 1, rowSize + pad, fout);
for (int i = 0; i < BSIZE - 2 * DEPTH; ++i)
fwrite(rowBuf[1], 1, rowSize + pad, fout);
for (int i = 0; i < DEPTH; ++i)
fwrite(rowBuf[2], 1, rowSize + pad, fout);
}
FillRGB(rowBuf[0], 210, 210, 0, width);
for (int i = 0; i < BSIZE; ++i)
fwrite(rowBuf[0], 1, rowSize + pad, fout);

delete[] rowBuf[0];
fclose(fout);
}

int main()
{
for (char* row = mz+W+1; row < mz + (H+1)*(W+1); row += W+1)
fill(row, row + W, 1);
srand(time(0));
int x = (rand() % (W/2)) * 2 + 1;
int y = (rand() % (H/2)) * 2 + 2;
Gen((W+1)*y+x, 0);
WriteBMP();
}

novus 發表在 痞客邦 PIXNET 留言(4) 人氣()


留言列表 (4)

發表留言
  • damody
  • 有一點點,焦點相對較低的感覺。
  • 所以你也覺得看不太出來嗎

    想了解一下
    你使用的螢幕尺寸及類型
    還有你隔多遠看

    novus 於 2010/08/06 12:49 回覆

  • 小斌
  • 我有看出來,而且覺得效果滿強烈的。

    螢幕尺寸是 21.5 吋 (474x269 mm) ,隔大概 88 公分遠看。解析度是 1920x1080 。
  • damody
  • 應該還是要漸層才會有效果。
  • 黑鬍子尼爾
  • 我覺得重口味版本飄動的程度反而沒前兩張明顯耶~