Click here to Skip to main content
15,903,817 members
Home / Discussions / C#
   

C#

 
GeneralRe: newbie using a game to learn c# and object-oriented programming Could I make an abstract factory to merge the other factories in a game? Pin
lmoelleb22-Dec-21 0:34
lmoelleb22-Dec-21 0:34 
GeneralRe: newbie using a game to learn c# and object-oriented programming Could I make an abstract factory to merge the other factories in a game? Pin
biull smith6-Jan-22 10:08
biull smith6-Jan-22 10:08 
AnswerRe: newbie using a game to learn c# and object-oriented programming Could I make an abstract factory to merge the other factories in a game? Pin
Gerry Schmitz21-Dec-21 6:30
mveGerry Schmitz21-Dec-21 6:30 
GeneralRe: newbie using a game to learn c# and object-oriented programming Could I make an abstract factory to merge the other factories in a game? Pin
biull smith21-Dec-21 7:01
biull smith21-Dec-21 7:01 
GeneralRe: newbie using a game to learn c# and object-oriented programming Could I make an abstract factory to merge the other factories in a game? Pin
Gerry Schmitz21-Dec-21 7:22
mveGerry Schmitz21-Dec-21 7:22 
GeneralRe: newbie using a game to learn c# and object-oriented programming Could I make an abstract factory to merge the other factories in a game? Pin
biull smith21-Dec-21 8:29
biull smith21-Dec-21 8:29 
GeneralRe: newbie using a game to learn c# and object-oriented programming Could I make an abstract factory to merge the other factories in a game? Pin
Gerry Schmitz21-Dec-21 10:04
mveGerry Schmitz21-Dec-21 10:04 
QuestionRe: newbie using a game to learn c# and object-oriented programming Could I make an abstract factory to merge the other factories in a game? Pin
biull smith21-Dec-21 13:15
biull smith21-Dec-21 13:15 
Would XML serialization be better for what I'm trying to do? Some of the factory classes will have a lot of subtypes in them, so wouldn't a factory or abstract factory be better? Let's say, for example. I took Itemfactory.cs, gameitem.cs, and Inventory.cs wouldn't those benefit from being a factory or even abstract factory?

itemfactory.cs

