3

I am currently learning Object Orientated Programming in C#, and as such, am just playing around with classes trying to create a game.

In the game I am making currently, I have a Warrior class, that has a method, Attack(), that has two overloads, public void Attack(Warrior enemy) as well as public void Attack(params Warrior[] enemies).

Using the first overload is fine, I instantiate two Warrior objects in Program.cs, and use a while loop that continues until one of the warriors is dead, choosing who attacks at each time based on a random number generator.

Random random = new Random();

Warrior warrior1 = new Warrior("Ben", Faction.GoodGuy);
Warrior warrior2 = new Warrior("Alfie", Faction.BadGuy);

while (warrior1.IsAlive && warrior2.IsAlive)
{
    if (random.Next(9) < 5)
    {
        warrior1.Attack(warrior2);
    }
    else
    {
        warrior2.Attack(warrior1);
    }
}

However, my problem arises when I try to use the second overload, with mulitiple enemies.

I create four enemies, and start the while loop, as shown below.

Random random = new Random();
Warrior warrior1 = new Warrior("Ben", Faction.GoodGuy);
Warrior warrior2 = new Warrior("Alfie", Faction.BadGuy);
Warrior warrior3 = new Warrior("Joel", Faction.BadGuy);
Warrior warrior4 = new Warrior("Ruben", Faction.GoodGuy);

while(warrior1.IsAlive || warrior2.IsAlive || warrior3.IsAlive || warrior4.IsAlive)
{
    Warrior[] warriors = new Warrior[] { warrior1, warrior2, warrior3, warrior4 };

    switch (random.Next(4))
    {
        case 0:
            break;
        case 1:
            break;
        case 2:
            break;
        case 3:
            break;
        default:
            break;
    }
}

On each case, I want a warrior to attack every other warrior that is currently alive.

So on case 0: warrior 1 attacks all other alive warriors

on case 1: warrior 2 attacks all other warriors

on case 2: warrior 3 attacks all other warriors

on case 3: warrior 4 attacks all other warriors

I could quite easily do this with a foreach loop, but I was wondering, in the interest of cleaner code and writing less code, if there was a way to do this inline. I have seen people use the ? operator for this sort of thing, but I am not sure exactly how to use it, or if it even applies here.

I would appreciate it if you could help me with the inline operator, if there is indeed one.

Thanks, Ben

My code if you should need it:

Program.Cs

using System;

namespace Game
{
    class Program
    {
        static void Main(string[] args)
        {
            Random random = new Random();

            Warrior warrior1 = new Warrior("Ben", Faction.GoodGuy);
            Warrior warrior2 = new Warrior("Alfie", Faction.BadGuy);

            /*while (warrior1.IsAlive && warrior2.IsAlive)
            {
                if (random.Next(9) < 5)
                {
                    warrior1.Attack(warrior2);
                }
                else
                {
                    warrior2.Attack(warrior1);
                }
            }*/

            Warrior warrior3 = new Warrior("Joel", Faction.BadGuy);
            Warrior warrior4 = new Warrior("Ruben", Faction.GoodGuy);

            while(warrior1.IsAlive || warrior2.IsAlive || warrior3.IsAlive || warrior4.IsAlive)
            {
                Warrior[] warriors = new Warrior[] { warrior1, warrior2, warrior3, warrior4 };

                switch (random.Next(4))
                {
                    case 0:
                        break;
                    case 1:
                        break;
                    case 2:
                        break;
                    case 3:
                        break;
                    default:
                        break;
                }
            }

            Console.WriteLine("End of Code");
        }
    }
}

Warrior.cs

namespace Game
{
    class Warrior
    {
        private const double GOOD_GUY_HEALTH = 100;
        private const double BAD_GUY_HEALTH = 100;

        public double Health { get; set; }
        public bool IsAlive { get; set; } = true;

        private string name;
        private Faction faction;
        private Weapon weapon;
        private Armour armour;

        public Warrior(string name, Faction faction)
        {
            this.name = name;
            this.faction = faction;

            switch (faction)
            {
                case Faction.GoodGuy:
                    Health = GOOD_GUY_HEALTH;
                    weapon = new Weapon(faction);
                    armour = new Armour(faction);
                    break;
                case Faction.BadGuy:
                    Health = BAD_GUY_HEALTH;
                    weapon = new Weapon(faction);
                    armour = new Armour(faction);
                    break;
                default:
                    break;
            }
        }

