为了保持一些随机性,我这样处理这个问题:
-
为每个区域生成种子起点
只需计算每个区域的随机起点,其中任何两个起点之间必须至少有一些已定义的最小距离。这将提供一些增长空间,因此结果看起来更好。
-
尽可能地种植每一粒种子
简单地迭代扩大每个区域,直到不存在间隙(忽略所需的区域大小)
-
更正尺寸
所以只需将领土i=1 和任何邻近领土j>i 放大/缩小。然后处理i=2 ...完成后按降序执行相同的操作,因此占据i=n的领土并从任何邻居j<i放大/缩小。
循环整个过程,直到区域大小正确
-
验证
bullet #3 可以将一些区域划分为非后续区域,我怀疑这是不受欢迎的。所以检测到这一点,如果案件再次产生这整个事情。
仅针对每个区域进行检测,找到它的第一个有效单元格并填充
算一算那块领地有多大。如果与已划分的区域大小不匹配,则应重新生成。
如果所有地区都匹配大小,则地图是相关的,您就完成了
这里是#1,#2,#3的预览:
表格标题中的数字是领土actual size - wanted size第一个数字是差距,然后是领土1,2,3 ...
还有我的 C++ 实现:
//---------------------------------------------------------------------------
// generator properties
const int n=7; // teritories+1
const int mx=19; // map size
const int my=11;
const int siz[n]={ 0,31,35,35,37,32,39 }; // teritory sizes (first is bordrer)
const int mindist=5; // min distance between teritory seed points
int map[mx][my]; // map 0 means no teritory else it is teritory ID
// rendering properties
const int grid=16; // grid size [pixels]
const DWORD col[n]= // teritory color table
{
0x00000000, // border (unused)
0x00FF0000, // territory 1
0x0000FF00, // territory 2
0x000000FF, // territory 3
0x00FFFF00, // territory 4
0x0000FFFF, // territory 5
0x00FF00FF, // territory 6
};
//---------------------------------------------------------------------------
void map_generate()
{
int x,y,xx,yy,i,j,e;
int cnt[n]; // generated teritory size
int seedx[n]; // start position for teritory
int seedy[n];
// AnsiString s="";
// s+=AnsiString().sprintf("Seed: %X |",RandSeed);
for (;;)
{
// clear map
cnt[0]=mx*my;
for (x=0;x<mx;x++)
for (y=0;y<my;y++)
map[x][y]=0;
// start position
for (i=1;i<n;)
{
// ranom position
seedx[i]=Random(mx);
seedy[i]=Random(my);
// find closest seed point x = distance to it
for (x=mx+my,j=1;j<i;j++)
{
y=abs(seedx[i]-seedx[j])+abs(seedy[i]-seedy[j]);
if (x>y) x=y;
}
// if OK use as seed point else repeat the whole thing again...
if (x>mindist)
{
map[seedx[i]][seedy[i]]=i;
cnt[i]=1; cnt[0]--; i++;
}
}
// un bounded growth fill (can exceeding area)
for (e=1;e;)
{
e=0;
for (x= 1;x<mx;x++) for (y=0;y<my;y++) { i=map[x][y]; if (i>0){ x--; if (map[x][y]==0) { map[x][y]=i; cnt[i]++; cnt[0]--; e=1; } x++; }}
for (x=mx-2;x>=0;x--) for (y=0;y<my;y++) { i=map[x][y]; if (i>0){ x++; if (map[x][y]==0) { map[x][y]=i; cnt[i]++; cnt[0]--; e=1; } x--; }}
for (x=0;x<mx;x++) for (y= 1;y<my;y++) { i=map[x][y]; if (i>0){ y--; if (map[x][y]==0) { map[x][y]=i; cnt[i]++; cnt[0]--; e=1; } y++; }}
for (x=0;x<mx;x++) for (y=my-2;y>=0;y--) { i=map[x][y]; if (i>0){ y++; if (map[x][y]==0) { map[x][y]=i; cnt[i]++; cnt[0]--; e=1; } y--; }}
}
// correct inequalities cnt[] vs. siz[]
for (;;)
{
// stop if all counts are matching
for (i=1;i<n;i++) if (cnt[i]!=siz[i]) { i=-1; break; } if (i>=0) break;
// growth i from any neighbor j>i
for (i=1;i<n;i++)
for (e=1;(e)&&(cnt[i]<siz[i]);)
{
e=0;
for (x= 1;x<mx;x++) for (y=0;y<my;y++) if ((i==map[x][y])&&(cnt[i]<siz[i])){ x--; j=map[x][y]; if ((i<j)&&(cnt[j]>1)){ map[x][y]=i; cnt[i]++; cnt[j]--; e=1; } x++; }
for (x=mx-2;x>=0;x--) for (y=0;y<my;y++) if ((i==map[x][y])&&(cnt[i]<siz[i])){ x++; j=map[x][y]; if ((i<j)&&(cnt[j]>1)){ map[x][y]=i; cnt[i]++; cnt[j]--; e=1; } x--; }
for (x=0;x<mx;x++) for (y= 1;y<my;y++) if ((i==map[x][y])&&(cnt[i]<siz[i])){ y--; j=map[x][y]; if ((i<j)&&(cnt[j]>1)){ map[x][y]=i; cnt[i]++; cnt[j]--; e=1; } y++; }
for (x=0;x<mx;x++) for (y=my-2;y>=0;y--) if ((i==map[x][y])&&(cnt[i]<siz[i])){ y++; j=map[x][y]; if ((i<j)&&(cnt[j]>1)){ map[x][y]=i; cnt[i]++; cnt[j]--; e=1; } y--; }
}
// shrink i from any neighbor j>i
for (i=1;i<n;i++)
for (e=1;(e)&&(cnt[i]>siz[i]);)
{
e=0;
for (x= 1;x<mx;x++) for (y=0;y<my;y++) if ((i==map[x][y])&&(cnt[i]>siz[i])){ x--; j=map[x][y]; if (i<j) { map[x+1][y]=j; cnt[j]++; cnt[i]--; e=1; } x++; }
for (x=mx-2;x>=0;x--) for (y=0;y<my;y++) if ((i==map[x][y])&&(cnt[i]>siz[i])){ x++; j=map[x][y]; if (i<j) { map[x-1][y]=j; cnt[j]++; cnt[i]--; e=1; } x--; }
for (x=0;x<mx;x++) for (y= 1;y<my;y++) if ((i==map[x][y])&&(cnt[i]>siz[i])){ y--; j=map[x][y]; if (i<j) { map[x][y+1]=j; cnt[j]++; cnt[i]--; e=1; } y++; }
for (x=0;x<mx;x++) for (y=my-2;y>=0;y--) if ((i==map[x][y])&&(cnt[i]>siz[i])){ y++; j=map[x][y]; if (i<j) { map[x][y-1]=j; cnt[j]++; cnt[i]--; e=1; } y--; }
}
// stop if all counts are matching
for (i=1;i<n;i++) if (cnt[i]!=siz[i]) { i=-1; break; } if (i>=0) break;
// growth i from any neighbor j<i
for (i=n-1;i>0;i--)
for (e=1;(e)&&(cnt[i]<siz[i]);)
{
e=0;
for (x= 1;x<mx;x++) for (y=0;y<my;y++) if ((i==map[x][y])&&(cnt[i]<siz[i])){ x--; j=map[x][y]; if ((i>j)&&(cnt[j]>1)){ map[x][y]=i; cnt[i]++; cnt[j]--; e=1; } x++; }
for (x=mx-2;x>=0;x--) for (y=0;y<my;y++) if ((i==map[x][y])&&(cnt[i]<siz[i])){ x++; j=map[x][y]; if ((i>j)&&(cnt[j]>1)){ map[x][y]=i; cnt[i]++; cnt[j]--; e=1; } x--; }
for (x=0;x<mx;x++) for (y= 1;y<my;y++) if ((i==map[x][y])&&(cnt[i]<siz[i])){ y--; j=map[x][y]; if ((i>j)&&(cnt[j]>1)){ map[x][y]=i; cnt[i]++; cnt[j]--; e=1; } y++; }
for (x=0;x<mx;x++) for (y=my-2;y>=0;y--) if ((i==map[x][y])&&(cnt[i]<siz[i])){ y++; j=map[x][y]; if ((i>j)&&(cnt[j]>1)){ map[x][y]=i; cnt[i]++; cnt[j]--; e=1; } y--; }
}
// shrink i from any neighbor j<i
for (i=n-1;i>0;i--)
for (e=1;(e)&&(cnt[i]>siz[i]);)
{
e=0;
for (x= 1;x<mx;x++) for (y=0;y<my;y++) if ((i==map[x][y])&&(cnt[i]>siz[i])){ x--; j=map[x][y]; if (i>j) { map[x+1][y]=j; cnt[j]++; cnt[i]--; e=1; } x++; }
for (x=mx-2;x>=0;x--) for (y=0;y<my;y++) if ((i==map[x][y])&&(cnt[i]>siz[i])){ x++; j=map[x][y]; if (i>j) { map[x-1][y]=j; cnt[j]++; cnt[i]--; e=1; } x--; }
for (x=0;x<mx;x++) for (y= 1;y<my;y++) if ((i==map[x][y])&&(cnt[i]>siz[i])){ y--; j=map[x][y]; if (i>j) { map[x][y+1]=j; cnt[j]++; cnt[i]--; e=1; } y++; }
for (x=0;x<mx;x++) for (y=my-2;y>=0;y--) if ((i==map[x][y])&&(cnt[i]>siz[i])){ y++; j=map[x][y]; if (i>j) { map[x][y-1]=j; cnt[j]++; cnt[i]--; e=1; } y--; }
}
}
// test if teritories are not divided and regenerate if needed
for (xx=0,i=1;i<n;i++)
{
// clear temp bit
for (x=0;x<mx;x++)
for (y=0;y<my;y++)
map[x][y]&=65535;
// find first occurence
j=0;
for (x=0;x<mx;x++)
for (y=0;y<my;y++)
if (map[x][y]==i) { map[x][y]|=65536; j=1; x=mx; y=my; }
if (!j) { xx=1; break; } // teritory not found
// growth fill count into j
for (e=1;e;)
for (e=0,x=0;x<mx;x++)
for ( y=0;y<my;y++)
if (map[x][y]==i)
{
yy=0;
if ((x> 0)&&(map[x-1][y]>=65536)) yy=1;
if ((x<mx-1)&&(map[x+1][y]>=65536)) yy=1;
if ((y> 0)&&(map[x][y-1]>=65536)) yy=1;
if ((y<my-1)&&(map[x][y+1]>=65536)) yy=1;
if (yy){ j++; map[x][y]|=65536; e=1; }
}
if (j!=siz[i]) { xx=1; break; } // teritory incorrect size
}
if (xx) continue; // regenerate again
// clear temp bit
for (x=0;x<mx;x++)
for (y=0;y<my;y++)
map[x][y]&=65535;
break; // al OK so stop
}
// for (i=0;i<n;i++) { s+=cnt[i]-siz[i]; s+=" "; }
// Main->Caption=s;
}
//---------------------------------------------------------------------------
代码没有经过优化以使其尽可能简单易懂......(可以重新编码以更快)。