More Fun With Classes (Hero & Monster Revision)

This is a revision of a previous blog posting of the Hero & Monster fight program. I decided to do some actual class seperation of the Character, Dice, and DisplayResult classes. I decided to also incorporate some private methods along with public methods in these classes that other parts of the program could use. I know that this program is really small in scale so you might be thinking why seperate things out? Well this will show the ability to use different classes based on the program function at any partcicular runtime. And how you can use public and private methods inside the classes to do work and generate results.

HeroMonsterV3SS

As you can see the results from the Default.aspx file are the same as the previous version. No changes there.

Default.aspx HTML Code File Contents

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="HeroMonster.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>

        <asp:Label ID="resultLabel" runat="server"></asp:Label>

    </div>
    </form>
</body>
</html>

Default.aspx Code File Contents

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Text;

namespace HeroMonster
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            //Defining the properties of our hero.
            Character hero = new Character();
            hero.Name = "Hero";
            hero.Health = 100;
            hero.DamageMaximum = 10;
            hero.AttackBonus = 2;

            //Defining the properties of our monster.
            Character monster = new Character();
            monster.Name = "Monster";
            monster.Health = 100;
            monster.DamageMaximum = 8;
            monster.AttackBonus = 1;

            // Creating an instance of Dice to use
            Dice dice = new Dice();

            // Quick text to display the start of the battle.
            resultLabel.Text += "<p><strong>The Battle Begins!!!</strong></p>";

            // Now let's fight the battle.
            performBattle(dice, hero, monster);
        }

        private void performBattle(Dice dice, Character hero, Character monster)
        {
            // While loop to run until someone runs out of health.
            while (hero.Health > 0 && monster.Health > 0)
            {
                // Getting the damage amount the hero and monster can inflict for this round.
                int heroDamage = hero.CharacterDamage(dice, hero);
                int monsterDamage = monster.CharacterDamage(dice, monster);

                // Adjusting the health of the hero and monster based on the damage amount.
                hero.Health = hero.Defend(monsterDamage);
                monster.Health = monster.Defend(heroDamage);

                //Displaying the health results of the characters.
                DisplayResults displayResults = new DisplayResults(hero, monster);
                resultLabel.Text += displayResults.PrintCharacterStats();
            }
        }
    }
}

Now as you can see from the Default.aspx code behind file there are a lot less lines of code than the previous version. My idea was to have this only take care of creating our Hero and Monster objects, setting their properties, creating a Dice object (more on this class later), and calling a private method to start the battle. Within that method was the battle going to take place, again, by calling other class methods to do work, and displaying the results of the round or who won the fight. Again this was me trying to keep my classes and methods as specific as possible and not having them do very much outside of what they are supposed to do. I’m also getting into the habit of passing my objects parameters around to the different methods and doing work on them.

Dice Class Code File Contents

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace HeroMonster
{
    public class Dice
    {
        // Dice Properties
        public int Sides { get; set; }

        // Random variable declaration to be used in rolling the dice
        Random random = new Random();

        // Dice methods.
        // Roll method used to roll the dice.
        public int Roll()
        {
            // This will return a random number based on the dice sides.
            return random.Next(1, this.Sides);
        }
    }
}

This Dice class is instantiated at the beginning of the program in the Default.aspx file. This class contains a Roll method that’s used to return a number similar to what you would do during a game of Dungeons and Dragons. The only diffference is the Sides property is based off the DamageMaximum property of the Character. Then the Roll method rolls the dice using Random based from 1 to the maximum number of sides. Simple class that can do a lot.

Character Class Code File Contents

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace HeroMonster
{
    public class Character
    {
        // Character Properties
        public string Name { get; set; }
        public int Health { get; set; }
        public int DamageMaximum { get; set; }
        public int AttackBonus { get; set; }

        // Random declaration to be used for the bonus attack.
        Random bonusAttack = new Random();

        // Method used for the character to attack.
        private int Attack(Dice dice)
        {
            dice.Sides = DamageMaximum;     // Setting the Sides property to the maximum amount of damage.
            int damageAmount = dice.Roll(); // Getting the damage amount based on a random number. 1 - damage max.
            return damageAmount;
        }

        // Method used for the character to defend.
        public int Defend(int damage)
        {
            // Getting a number for a percentage to decide if a surprise attack will happen.
            int surpriseAttack = bonusAttack.Next(0, 20);

            // Based on the percentage deciding if a surprised attack will happen.
            if (surpriseAttack > 15)
                return this.Health - (damage + AttackBonus);
            else
                return this.Health - damage;
        }

        // Method used to see how much damage the character can inflict for the given round.
        public int CharacterDamage(Dice dice, Character character)
        {
            // Variable to store the amount of damage the character can inflict.
            int damageAmount = character.Attack(dice);
            return damageAmount;
        }
    }
}

This class is where the action takes place. In the Default.aspx class the damage amount is set by calling on the CharacterDamage method while using the Dice and Character objects as parameters. This is done twice each time during the while loop, once for the hero, the other for the monster. The CharacterDamage then calculates the damage amount using the dice parameter to call on a private attack method. This is private because the rest of the program doesn’t really need to know what is going on behind the scenes. Just return me a number that I can use for a damage amount so I move on. Then the defend method comes into play so the characters health can be adjusted. I decided to add something extra in there in the form of the Random class for a bonus attack. Basically if that number was greater than 15 the characters bonus attack propery came into play giving them that extra hit to their opponent. Again the defend method is public while calling on the private attack method.

DisplayResult Class Code File Contents

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;

namespace HeroMonster
{
    public class DisplayResults
    {
        // Properties
        private Character Hero { get; set; }
        private Character Monster { get; set; }

        // Constructor
        public DisplayResults(Character hero, Character monster)
        {
            // Setting the properties from this constructor.
            this.Hero = hero;
            this.Monster = monster;
        }

        public string PrintCharacterStats()
        {            
            // Checking to see if anyone has won. If not then display stats and move to the next round.
            string result;
            if (Hero.Health <= 0)
                return result = displayHealth().ToString() + "</br>Monster Wins!!!";

            else if (Monster.Health <= 0)
                return result = displayHealth().ToString() + "</br>Hero Wins!!!";

            else if (Hero.Health <= 0 && Monster.Health <= 0)
                return result = displayHealth().ToString() + "</br>Hero And Monster Are Both Dead!!!";

            else
                return result = displayHealth().ToString();
        }

        // Method used to build the string in a certain format and return it.
        private StringBuilder displayHealth()
        {
            StringBuilder resultBuilder = new StringBuilder();
            return resultBuilder.Append(String.Format("Hero Health: {0} - Monster Health: {1}</br>",
                    Hero.Health, Monster.Health));
        }
    }
}

This DisplayResult class is self explanatory. I wanted a class to be able to return the strings I needed to display the characters health for each round and display the winner when one characters health went to zero. I’m doing this by creating my DisplayResult object and using the constructor method with the Character parameters. Then calling upon the public PrintCharacterStats method to do the work via a private displayHealth method that utilizes the StringBuilder class.

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s