Zacharias Hortén
Zacharias Hortén

Reputation: 179

Find class in LinkedList

I am making this 2-D game where I want to be able to build structures. The player must be able to benefit from certain structures. Today the game looks like this:

enter image description here (the blue dot is the player, other dots are ais)

I have made a class named Structure and three other classes that inherits from Structure. These classes are more or less empty. The tiles of the game has there own class named Tile. In this class I have written some things but the code of interest is this:

public LinkedList<Structure> Structures = new LinkedList<Structure>();

When i build a structure (a fireplace for example) the code looks like this:

Bundle.map.tile[Bundle.player.X, Bundle.player.Y].Structures.
    AddFirst(new Fireplace());

The part I´m uncertain about is how I check if the list contain a fireplace for example (which is a class named Fireplace) or any other building. For example if a player finds a fireplace on a tile he/she will regain warmth. This does not work. Perhaps I have the wrong approach to all this, in either case please provide me with an code example.

Conclusion of answer:

bool anyFireplace = Bundle.map.tile[Bundle.player.X, Bundle.player.Y].Structures.OfType<Fireplace>().Any();
if (anyFireplace)
{
    Warmth = MaxWarmth;
}
else
{
if (Warmth > 0)
{
    Warmth--;
}
else
{
    HP--;
}
}

Upvotes: 2

Views: 690

Answers (5)

Tommaso Belluzzo
Tommaso Belluzzo

Reputation: 23685

You could use, for example, Enumerable.OfType<TResult>() and Enumerable.Any(TSource) as follows:

LinkedList<Structure> structures = new LinkedList<Structure>();

// Add Different Types of Structures

Boolean anyFireplace = structures.OfType<Fireplace>().Any();

Just make sure you have:

using System.Linq;

in your using directives at the top of your source and a reference to the System.Core assembly module. You could also use Count() method if you need to know the exact number of fireplaces inside the LinkedList, otherwise Any() is more efficient in Linq objects.

Upvotes: 2

antonijn
antonijn

Reputation: 5760

I would suggest using the is keyword. It is used to check whether a variable has a certain type. For example:

object example = "Hello World!";
bool isString = example is string; // Evaluates to true

And you could use that in your code as such:

foreach (Structure s in Structures)
{
    if (s is FirePlace)
    {
        // Warmup the player
    }
}

Also, I would suggest using List<T> instead of LinkedList<T>, since List<T> is (generally) much faster.

As you might have gathered from some of the other answers, multiple ways lead to Rome here, many ways. However, according to this test, the is way of doing it outperforms all other suggested ways (thanks to Hogan btw for this test):

OfType time: .6702958, GetType time: .2268946, Property time: .1400208, Is time: .1112995

And this way is cleaner IMHO.

Upvotes: 2

Hogan
Hogan

Reputation: 70523

Maybe having the class name describe the object is not advisable. You will have to use reflection which is kinda slow. AND you only get one description (the class name). You will want more than just one. You might want to consider a base object like this:

public abstract class MapObject
{
   public int x,y;  // object location
   public string myclass;  // object class
   public string mytype;   // object type
   // etc

   // constructor
   public MapObject(string myclass, string mytype);

}

Then the a fireplace might look like this

public class FirePlace : MapObject
{
   public FirePlace() 
       : base("Builtin furniture", "Fireplace") { }
   // etc
}

Now you can loop over all MapObjects for ones of mytype = "Fireplace"

Upvotes: 0

Nick Butler
Nick Butler

Reputation: 24383

You can use LINQ to Objects for this:

LinkedList<Structure> list = ...

List<Fireplace> fireplaces = list.OfType<Fireplace>().ToList();

fireplaces is then a list of all the elements in the list of type Fireplace - or an empty list if none exist.

If you just want to know if one exists or not, you can adapt this to:

bool hasFirplace = list.OfType<Fireplace>().Any();

Upvotes: 1

DVD
DVD

Reputation: 1784

You can use the Type to know that:

foreach(var s in Structures)
{
  var type = s.GetType();
  if(type == typeof(FirePlace)
  {
    (your code here)
  }
}

For a single method

public bool HasType<T>(IEnumerable<T> list, Type t)
{
    return list.Any(e=>e.GetType() == t);
}

The usage should be like:

if(HasType(Structures,typeof(FirePlace))
{
  (code here)
}

At last you can turn this into an extension method, but I leave that option to you ;)

Upvotes: -1

Related Questions