        public void Attack(Warrior enemy)
        {
            System.Random random = new System.Random();
            double attackDamage = random.Next((int)System.Math.Ceiling(weapon.Damage)) - random.Next((int)System.Math.Ceiling(enemy.armour.ArmourPoints));

            if (attackDamage < 0)
            {
                attackDamage = 0;
            }

            enemy.Health -= attackDamage;

            if (enemy.Health <= 0)
            {
                enemy.Health = 0;
                enemy.IsAlive = false;
            }

            System.Console.WriteLine("{0} deals {1} damage. {2} is on {3} health", this.name, attackDamage, enemy.name, enemy.Health);

            if (enemy.IsAlive == false)
            {
                System.Console.WriteLine("{0} is dead, {1} is victorious!", enemy.name, this.name);
            }
        }

        public void Attack(params Warrior[] enemies)
        {
            System.Random random = new System.Random();
            double damageLeft = weapon.Damage;

            for (int i = 0; i < enemies.Length; i++)
            {
                if (damageLeft <= 0)
                {
                    return;
                }

                double damageBeforeShield = random.NextDouble() * System.Math.Ceiling(damageLeft / enemies.Length);
                double attackDamage = damageBeforeShield - (random.NextDouble() * enemies[i].armour.ArmourPoints);

                damageLeft -= attackDamage;

                if (enemies[i].Health < 0)
                {
                    enemies[i].Health = 0;
                    enemies[i].IsAlive = false;
                }

                System.Console.WriteLine("{0} deals {1} damage. {2} is on {3} helath", this.name, attackDamage, enemies[i].name, enemies[i].Health);

                if (enemies[i].IsAlive == false)
                {
                    System.Console.WriteLine("{0} is dead, {1} is victorious!", enemies[i].name, this.name);
                }




            }
        }

    }
}

Faction.cs

namespace Game
{
    enum Faction
    {
        GoodGuy, BadGuy
    }
}

Weapon.cs

namespace Game
{
    class Weapon
    {
        private double damage;

        public double Damage
        {
            get
            {
                return damage;
            }
        }

        public Weapon(Faction faction)
        {
            switch (faction)
            {
                case Faction.GoodGuy:
                    damage = 20;
                    break;
                case Faction.BadGuy:
                    damage = 20;
                    break;
                default:
                    break;
            }
        }

    }
}

Armour.cs

namespace Game
{
    class Armour
    {
        private readonly double armourPoints;

        public double ArmourPoints
        {
            get
            {
                return armourPoints;
            }
        }

        public Armour(Faction faction)
        {
            switch (faction)
            {
                case Faction.GoodGuy:
                    armourPoints = 20;
                    break;
                case Faction.BadGuy:
                    armourPoints = 20;
                    break;
                default:
                    break;
            }
        }
    }
}

1 Answer 1

3

Very nice application for studying purpose, you are doing great!

You can use RemoveAt method of List. I don't see a reason in switch there, so it will be quite simple:

while(warrior1.IsAlive || warrior2.IsAlive || warrior3.IsAlive || warrior4.IsAlive)
{
    var warriors = new List<Warrior> { warrior1, warrior2, warrior3, warrior4 };
    ProcessAttacks(warriors, random.Next(4));
}

And here is ProcessAttacks function:

private void ProcessAttacks(List<Warrior> warriors, int currentWarrior)
{
    var warrior = warriors[currentWarrior];
    warriors.RemoveAt(currentWarrior);
    warrior.Attack(warriors);
}

Also it will require changing signature of you public void Attack(params Warrior[] enemies) to public void Attack(List<Warrior> enemies)

Sign up to request clarification or add additional context in comments.

3 Comments

I guess only one thing is missing in ProcessAttacks(), after Attack() method we should I add currentWarrior again because he is still alive. Correct me if I am wrong here
if you mean adding warrior back to List then no, we don't need to do that because on the next loop cycle List is recreated again with all 4.
yeah, I did not notice it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.