Выберите неизвестный элемент из многомерного массива с помощью LINQ - PullRequest
3 голосов
/ 17 июня 2009

Для собственного удовольствия я пишу то, что, надеюсь, станет основой игры, которая появится позже. На данный момент я работаю над игрой "доска". Пожалуйста, примите во внимание следующее:

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 ]

8 голосов
/ 17 июня 2009

LINQ не видит многомерные массивы так, как вы этого хотите, потому что они не реализуют IEnumerable<T> (хотя массивы с одним индексом делают, что удивляет людей). Есть несколько обходных путей: вы можете избежать LINQ для поиска в кубе или вы можете написать собственный метод расширения, который выполняет более традиционные прогулки.

Это тот случай, когда я бы не использовал LINQ do для поиска, но более того, я бы, вероятно, сохранил некоторые ссылки на различные игровые фрагменты в простой структуре (вероятно, в словаре), которую проще обновлять и управлять ею. , В качестве идеи ваш объект-кусочек будет знать где , он находится на самой доске и может обновлять куб по мере его перемещения, удаляя себя из одной ячейки и добавляя себя в другую.

Было бы важно знать, может ли одна ячейка содержать более одного куска: если это так, то каждая ячейка должна быть также списком некоторого типа (в вашем коде это выглядит именно так). И как только вы дойдете до этого момента, если игровых фигур будет значительно меньше, чем клеток, я, вероятно, никогда не создам сам «куб» в качестве структуры данных. Это будет нарисовано, и части будут отображаться с помощью некоторого алгоритма рисования Z-порядка, который извлекается непосредственно из списка частей, а не из массива. Это будет зависеть от стиля игры: если фигуры имеют атрибуты и их мало, это сработает. Если игра больше похожа на 3D Go или похожую, то ваш оригинальный кубик будет иметь смысл ... это действительно зависит от того, сколько "индивидуальности" (и, следовательно, данных) у ваших фигур.

0 голосов
/ 17 июня 2009

Я думаю, что Человек должен сообщить Правлению, где он находится, а не спрашивать Правление. Другими словами, я бы создал класс Location3D (x, y, z), используя его в классе GamePiece, от которого наследуются все остальные элементы на доске. Это хранит местоположение, тогда каждый кусочек знает, где он находится.

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));
  }
}
0 голосов
/ 17 июня 2009

Для меня гораздо разумнее переместить объявление int [] currentLocation на верхний уровень внутри вашего класса Person и предоставить методы getter / setter. Затем каждый человек сохраняет свое местоположение.

При стоимости памяти в 3 дюйма вы избавляетесь от необходимости запрашивать 1000 записей в базе данных каждый раз, когда хотите получить информацию о местонахождении человека.

...