我为所有代码道歉,但我很难描述我想要做的事情。我正在为瓷砖地图创建一个2D网格。瓷砖(块)被分解为称为块的10x10平方的瓷砖,块形成10x10的正方形以形成区域,10x10的正方形区域形成一个世界。方形边尺寸为blockSize。
所有坐标都是[X,Y],0,0是左上角,所有扫描都是从左到右,然后从上到下扫描。
从最大到最小:世界 - >地区 - >块 - >块。
此图显示了如何布置具有2x2 Blocksize的世界:
“大”地址显示了每个块的地址,如果它在一个巨大的阵列中,而不是分成子单元。
在这篇文章的最后,我给出了我已经工作的代码的悬崖笔记版本。我可以创建所有结构。我设置了迭代器(参见末尾的代码),这样每个级别只能迭代低于它的级别。我的代码可以执行以下操作:
// Create a world of 10x10 regions, each made up of 10x10 chunks, each made up of 10x10 tiles
World world = new World(blockSize);
// Address the upper left hand corner of the world. The first region's first chunk's first block.
Block block = World.Regions[0,0].Chunks[0,0].Blocks[0,0];
// Address a random chunk
Chunk chunk = World.Regions[1,2].Chunks[6,2];
// Iterate over the Block[,] grid of the given chunk from left to right, up to down
// This will give us every block in Region 1,2 Chunk 6,2
foreach (Block block in chunk) {}
// Address a random region
Region region = World.Regions[4,5];
// Iterate over the Chunk[,] grid of the given region from left to right, up to down
// This will give us every Chunk in Region 4,5
foreach (Chunk chunk in region) {}
// In World, iterate over the Region[,] grid from left to right, up to down
// This will give us every Region in the World
foreach (Region region in World.regions) {}
...
我想要的是我的迭代器能够遍历两个级别的数据。例如,给定一个Region,扫描该区域中的所有块,并为我提供整个块中所有块的列表。或者给予一个世界,获得世界上所有的大块。或者是整个世界所有街区的巨大清单。
...
// Given a region, return all chunks in that region
foreach (Chunk chunk in region) {}
// Given a region, return all blocks in all chunks in that region
foreach (Block block in region.GetAllBlocks)
{
// Scan the chunks from left to right.
// In each chunk, scan the blocks from left to right.
// Cover every block in the region.
}
// Given a world, return all the regions
Region regionArray = World.region; // For clarity
foreach (Region region in regionArray ) {}
// Given a world, return all the chunks in all the regions
Region regionArray = World.region; // For clarity
foreach (Chunk chunk in regionArray.GetAllChunks)
{
// Scan the regions from left to right, up to down.
// In each region, scan the chunks from left to right, up to down.
}
// Given a world, return all the blocks in all the chunks in all the regions
Region regionArray = World.region; // For clarity
foreach (Block block in regionArray.GetAllBlocks)
{
// Scan the regions from left to right, up to down.
// In each region, scan the chunks from left to right, up to down.
// In each chunk, scan the blocks from left to right, up to down.
}
...
如何编写迭代器代码,以便生成我想要的列表?这是我第一次使用迭代器完成任何复杂的操作,并且在弄清楚如何操作时遇到了很多麻烦。尝试这种事情是个好主意吗?这是有效/低效的吗?
以下是我的代码展示我工作内容的精简版本:
/* **************************************** */
class Block
{
int blockX, blockY; // Grid X/Y of this block in it's chunk
public Block(blockX, blockY)
{
this.blockX = blockX;
this.blockY = blockY;
}
} // Block Class
/* **************************************** */
class Chunk : IEnumerator, IENumerable
{
int chunkX, chunkY; // X/Y of the chunk in it's region
int blockSize;
int containsBlocks;
public Block[,] blocks;
int enumeratorIndex = -1;
public Chunk(int chunkX, int chunkY, int blockSize)
{
this.chunkX = chunkX;
this.chunkY = chunkY;
this.blockSize = blockSize;
this.containsBlocks = blockSize * blockSize;
blocks = new Block[blockSize, blockSize];
for (int x = 0; x < blockSize; ++x)
{
for (int y = 0; y < blockSize; ++y)
{
blocks[x, y] = new Block(x, y);
}
}
} // constructor
public IEnumerator GetEnumerator()
{
return (IEnumerator)this;
}
public bool MoveNext()
{
enumeratorIndex++;
return (enumeratorIndex < this.containsBlocks);
}
public void Reset() { enumeratorIndex = 0; }
public object Current
{
get
{
int y = enumeratorIndex / blockSize;
int x = enumeratorIndex % blockSize;
return blocks[x, y];
}
}
} // Chunk Class
/* **************************************** */
class Region : IEnumerator, IENumerable
{
int regionX, int regionY; // X/Y of region in the world
int blockSize;
int containsBlocks;
public Chunks[,] chunks;
int enumeratorIndex = -1;
...
Same kind of constructor to setup the Chunks[,] array, but this time the iterator is
...
public object Current
{
get
{
int y = enumeratorIndex / blockSize;
int x = enumeratorIndex % blockSize;
return Chunks[x, y];
}
}
} // Region Class
/* **************************************** */
class World : IEnumerator, IENumerable
{
public Region[,] regions; // There is only one world, here are it's regions
int blockSize;
...
etc
...
public object Current
{
get
{
int y = enumeratorIndex / blockSize;
int x = enumeratorIndex % blockSize;
return Region[x, y];
}
}
}