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

时间:2023-01-11 21:34:25

For my own personal amusement, I'm writing what I hope will be the foundation of a game to come later. At current, I'm working on the game "board". Please consider the following:

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

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);
    }
}

And this:

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

I know this is so wrong it's probably not even funny, but this is the roughest of rough cuts.

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

I'm trying to get GetLocation to return the specific index of the Cube in which the Person is located. So that if the person is in Board.GameBoard[1, 2, 10] I'll be able to retrieve that location (probably as an int[] as listed above). However, at current, I'm unable to compile due to the following error:

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

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

I was pretty sure that LINQ should be able to query multi-dimensional arrays, but I haven't found any documentation on how to do it.

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

Any suggestions, or am I on the completly wrong track here?

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

3 个解决方案

#1


LINQ does not see multidimential arrays as you want it to because they do not implement IEnumerable<T> (although single index arrays do, which is what surprises people). There are several workarounds: you can avoid LINQ for searching the cube or you can write an extension method of your own that does the more traditional walks.

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

This is a case where I wouldn't use LINQ do to the search, but more than that I probably would keep some references to the various playing pieces in a simple structure (probably a dictionary) that is easier to update and manage. As an idea, your piece object would know where it is on the board itself and could update the cube as it moved by removing itself from one cell and adding itself to another.

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

It would be important to know if a single cell can contain more than one piece: if so, each cell would need to be a list of some type as well (it appears that way in your code). And once you get to this point, if there are vastly fewer playing pieces than cells, I probably would never actually create the "cube" itself as a datastructure. It would be drawn and the pieces displayed via some Z order drawing algorithm that pulled directly from the piece list, rather than an array. This would depend on the style of game though: if the pieces have attributes and are small in number this would work. If the game is more like 3D Go or similar, then your original cube would make sense... it really depends on how much "personality" (and thus data) your pieces have.

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

#2


Makes a lot more sense to me to move the int[] currentLocation declaration to the top level inside your Person class, and provide getter/setter methods. Then each Person stores its own location.

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

For the memory cost of 3 ints, you save yourself from having to query 1000 database entries every time you want to retrieve the person's location.

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

#3


I think the Person should tell the board where he is, not ask the board. In otherwords, I would create a Location3D class (x,y,z), use that in a GamePiece class that all other things on the board inherit from. That stores location, then each peice knows it's location.

我认为这个人应该告诉董事会他在哪里,而不是问董事会。换句话说,我会创建一个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));
  }
}

#1


LINQ does not see multidimential arrays as you want it to because they do not implement IEnumerable<T> (although single index arrays do, which is what surprises people). There are several workarounds: you can avoid LINQ for searching the cube or you can write an extension method of your own that does the more traditional walks.

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

This is a case where I wouldn't use LINQ do to the search, but more than that I probably would keep some references to the various playing pieces in a simple structure (probably a dictionary) that is easier to update and manage. As an idea, your piece object would know where it is on the board itself and could update the cube as it moved by removing itself from one cell and adding itself to another.

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

It would be important to know if a single cell can contain more than one piece: if so, each cell would need to be a list of some type as well (it appears that way in your code). And once you get to this point, if there are vastly fewer playing pieces than cells, I probably would never actually create the "cube" itself as a datastructure. It would be drawn and the pieces displayed via some Z order drawing algorithm that pulled directly from the piece list, rather than an array. This would depend on the style of game though: if the pieces have attributes and are small in number this would work. If the game is more like 3D Go or similar, then your original cube would make sense... it really depends on how much "personality" (and thus data) your pieces have.

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

#2


Makes a lot more sense to me to move the int[] currentLocation declaration to the top level inside your Person class, and provide getter/setter methods. Then each Person stores its own location.

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

For the memory cost of 3 ints, you save yourself from having to query 1000 database entries every time you want to retrieve the person's location.

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

#3


I think the Person should tell the board where he is, not ask the board. In otherwords, I would create a Location3D class (x,y,z), use that in a GamePiece class that all other things on the board inherit from. That stores location, then each peice knows it's location.

我认为这个人应该告诉董事会他在哪里,而不是问董事会。换句话说,我会创建一个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));
  }
}