2012-03-10 3 views
2

Я пытаюсь создать видео-игру «Марио», и, чтобы получить пересекающиеся объекты, наш учитель предоставил нам пример демонстрации, который позволяет объекту обнаруживать, если он касался ТОЧНО одного другого объекта, а первый объект что метод находит, возвращается. Я пытаюсь, вместо этого, возвращать массив каждого объекта, который текущий объект в данный момент касается. Я был способен возвращать массив всех объектов в настоящее время касаясь его, но теперь мне нужен простой/эффективный способ проверить, если массив содержит объект требуемого типа, например,Как вы запрашиваете массив, если он содержит конкретный класс?

if (array.Contains(Mario)) 
    { 
    //Do Work here 
    } 

массива, который является если он содержит (Марио), является возвращенным массивом пересекающихся спрайтов, но когда я спрашиваю, действительно ли он содержит объекты типа Mario, он говорит: «Ошибка 14« WindowsGame10.Mario »является« типом », но используется как «переменная». Я знаю, что могу сделать это с помощью цикла for, и спросить каждый отдельный индекс в массиве if (array[i].GetType() == typeof(Mario)), но за количество раз, которое мне нужно будет выполнить эту проверку внутри кода, и повторять один и тот же код снова и снова, я чувствую что мне нужно изучить более эффективный способ выполнения этого. Я нахожусь в своем первом году компьютерного программирования, и я работаю с C# XNA, и мне нужно иметь некоторое решение, которое я могу понять. Если есть лучший способ сделать это, пожалуйста, дайте мне знать.

+1

Вы всегда можете просто обернуть эту петлю в методе, избегая дублирования кода , – prelic

ответ

6

Вы можете использовать Linq в OfType() и Any() методы:

if (array.OfType<Mario>().Any()) 
{ 
+0

Спасибо. Это просто значительно уменьшило количество циклов, которыми я подвергался опасности. –

+3

Обратите внимание, что вы по-прежнему перемещаете массив до тех пор, пока не найдете первое совпадение или не пройдете весь массив, если нет совпадения. Linq - прекрасная абстракция, которая уменьшает усилия программирования, но на самом деле это может быть очень незначительно медленнее, чем кодирование цикла напрямую.Если у вас есть большое количество игровых объектов (тысячи или более), вы хотите оптимизировать структуру хранилища, чтобы лучше, чем поиск O (n). –

+0

@EricJ. Да, но без изменения механизма хранения, цикл по этому решению не принесет вам многого. Переход на словарь или отдельные коллекции по типу и т. Д. Потенциально может быть оптимизацией в зависимости от того, как и когда он будет использоваться. –

4

Использование Linq вы можете сделать:

var marios = array.OfType<Mario>(); 
if (marios.Any()) 
{ 
    //Stuff 
} 
1

Наиболее прямым способом (без использования LINQ) будет использовать is ключевое слово:

foreach (Object obj in array) 
{ 
    if (obj is Mario) 
    { 
     ... 
    } 
} 

Update: Если вам нужен точный Type матч, и хотите, чтобы избежать дублирования кода, я думаю, довольно упрощенно метод расширения похож на это было бы лучше -

public static bool ContainsType<T>(this T[] arr, Type type) 
{ 
    for (int i = 0; i < arr.Length; i++) 
     if (arr[i].GetType().Equals(type)) 
      return true; 
    return false; 
} 

А использование -

if (array.ContainsType(typeof(Mario))) 
+0

К моему пониманию (и я мог бы быть здесь), ключевое слово имеет дело с родительским отражением, и если я решим сделать делегатов марио в будущем, я могу не иметь возможности взаимодействовать с этим классом, тогда он также создаст взаимодействие с ними, потому что они наследуются от базового класса Марио, потому что «есть» работает с отражением. –

+0

@MatthewCrandall: оператор is [не использует Reflection и очень эффективен] (http://stackoverflow.com/a/1134104/284240). –

+0

@MatthewCrandall Ну, вы правы, что он также включает в себя наследующие типы, - но мне было непонятно, что это был нежелательный эффект. Во всяком случае, я обновил свой пост. Кроме того, я считаю, что вы неправильно относитесь к наследованию как к размышлению. – Acidic

2

если вам просто нужно знать, есть ли Марио то

if(array.Any(a=>a is Mario)) 
{ 
} 

это вырваться из iteratio n, как только он найдет первый матч.

+0

FYI - Мое решение не выполняет итерацию по всему массиву (обязательно), но разрывается, как только первый найден, из-за вызова Any(). –

+0

Хммм, не знал этого. Спасибо, Рид. – labroo

+1

Это связано с моделью отложенного исполнения LINQ. –

1

Ответы Linq замечательные. Просто чтобы обеспечить альтернативный подход, можно определить метод расширения, как это:

static public bool ContainsType(this Array array, Type type) 
{ 
    int len = array.Length; // Note that putting this in the loop is slightly slower 
          // because the compiler can't assume that a property value 
          // remains constant. 
    for (int i = 0; i < len; i++) 
    { 
     if (array.GetValue(i).GetType() == type) return true; 
    } 

    return false; 
} 

, который будет использоваться как это:

Array a = new object[] { "The meaning of life.", 42 }; 
    bool hasString = a.ContainsType(typeof(string)); // true 
    bool hasInteger = a.ContainsType(typeof(int)); // true 
    bool hasChar = a.ContainsType(typeof(char)); // false 
Смежные вопросы