两种类型的迭代器

时间:2012-11-26 15:11:37

标签: c# .net ienumerable ienumerator

我为所有代码道歉,但我很难描述我想要做的事情。我正在为瓷砖地图创建一个2D网格。瓷砖(块)被分解为称为块的10x10平方的瓷砖,块形成10x10的正方形以形成区域,10x10的正方形区域形成一个世界。方形边尺寸为blockSize。

所有坐标都是[X,Y],0,0是左上角,所有扫描都是从左到右,然后从上到下扫描。

从最大到最小:世界 - >地区 - >块 - >块。

此图显示了如何布置具有2x2 Blocksize的世界:

enter image description here

“大”地址显示了每个块的地址,如果它在一个巨大的阵列中,而不是分成子单元。

在这篇文章的最后,我给出了我已经工作的代码的悬崖笔记版本。我可以创建所有结构。我设置了迭代器(参见末尾的代码),这样每个级别只能迭代低于它的级别。我的代码可以执行以下操作:

// 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];
        }
    }
}

0 个答案:

没有答案