我为所有代码道歉,但我很难描述我想要做什么。我正在为瓦片地图创建一个 2D 网格。瓷砖(块)被分解成一个 10x10 的方块,称为一个块,这些块形成 10x10 的方块以形成区域,一个 10x10 的方块形成一个世界。正方形的边尺寸是blockSize。
所有坐标都是[X,Y],0,0是左上角,都是从左到右再从上到下扫描。
从最大到最小:世界 -> 区域 -> 块 -> 块。
这张图片显示了一个 2x2 块大小的世界将如何布局:
“大”地址显示每个块的地址如果它位于单个巨型阵列中而不是分解为子单元时。
在这篇文章的最后,我给出了我已经工作的代码的悬崖笔记版本。我可以创建所有的结构。我设置了迭代器(参见最后的代码),以便每个级别只能迭代低于它的级别。我的代码可以执行以下操作:
// 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) {}
...
我想要的是让我的迭代器能够遍历我的数据的两个级别。例如,给定一个区域,扫描该区域中的所有块,并为我提供整个区域中所有块的列表。或者给定一个世界,得到世界上所有的块。或者是整个世界中所有方块的巨大列表。
...
// 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];
}
}
}