使用LINQ从多维数组中选择未知项

时间:2009-06-17 19:16:25

标签: c# linq multidimensional-array

为了我自己的个人娱乐,我写的是我希望以后能够成为游戏的基础。目前,我正在制作游戏“棋盘”。请考虑以下事项:

class Board
{
    private Cube[,,] gameBoard;
    public Cube[, ,] GameBoard { get; }
    private Random rnd;
    private Person person;
    public Person _Person { get; }

    //default constructor
    public Board()
    {
        person = new Person(this);
        rnd = new Random();
        gameBoard = new Cube[10, 10, 10];
        gameBoard.Initialize();
        int xAxis = rnd.Next(11);
        int yAxis = rnd.Next(11);
        int zAxis = rnd.Next(11);

        gameBoard[xAxis, yAxis, zAxis].AddContents(person);
    }
}

而且:

class Person : IObject
{
    public Board GameBoard {get; set;}
    public int Size { get; set; }
    public void Move()
    {
        throw new NotImplementedException();
    }

    public void Move(Cube startLocation, Cube endLocation)
    {
        startLocation.RemoveContents(this);
        endLocation.AddContents(this);
    }

    public Person(Board gameBoard)
    {
        Size = 1;
        GameBoard = gameBoard;
    }

    public int[] GetLocation()
    {
        int[] currentLocation;
        var location =
            from cubes in GameBoard.GameBoard
            where cubes.GetContents.Contains(this)
            select cubes;
    }
}

我知道这是错的,它可能甚至不好笑,但这是最粗糙的削减。

我正在尝试让GetLocation返回Cube所在的Person的特定索引。因此,如果此人在Board.GameBoard[1, 2, 10],我将能够检索该位置(可能是上面列出的int[])。但是,目前,由于以下错误,我无法编译:

Could not find an implementation of the query pattern for source type 'Cubes.Cube[*,*,*]'. 'Where' not found.'

我非常确定LINQ应该能够查询多维数组,但我还没有找到任何关于如何执行此操作的文档。

有任何建议,还是我在完全错误的轨道上?

3 个答案:

答案 0 :(得分:8)

LINQ没有像你想要的那样看到多维数组,因为它们没有实现IEnumerable<T>(虽然单个索引数组会这样做,这让人感到惊讶)。有几种解决方法:您可以避免使用LINQ搜索多维数据集,或者您可以编写自己的扩展方法来执行更传统的步骤。

这是一个我不会使用LINQ做搜索的情况,但更多的是我可能会在一个简单的结构(可能是字典)中保留一些更容易更新和管理的各种游戏片段的引用。作为一个想法,你的棋子对象会知道它在棋盘上的 where ,并且可以通过从一个单元格中移除自身并将自己添加到另一个单元格来更新多维数据集。

知道单个单元格是否可以包含多个单元格非常重要:如果是这样,每个单元格也需要是某种类型的列表(在代码中会出现这种情况)。一旦你达到这一点,如果游戏块比单元格少得多,我可能永远不会真正创建“立方体”本身作为数据结构。它将被绘制,并通过直接从片段列表而不是数组拉出的一些Z阶绘制算法显示这些片段。这取决于游戏的风格:如果棋子具有属性并且数量很少,这将起作用。如果游戏更像3D Go或类似游戏,那么你的原始立方体就会有意义......这实际上取决于你的作品有多少“个性”(以及数据)。

答案 1 :(得分:0)

让我更有意义的是将int [] currentLocation声明移动到Person类中的顶层,并提供getter / setter方法。然后每个人都存储自己的位置。

对于3个整数的内存成本,每次要检索此人的位置时,您不必查询1000个数据库条目。

答案 2 :(得分:0)

我认为该人应该告诉董事会他在哪里,而不是问董事会。换句话说,我会创建一个Location3D类(x,y,z),在GamePiece类中使用它,该板上的所有其他东西都继承自。存储位置,然后每个peice都知道它的位置。

public class Location3D
{
  public Location3D(int x, int y, int z) { X = x; Y = y; Z = z; }
  public int X { get; set; }
  public int Y { get; set; }
  public int Z { get; set; }
}

public abstract GamePiece
{
  public Location3d { get; set; }

public class Person: GamePiece // inherit GamePiece
{
  // everything else about Person
}

public class Board
{
  public Board()
  {
    person = new Person(this);
    rnd = new Random();
    gameBoard = new Cube[10, 10, 10];
    gameBoard.Initialize();
    int xAxis = rnd.Next(11);
    int yAxis = rnd.Next(11);
    int zAxis = rnd.Next(11);

    var location = new Location3D(xAxis, yAxis, zAxis);
    person.Location = location;

    GetCubeAt(location).AddContents(person);
  }

  public Cube GetCubeAt(Location3D location)
  {
    return gameBoard[location.X, location.Y, location.Z];
  }

  public Cube GetCubeAt(int x, int y, int z)
  {
    return GetCubeAt(new Location3D(x,y,z));
  }
}