C#
   using System.Collections.Generic;
   using System.IO;
   using System.Linq;
   using System.Xml;
   using Engine.Actions;
   using Engine.Models;
   using Engine.Shared;
   using SOSCSRPG.Core;

   namespace Engine.Factories
  {
    public static class ItemFactory
    {
        private const string GAME_DATA_FILENAME = 
        ".\\GameData\\GameItems.xml";

        private static readonly List<GameItem> _standardGameItems = new 
        List<GameItem> 
        ();

        static ItemFactory()
        {
            if(File.Exists(GAME_DATA_FILENAME))
            {
                XmlDocument data = new XmlDocument();
                data.LoadXml(File.ReadAllText(GAME_DATA_FILENAME));

                LoadItemsFromNodes(data.SelectNodes("/GameItems/Weapons/Weapon"));
                
LoadItemsFromNodes(data.SelectNodes("/GameItems/HealingItems/HealingItem"));
                
LoadItemsFromNodes(data.SelectNodes("/GameItems/MiscellaneousItems/MiscellaneousItem"));
            }
            else
            {
                throw new FileNotFoundException($"Missing data file: 
                {GAME_DATA_FILENAME}");
            }
        }

        public static GameItem CreateGameItem(int itemTypeID)
        {
            return _standardGameItems.FirstOrDefault(item => 
            item.ItemTypeID == 
            itemTypeID)?.Clone();
        }

        private static void LoadItemsFromNodes(XmlNodeList nodes)
        {
            if(nodes == null)
            {
                return;
            }

            foreach(XmlNode node in nodes)
            {
                GameItem.ItemCategory itemCategory = 
                DetermineItemCategory(node.Name);
                
                GameItem gameItem =
                    new GameItem(itemCategory,
                                 node.AttributeAsInt("ID"),
                                 node.AttributeAsString("Name"),
                                 node.AttributeAsInt("Price"),
                                 itemCategory == 
                                 GameItem.ItemCategory.Weapon);

                if(itemCategory == GameItem.ItemCategory.Weapon)
                {
                    gameItem.Action =
                        new AttackWithWeapon(gameItem, 
                        node.AttributeAsString("DamageDice"));
                }
                else if(itemCategory == 
                GameItem.ItemCategory.Consumable)
                {
                    gameItem.Action =
                        new Heal(gameItem,
                                 
                        node.AttributeAsInt("HitPointsToHeal"));
                }

                _standardGameItems.Add(gameItem);
            }
        }

        private static GameItem.ItemCategory 
        DetermineItemCategory(string itemType)
        {
            switch(itemType)
            {
                case "Weapon":
                    return GameItem.ItemCategory.Weapon;
                case "HealingItem":
                    return GameItem.ItemCategory.Consumable;
                default:
                    return GameItem.ItemCategory.Miscellaneous;
            }
        }
    }
}


gameitem.cs

using Engine.Actions;
using Newtonsoft.Json;

namespace Engine.Models
{
    public class GameItem
    {
        public enum ItemCategory
        {
            Miscellaneous,
            Weapon,
            Consumable
        }

        [JsonIgnore]
        public ItemCategory Category { get; }
        public int ItemTypeID { get; }
        [JsonIgnore]
        public string Name { get; }
        [JsonIgnore]
        public int Price { get; }
        [JsonIgnore]
        public bool IsUnique { get; }
        [JsonIgnore]
        public IAction Action { get; set; }

        public GameItem(ItemCategory category, int itemTypeID, string name, int price,
                        bool isUnique = false, IAction action = null)
        {
            Category = category;
            ItemTypeID = itemTypeID;
            Name = name;
            Price = price;
            IsUnique = isUnique;
            Action = action;
        }

        public void PerformAction(LivingEntity actor, LivingEntity target)
        {
            Action?.Execute(actor, target);
        }

        public GameItem Clone()
        {
            return new GameItem(Category, ItemTypeID, Name, Price, IsUnique, Action);
        }
    }
}


Inventory.cs

using System.Collections.Generic;
using System.Linq;
using Engine.Shared;
using Newtonsoft.Json;

namespace Engine.Models
{
    public class Inventory
    {
        #region Backing variables

        private readonly List<GameItem> _backingInventory =
            new List<GameItem>();

        private readonly List<GroupedInventoryItem> _backingGroupedInventoryItems =
            new List<GroupedInventoryItem>();

        #endregion

        #region Properties

        public IReadOnlyList<GameItem> Items => _backingInventory.AsReadOnly();

        [JsonIgnore]
        public IReadOnlyList<GroupedInventoryItem> GroupedInventory =>
            _backingGroupedInventoryItems.AsReadOnly();

        [JsonIgnore]
        public IReadOnlyList<GameItem> Weapons =>
            _backingInventory.ItemsThatAre(GameItem.ItemCategory.Weapon).AsReadOnly();

        [JsonIgnore]
        public IReadOnlyList<GameItem> Consumables =>
            _backingInventory.ItemsThatAre(GameItem.ItemCategory.Consumable).AsReadOnly();

        [JsonIgnore]
        public bool HasConsumable => Consumables.Any();

        #endregion

        #region Constructors

        public Inventory(IEnumerable<GameItem> items = null)
        {
            if(items == null)
            {
                return;
            }

            foreach(GameItem item in items)
            {
                _backingInventory.Add(item);

                AddItemToGroupedInventory(item);
            }
        }

        #endregion

        #region Public functions

        public bool HasAllTheseItems(IEnumerable<ItemQuantity> items)
        {
            return items.All(item => Items.Count(i => i.ItemTypeID == item.ItemID) >= item.Quantity);
        }

        public Inventory AddItem(GameItem item)
        {
            return AddItems(new List<GameItem> { item });
        }

        public Inventory AddItems(IEnumerable<GameItem> items)
        {
            return new Inventory(Items.Concat(items));
        }

        public Inventory RemoveItem(GameItem item)
        {
            return RemoveItems(new List<GameItem> { item });
        }

        public Inventory RemoveItems(IEnumerable<GameItem> items)
        {
            // REFACTOR: Look for a cleaner solution, with fewer temporary variables.
            List<GameItem> workingInventory = Items.ToList();
            IEnumerable<GameItem> itemsToRemove = items.ToList();

            foreach (GameItem item in itemsToRemove)
            {
                workingInventory.Remove(item);
            }

            return new Inventory(workingInventory);
        }

        public Inventory RemoveItems(IEnumerable<ItemQuantity> itemQuantities)
        {
            // REFACTOR
            Inventory workingInventory = new Inventory(Items);

            foreach (ItemQuantity itemQuantity in itemQuantities)
            {
                for (int i = 0; i < itemQuantity.Quantity; i++)
                {
                    workingInventory =
                        workingInventory
                            .RemoveItem(workingInventory
                                .Items
                                .First(item => item.ItemTypeID == itemQuantity.ItemID));
                }
            }

            return workingInventory;
        }

        #endregion

        #region Private functions

        // REFACTOR: Look for a better way to do this (extension method?)
        private void AddItemToGroupedInventory(GameItem item)
        {
            if(item.IsUnique)
            {
                _backingGroupedInventoryItems.Add(new GroupedInventoryItem(item, 1));
            }
            else
            {
                if(_backingGroupedInventoryItems.All(gi => gi.Item.ItemTypeID != item.ItemTypeID))
                {
                    _backingGroupedInventoryItems.Add(new GroupedInventoryItem(item, 0));
                }

                _backingGroupedInventoryItems.First(gi => gi.Item.ItemTypeID == 
                 item.ItemTypeID).Quantity++;
            }
        }

        #endregion
    }
}


modified 21-Dec-21 19:30pm.

AnswerRe: newbie using a game to learn c# and object-oriented programming Could I make an abstract factory to merge the other factories in a game? Pin
Gerry Schmitz21-Dec-21 17:56
mveGerry Schmitz21-Dec-21 17:56 
GeneralRe: newbie using a game to learn c# and object-oriented programming Could I make an abstract factory to merge the other factories in a game? Pin
biull smith6-Jan-22 10:18
biull smith6-Jan-22 10:18 
QuestionTotal Newbie... just installing Visual Studio... Pin
Audio Babble17-Dec-21 6:08
Audio Babble17-Dec-21 6:08 
AnswerRe: Total Newbie... just installing Visual Studio... Pin
OriginalGriff17-Dec-21 6:12
mveOriginalGriff17-Dec-21 6:12 
GeneralRe: Total Newbie... just installing Visual Studio... Pin
Audio Babble17-Dec-21 6:24
Audio Babble17-Dec-21 6:24 
QuestionDisplaying data in a textBox Pin
Luis M. Rojas16-Dec-21 8:50
Luis M. Rojas16-Dec-21 8:50 
AnswerRe: Displaying data in a textBox Pin
trønderen16-Dec-21 9:10
trønderen16-Dec-21 9:10 
AnswerRe: Displaying data in a textBox Pin
OriginalGriff16-Dec-21 9:50
mveOriginalGriff16-Dec-21 9:50 
GeneralRe: Displaying data in a textBox Pin
Eddy Vluggen17-Dec-21 1:14
professionalEddy Vluggen17-Dec-21 1:14 
GeneralRe: Displaying data in a textBox Pin
OriginalGriff17-Dec-21 1:42
mveOriginalGriff17-Dec-21 1:42 
GeneralRe: Displaying data in a textBox Pin
Eddy Vluggen17-Dec-21 2:58
professionalEddy Vluggen17-Dec-21 2:58 
QuestionMonthCalendar - Adding a date without having the month or year. Pin
Richard A Knox16-Dec-21 3:06
Richard A Knox16-Dec-21 3:06 
AnswerRe: MonthCalendar - Adding a date without having the month or year. Pin
PIEBALDconsult16-Dec-21 3:07
mvePIEBALDconsult16-Dec-21 3:07 
AnswerRe: MonthCalendar - Adding a date without having the month or year. Pin
OriginalGriff16-Dec-21 4:09
mveOriginalGriff16-Dec-21 4:09 
AnswerRe: MonthCalendar - Adding a date without having the month or year. Pin
#realJSOP17-Dec-21 2:40
professional#realJSOP17-Dec-21 2:40 
Questionre-create a local database Pin
steven_noppe15-Dec-21 20:04
steven_noppe15-Dec-21 20:04 
AnswerRe: re-create a local database Pin
OriginalGriff15-Dec-21 20:54
mveOriginalGriff15-Dec-21 20:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.