0

I've searched a lot but can't find the answer that I understand enough to translate into my project. What is the goal: I need to find an item with the highest armor_class parameter on the list, and add that items' armor_class to character's armor class.

So, we have a list created this way:

public List<Weapon> characterInvWeapon;
public List<Armor> characterInvArmor;

etc.

Here's how class Armor and its properties are created:

public class Armor : Item, IComparable <Armor> {
  public string armor_prof;
  public string armor_category;
  public int armor_class;
  public int armor_str_req;
  public string armor_stealth_mod;

  public Armor (string c_name
      , string c_description
      , bool c_stackable
      , int c_value
      , string c_coin_type
      , int c_weight
      , string c_armor_prof
      , string c_armor_category
      , int c_armor_class
      , int c_armor_str_req   
      , string c_armor_stealth_mod) : base (c_name, c_description, c_stackable, c_value, c_coin_type, c_weight)
  {
      armor_prof = c_armor_prof;
      armor_category = c_armor_category;
      armor_class = c_armor_class;
      armor_str_req = c_armor_str_req;
      armor_stealth_mod = c_armor_stealth_mod;
  }

  public int CompareTo(Armor other)
  {
      if (armor_class == other.armor_class)
        return String.Compare (name, other.name); // a < ab < b 
      else
        return other.armor_class - armor_class;
  }
}

Armor is a class inheriting from class Item, which has the first 6 properties. Armors are stored in a list specific to Armor - public List<Armor> characterInvArmor;.

Example item:

AddToItemStore(new Armor("Breastplate", "Description.", false, 400, "gp", 20, "Breastplate", "Medium Armor", 14, 0, ""));

Adding script:

public void AddToCharacterInventory(Item it)
    {
        if (it is Weapon)
        {
            charInvWeapon.Add((Weapon)it);
            charInvWeapon.Sort();
        }
        else if (it is Armor)
        {
            charInvArmor.Add((Armor)it);
            charInvArmor.Sort();
        }
    }

Now as I mentioned, I need to find an item on the list charInvArmor with highest armor_class parameter and use its value in other function, which calculates armor class from many variables.

So in other function, characterArmorClass = armorWithHighestArmorClass + otherVariable + someotherVariable; etc.

I suspect there are some handy shortcuts in Linq, but I'd be most thankful for some example without Linq. Linq would be welcome too, but I'm absolutely new to it and also I'm worried about performance and my apps compatibility with iPhone, for example. I've read iOS can cause problems with Linq. This must be fast and compatible calculation.

A guy
  • 71
  • 11

2 Answers2

2

With LINQ:

int maxArmorClass = characterInvArmor.Max(armor => armor.armor_class);

Without LINQ with Sort:

var list = characterInvArmor.ToList(); // copy list, so we do not break sorted orded
list.Sort((armor1, armor2) => armor2.armor_class.CompareTo(armor1.armor_class));
int maxArmorClass = list[0].armor_class;

And of course you can always write a manual method with a cycle and "max" variable.

BTW, I noticed, that you sort charInvArmor in AddToCharacterInventory method. If array is always sorted, then, based on your CompareTo implementation, an item with maximum armor_class should always be last (or first, I'm not sure). So just take the last (first) element of your list.

just.ru
  • 648
  • 5
  • 12
  • Thank you, seems better than what I came up with. And yes, it's sorted here, but sometimes I add items without sorting them and was curious if there's some other way. And yes, maybe I don't want the list sorted that way later - I thought that sorting it each time and sorting again by other parameter would be costly with performance, and just too big operation for such "simple" task. So your solution with copying the list is a better idea already. – A guy Aug 13 '16 at 22:01
1

You have to loop through the list and check each value since the list is not sorted based on the armor class value and you do not want to use LINQ:

int maxArmorClass = 0;
foreach (var armor in characterInvArmor)
{
    // Do a comparison here and see if you found a higher value
    // If a higher value is found, store it in maxArmorClass
}

As a side note I recommend the following links:

Public Fields versus Automatic Properties

and

Style guide for c# * In C#, Pascal casing and camel casing are the established conventions.

Community
  • 1
  • 1
Jesse Good
  • 50,901
  • 14
  • 124
  • 166
  • Yes, that would be probably the best way. But how do I compare items if they are all "armor" in this case? ps. I'll read it, thanks, I'm really new to C# and coding so I make many mistakes at this point. – A guy Aug 13 '16 at 22:06
  • @Sarr: You cannot simply do `if (armor.armor_class > maxArmorClass)`? I'm not sure what you mean by `if they are all "armor"`. – Jesse Good Aug 13 '16 at 22:11
  • Oh darn, sorry, didn't think about obvious thing. Checking out. // And this is it, absolutely brillant and easiest solution for me. Thanks, it will help in many other areas. – A guy Aug 13 '16 at 22:30