8
\$\begingroup\$

As a student of C# right now, I am trying my best to get a grasp on many of the systems being taught. I just completed Week 1 of a C# 102 class and the class was assigned a bit of homework. I am curious, from a beginners point of view, how you might restructure this code to make it more readable and understandable.

For context, here is a word for word description of what the homework was supposed to be.

Create an abstract Pet class that has abstract functionality (at least 3 methods). It must have a "string Name" read-only (he didnt mean readonly keyword) that is filled by a parameter to the constructor. At least one of the methods must take in parameters, and at least one of the methods must return a value instead of printing things to the console.

Create four implementations of the Pet class that all appropriately implement the different methods.

Allow the user to enter 0 to many pets (can be any type) and store them into a List object

After the user is done entering in pets allow the user to:

A: select a pet

B: perform an operation

C: allow the user to repeat everything

Thanks for your time. And if you do find yourself answering, please keep in mind, we have not gone over Interfaces yet. That is the next class. The things we learned in this class had mostly to do with virtual, override, abstract members and classes.

using System;
using System.Collections.Generic;

namespace Pet_Application
{
    public enum PetMood
    {
        Furious,
        Upset,
        Bored,
        Content,
        Happy
    };

    public enum HungerLevel
    {
        Starving,
        Hungry,
        Content,
        Full
    }

    public abstract class Pet
    {
        public string Name { get; private set; }
        public string Breed { get; private set; }

        //Happiness relates to playing with the pet
        public PetMood Mood { get; private set; }      

        //Pet hunger level
        public HungerLevel Hunger { get; private set; }

        //Has the pet been vaccinated
        public bool IsVaccinated { get; private set; }

        //The pet class constructor
        public Pet(string name, string breed, PetMood mood, HungerLevel hunger, bool isVaccinated)
        {
            Name = name;
            Breed = breed;
            Mood = mood;
            Hunger = hunger;
            IsVaccinated = isVaccinated;
        }

        public void GivePetShot()
        {
            IsVaccinated = true;
        }

        public abstract PetMood PlayWithPet();

        public abstract PetMood PunishPet();

        public abstract HungerLevel FeedPet();

        public abstract HungerLevel StarvePet();

        public void UpdatePet(HungerLevel hunger)
        {
            if (hunger != Hunger)
            {
                Hunger = hunger;
            }
        }

        public void UpdatePet(PetMood mood)
        {
            if (mood != Mood)
            {
                Mood = mood;
            }
        }

        public void DisplayPetInformation()
        {
            Console.WriteLine("\n\nName: {0}\n" +
                              "Breed: {1}\n" +
                              "Mood: {2}\n" +
                              "Hunger Status: {3}\n" +
                              "Is Pet Vaccinated: {4}\n", 
                              Name, Breed, Mood, Hunger, IsVaccinated);
        }
    }

    public class Cat : Pet
    {
        private string _name;
        private string _breed;
        private PetMood _mood;
        private HungerLevel _hunger;
        private bool _isVaccinated;

        public Cat(string name, string breed, PetMood mood, HungerLevel hunger, bool isVaccinated) : 
            base(name, breed, mood, hunger, isVaccinated)
        {
            _name = name;
            _breed = breed;
            _mood = mood;
            _hunger = hunger;
            _isVaccinated = isVaccinated;
        }



        public override PetMood PlayWithPet()
        {
            if ((int)_mood < 4)
            {
                Console.WriteLine("You gave the cat a ball!");
                return _mood += 1;
            }
            Console.WriteLine("You gave the cat a ball!");
            return _mood;
        }

        public override PetMood PunishPet()
        {
            if ((int)_mood > 0)
            {
                Console.WriteLine("You slapped that kitty!");
                return _mood -= 1;
            }
            Console.WriteLine("You slapped that kitty!");
            return _mood;
        }

        public override HungerLevel FeedPet()
        {
            if ((int)_hunger < 3)
            {
                Console.WriteLine("You fed the cat!");
                _hunger += 1;
                return _hunger;
            }

            Console.WriteLine("You failed to feed the cat!");
            return _hunger;
        }

        public override HungerLevel StarvePet()
        {
            if ((int)_hunger > 0)
            {
                Console.WriteLine("You starved the cat!");
                _hunger -= 1;
                return _hunger;
            }

            Console.WriteLine("You starved the cat!");
            return _hunger;
        }
    }

    public class Dog : Pet
    {
        private string _name;
        private string _breed;
        private PetMood _mood;
        private HungerLevel _hunger;
        private bool _isVaccinated;

        public Dog(string name, string breed, PetMood mood, HungerLevel hunger, bool isVaccinated) :
            base(name, breed, mood, hunger, isVaccinated)
        {
            _name = name;
            _breed = breed;
            _mood = mood;
            _hunger = hunger;
            _isVaccinated = isVaccinated;
        }

        public override PetMood PlayWithPet()
        {
            if ((int)_mood < 4)
            {
                Console.WriteLine("You threw a frisby!");
                return _mood += 1;
            }
            return _mood;
        }

        public override PetMood PunishPet()
        {
            if ((int)_mood > 0)
            {
                Console.WriteLine("You scolded to dog!");
                return _mood -= 1;
            }
            return _mood;
        }

        public override HungerLevel FeedPet()
        {
            if ((int)_hunger < 3)
            {
                Console.WriteLine("You fed the dog!");
                _hunger += 1;
                return _hunger;
            }

            Console.WriteLine("You failed to feed the dog!");
            return _hunger;
        }

        public override HungerLevel StarvePet()
        {
            if ((int)_hunger > 0)
            {
                Console.WriteLine("You starved the dog!");
                _hunger -= 1;
                return _hunger;
            }

            Console.WriteLine("You starved the dog!");
            return _hunger;
        }
    }

    public class Shark : Pet
    {
        private string _name;
        private string _breed;
        private PetMood _mood;
        private HungerLevel _hunger;
        private bool _isVaccinated;

        public Shark(string name, string breed, PetMood mood, HungerLevel hunger, bool isVaccinated) :
            base(name, breed, mood, hunger, isVaccinated)
        {
            _name = name;
            _breed = breed;
            _mood = mood;
            _hunger = hunger;
            _isVaccinated = isVaccinated;
        }

        public override PetMood PlayWithPet()
        {
            if ((int)_mood < 4)
            {
                Console.WriteLine("You swam with! {0}", _name);
                return _mood += 1;
            }
            return _mood;
        }

        public override PetMood PunishPet()
        {
            if ((int)_mood > 0)
            {
                Console.WriteLine("You hit your shark on the nose!");
                return _mood -= 1;
            }
            return _mood;
        }

        public override HungerLevel FeedPet()
        {
            if ((int)_hunger < 3)
            {
                Console.WriteLine("You fed the shark!");
                _hunger += 1;
                return _hunger;
            }

            Console.WriteLine("You failed to feed the shark!");
            return _hunger;
        }

        public override HungerLevel StarvePet()
        {
            if ((int)_hunger > 0)
            {
                Console.WriteLine("You starved the shark!");
                _hunger -= 1;
                return _hunger;
            }

            Console.WriteLine("You starved the shark!");
            return _hunger;
        }
    }

    public class Bird : Pet
    {
        private string _name;
        private string _breed;
        private PetMood _mood;
        private HungerLevel _hunger;
        private bool _isVaccinated;

        public Bird(string name, string breed, PetMood mood, HungerLevel hunger, bool isVaccinated) :
            base(name, breed, mood, hunger, isVaccinated)
        {
            _name = name;
            _breed = breed;
            _mood = mood;
            _hunger = hunger;
            _isVaccinated = isVaccinated;
        }

        public override PetMood PlayWithPet()
        {
            if ((int)_mood < 4)
            {
                Console.WriteLine("You petted the bird!");
                return _mood += 1;
            }
            return _mood;
        }

        public override PetMood PunishPet()
        {
            if ((int)_mood > 0)
            {
                Console.WriteLine("You clipped the birds wings!");
                return _mood -= 1;
            }
            return _mood;
        }

        public override HungerLevel FeedPet()
        {
            if ((int)_hunger < 3)
            {
                Console.WriteLine("You fed the bird!");
                _hunger += 1;
                return _hunger;
            }

            Console.WriteLine("You failed to feed the bird!");
            return _hunger;
        }

        public override HungerLevel StarvePet()
        {
            if ((int)_hunger > 0)
            {
                Console.WriteLine("You starved the bird!");
                _hunger -= 1;
                return _hunger;
            }

            Console.WriteLine("You starved the bird!");
            return _hunger;
        }
    }

    public class PetDataHandler
    {
        private List<Pet> pets = new List<Pet>();

        public void AddPet(Pet pet)
        {
            pets.Add(pet);
        }

        public void RemovePet(int i)
        {
            pets.RemoveAt(i);
        }

        public int PetCount()
        {
            return pets.Count;
        }

        public void Feed(int index)
        {
            pets[index].UpdatePet(pets[index].FeedPet());
        }

        public void Starve(int index)
        {
            pets[index].UpdatePet(pets[index].StarvePet());
        }

        public void PlayWith(int index)
        {
            pets[index].UpdatePet(pets[index].PlayWithPet());
        }

        public void Punish(int index)
        {
            pets[index].UpdatePet(pets[index].PunishPet());
        }

        public void GiveShot(int index)
        {
            pets[index].GivePetShot();
        }

        public void ShowData(int index)
        {
            pets[index].DisplayPetInformation();
        }

        //Creates an indexer for the pets list
        public string this[int i]
        {
            get { return pets[i].Name; }
        }
    }

    public class Menu
    {
        Input input = new Input();
        PetDataHandler petList = new PetDataHandler();

        public void DisplayMainMenu()
        {
            DisplayTitle();
            Console.WriteLine("[1] Add a pet\n" +
                              "[2] Remove a pet\n" +
                              "[3] Inspect a pet\n" +
                              "[4] Quit application\n");

            MenuChoice(input.GetChoice("Enter choice"));
        }

        public void DisplayPetTypeMenu()
        {
            DisplayTitle();
            Console.WriteLine("[1] Cat\n" +
                              "[2] Dog\n" +
                              "[3] Shark\n" +
                              "[4] Bird\n" +
                              "[5] Exit\n");

            PetTypeChoice(input.GetChoice("Enter choice"));
        }

        public void DisplayPetActionMenu(int petIndex)
        {
            Console.WriteLine("[1] Feed Pet\n" +
                              "[2] Starve Pet\n" +
                              "[3] Play With Pet\n" +
                              "[4] Punish Pet\n" +
                              "[5] Vaccinate Pet\n" +
                              "[6] Main Menu");

            PetActionChoice(input.GetChoice("Enter choice"), petIndex);
        }

        public void DisplayPetRemovalMenu()
        {
            DisplayTitle();
            for (int i = 0; i < petList.PetCount(); i++)
            {
                Console.WriteLine("[{0}]{1}", (i + 1), petList[i]);
            }

            int choice = input.GetChoice("Enter choice");

            if (choice > 0 && choice <= petList.PetCount())
            {
                petList.RemovePet(choice - 1);
            }

            DisplayMainMenu();
        }

        public void DisplayPetInspectionMenu()
        {
            DisplayTitle();
            for (int i = 0; i < petList.PetCount(); i++)
            {
                Console.WriteLine("[{0}]{1}", (i + 1), petList[i]);
            }

            int choice = input.GetChoice("Enter number for pet");

            if (choice > 0 && choice <= petList.PetCount())
            {
                petList.ShowData(choice - 1);
            }

            DisplayPetActionMenu(choice - 1);

            Console.ReadKey(true);

            DisplayMainMenu();
        }

        private void DisplayTitle()
        {
            Console.Clear();
            Console.WriteLine("=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n" +
                              "           Pet Application 1.0\n" +
                              "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-");
        }

        public void MenuChoice(int choice)
        {
            switch (choice)
            {
                case 1:
                    DisplayPetTypeMenu();
                    PetTypeChoice(input.GetChoice("Enter choice"));
                    break;

                case 2:
                    DisplayPetRemovalMenu();
                    break;

                case 3:
                    DisplayPetInspectionMenu();
                    break;

                case 4:
                    Environment.Exit(0);
                    break;

                default:
                    Console.Write("\n\nNot a valid selection. Press any key to return");
                    Console.ReadKey(true);
                    DisplayMainMenu();
                    break;
            }
        }

        public void PetTypeChoice(int choice)
        {
            switch (choice)
            {
                case 1:
                    petList.AddPet(new Cat(input.GetString("\n\nName"), input.GetString("Breed"), PetMood.Content, HungerLevel.Content, false));
                    DisplayMainMenu();
                    break;

                case 2:
                    petList.AddPet(new Dog(input.GetString("\n\nName"), input.GetString("Breed"), PetMood.Content, HungerLevel.Content, false));
                    DisplayMainMenu();
                    break;

                case 3:
                    petList.AddPet(new Shark(input.GetString("\n\nName"), input.GetString("Breed"), PetMood.Content, HungerLevel.Content, false));
                    DisplayMainMenu();
                    break;

                case 4:
                    petList.AddPet(new Bird(input.GetString("\n\nName"), input.GetString("Breed"), PetMood.Content, HungerLevel.Content, false));
                    DisplayMainMenu();
                    break;

                case 5:
                    DisplayMainMenu();
                    break;

                default:
                    Console.Write("\n\nNot a valid selection. Press any key to return>");
                    Console.ReadKey(true);
                    DisplayPetTypeMenu();
                    break;
            }
        }

        public void PetActionChoice(int choice, int petIndex)
        {
            switch (choice)
            {
                case 1:
                    petList.Feed(petIndex);
                    DisplayPetInspectionMenu();
                    break;

                case 2:
                    petList.Starve(petIndex);
                    DisplayPetInspectionMenu();
                    break;

                case 3:
                    petList.PlayWith(petIndex);
                    DisplayPetInspectionMenu();
                    break;

                case 4:
                    petList.Punish(petIndex);
                    DisplayPetInspectionMenu();
                    break;

                case 5:
                    petList.GiveShot(petIndex);
                    DisplayPetInspectionMenu();
                    break;

                case 6:
                    DisplayMainMenu();
                    break;

                default:
                    Console.Write("\n\nNot a valid selection. Press any key to return>");
                    Console.ReadKey(true);
                    DisplayPetTypeMenu();
                    break;
            }
        }
    }

    public class Input
    {
        public string GetString(string prompt)
        {
            Console.Write("{0}> ", prompt);
            return Console.ReadLine();
        }

        public int GetInt(string prompt)
        {
            Console.Write("{0}> ", prompt);
            return int.Parse(Console.ReadLine());
        }

        public int GetChoice(string prompt)
        {
            Console.Write("{0}> ", prompt);
            return int.Parse(Console.ReadKey().KeyChar.ToString());
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Menu menu = new Menu();

            menu.DisplayMainMenu();
        }
    }
}
\$\endgroup\$
0

5 Answers 5

6
\$\begingroup\$
  1. Remove fields which we already have as properties in base class.
  2. Change everything to use base properties
  3. Change setter scope of base properties to protected

Let's start with PlayWithPet. This is doing the same thing in all subclasses except displaying a different message for each one of them.

Let's move this code into Base and implement a method GetPlayWithPetMessage in all child classes which will return that different message.

Change PlayWithPet from abstract to virtual and add a new abstract method instead which is GetPlayWithPetMessage and then PlayWithPet will call this new method.

Now do the same thing for PunishPet which is to change it to a virtual method and a new abstract method GetPunishPetMessage, and so on for FeedPet and StarvePet.

Have a look at the modified source code. For you info, this code still has some duplication which can be removed by using C# lambda Actions or interfaces but probably too early for you. After writing few lines of code, always try to refactory (basically you should refactor after passing your test but I guess its again too early for you). And the primary factor when doing refactoring is to look for duplication in your code and try to remove it. BTW I only looked into Pet and subclasses but I am pretty sure others classes functionality can be moved into base pet classes as well and then each sub class display its own information.

using System;
using System.Collections.Generic;

namespace Pet_Application
{
    public enum PetMood
    {
        Furious,
        Upset,
        Bored,
        Content,
        Happy
    };

    public enum HungerLevel
    {
        Starving,
        Hungry,
        Content,
        Full
    }

    public abstract class Pet
    {
        public Pet( string name, string breed, PetMood mood, HungerLevel hunger, bool isVaccinated )
        {
            Name = name;
            Breed = breed;
            Mood = mood;
            Hunger = hunger;
            IsVaccinated = isVaccinated;
        }

        public string Name { get; private set; }
        public string Breed { get; private set; }

        //Happiness relates to playing with the pet
        public PetMood Mood { get; protected set; }

        //Pet hunger level
        public HungerLevel Hunger { get; protected set; }

        //Has the pet been vaccinated
        public bool IsVaccinated { get; private set; }

        //The pet class constructor

        public void GivePetShot()
        {
            IsVaccinated = true;
        }

        public virtual PetMood PlayWithPet()
        {
            var message = GetPlayWithPetMessage();
            if ( (int)this.Mood < 4 )
            {
                Console.WriteLine( message );
                return this.Mood += 1;
            }
            Console.WriteLine( message );
            return this.Mood;            
        }

        public abstract string GetPlayWithPetMessage();


        public virtual PetMood PunishPet()
        {
            string message = GetPunishPetMessage();
            if ( (int) this.Mood > 0 )
            {
                Console.WriteLine( message );
                return this.Mood -= 1;
            }
            Console.WriteLine( message );
            return this.Mood;            
        }

        public abstract string GetPunishPetMessage();

        public virtual HungerLevel FeedPet()
        {
            if ( (int)this.Hunger < 3 )
            {
                Console.WriteLine( GetFeedPetSuccessMessage() );
                this.Hunger += 1;
                return this.Hunger;
            }

            Console.WriteLine( GetFeedPetFailedMessage() );
            return this.Hunger;            
        }

        public abstract string GetFeedPetSuccessMessage();
        public abstract string GetFeedPetFailedMessage();


        public HungerLevel StarvePet()
        {
            string message = GetStarvePetMessage();
            if ( (int)this.Hunger > 0 )
            {
                Console.WriteLine( message );
                this.Hunger -= 1;
                return this.Hunger;
            }

            Console.WriteLine( message );
            return this.Hunger;            
        }
        public abstract string GetStarvePetMessage();

        public void UpdatePet( HungerLevel hunger )
        {
            if ( hunger != Hunger )
            {
                Hunger = hunger;
            }
        }

        public void UpdatePet( PetMood mood )
        {
            if ( mood != Mood )
            {
                Mood = mood;
            }
        }

        public void DisplayPetInformation()
        {
            Console.WriteLine( "\n\nName: {0}\n" +
                                "Breed: {1}\n" +
                                "Mood: {2}\n" +
                                "Hunger Status: {3}\n" +
                                "Is Pet Vaccinated: {4}\n",
                                Name, Breed, Mood, Hunger, IsVaccinated );
        }
    }

    public class Cat : Pet
    {
        public Cat( string name, string breed, PetMood mood, HungerLevel hunger, bool isVaccinated ) :
            base( name, breed, mood, hunger, isVaccinated )
        {
        }


        public override string GetPlayWithPetMessage()
        {
            const string result = @"You gave the cat a ball!";
            return result;
        }

        public override string GetPunishPetMessage()
        {
            return "You slapped that kitty!";
        }

        public override string GetFeedPetSuccessMessage()
        {
            return "You fed the cat!";
        }

        public override string GetFeedPetFailedMessage()
        {
            return "You failed to feed the cat!";
        }

        public override string GetStarvePetMessage()
        {
            return "You starved the cat!";
        }
    }

    public class Dog : Pet
    {
        public Dog( string name, string breed, PetMood mood, HungerLevel hunger, bool isVaccinated ) :
            base( name, breed, mood, hunger, isVaccinated )
        {
        }

        public override string GetPlayWithPetMessage()
        {
            return @"You threw a frisby!";
        }

        public override string GetPunishPetMessage()
        {
            return "You scolded to dog!";
        }

        public override string GetFeedPetSuccessMessage()
        {
            return "You fed the dog!";
        }

        public override string GetFeedPetFailedMessage()
        {
            return "You failed to feed the dog!";
        }

        public override string GetStarvePetMessage()
        {
            return "You starved the dog!";
        }
    }

    public class Shark : Pet
    {
        public Shark( string name, string breed, PetMood mood, HungerLevel hunger, bool isVaccinated ) :
            base( name, breed, mood, hunger, isVaccinated )
        {
        }

        public override string GetPlayWithPetMessage()
        {
            return "You swam with! " + this.Name;
        }

        public override string GetPunishPetMessage()
        {
            return "You hit your shark on the nose!";
        }

        public override string GetFeedPetSuccessMessage()
        {
            return "You fed the shark!";
        }

        public override string GetFeedPetFailedMessage()
        {
            return "You failed to feed the shark!";
        }

        public override string GetStarvePetMessage()
        {
            return "You starved the shark!";
        }
    }

    public class Bird : Pet
    {
        public Bird( string name, string breed, PetMood mood, HungerLevel hunger, bool isVaccinated ) :
            base( name, breed, mood, hunger, isVaccinated )
        {
        }

        public override string GetPlayWithPetMessage()
        {
            return "You petted the bird!";
        }

        public override string GetPunishPetMessage()
        {
            return "You clipped the birds wings!";
        }

        public override string GetFeedPetSuccessMessage()
        {
            return "You fed the bird!";
        }

        public override string GetFeedPetFailedMessage()
        {
            return "You failed to feed the bird!";
        }

        public override string GetStarvePetMessage()
        {
            return "You starved the bird!";
        }
    }

    public class PetDataHandler
    {
        private readonly List<Pet> pets = new List<Pet>();

        public string this[ int i ]
        {
            get { return pets[i].Name; }
        }

        public void AddPet( Pet pet )
        {
            pets.Add( pet );
        }

        public void RemovePet( int i )
        {
            pets.RemoveAt( i );
        }

        public int PetCount()
        {
            return pets.Count;
        }

        public void Feed( int index )
        {
            pets[index].UpdatePet( pets[index].FeedPet() );
        }

        public void Starve( int index )
        {
            pets[index].UpdatePet( pets[index].StarvePet() );
        }

        public void PlayWith( int index )
        {
            pets[index].UpdatePet( pets[index].PlayWithPet() );
        }

        public void Punish( int index )
        {
            pets[index].UpdatePet( pets[index].PunishPet() );
        }

        public void GiveShot( int index )
        {
            pets[index].GivePetShot();
        }

        public void ShowData( int index )
        {
            pets[index].DisplayPetInformation();
        }

        //Creates an indexer for the pets list
    }

    public class Menu
    {
        readonly Input input = new Input();
        readonly PetDataHandler petList = new PetDataHandler();

        public void DisplayMainMenu()
        {
            DisplayTitle();
            Console.WriteLine( "[1] Add a pet\n" +
                                "[2] Remove a pet\n" +
                                "[3] Inspect a pet\n" +
                                "[4] Quit application\n" );

            MenuChoice( input.GetChoice( "Enter choice" ) );
        }

        public void DisplayPetTypeMenu()
        {
            DisplayTitle();
            Console.WriteLine( "[1] Cat\n" +
                                "[2] Dog\n" +
                                "[3] Shark\n" +
                                "[4] Bird\n" +
                                "[5] Exit\n" );

            PetTypeChoice( input.GetChoice( "Enter choice" ) );
        }

        public void DisplayPetActionMenu( int petIndex )
        {
            Console.WriteLine( "[1] Feed Pet\n" +
                                "[2] Starve Pet\n" +
                                "[3] Play With Pet\n" +
                                "[4] Punish Pet\n" +
                                "[5] Vaccinate Pet\n" +
                                "[6] Main Menu" );

            PetActionChoice( input.GetChoice( "Enter choice" ), petIndex );
        }

        public void DisplayPetRemovalMenu()
        {
            DisplayTitle();
            for ( int i = 0; i < petList.PetCount(); i++ )
            {
                Console.WriteLine( "[{0}]{1}", ( i + 1 ), petList[i] );
            }

            int choice = input.GetChoice( "Enter choice" );

            if ( choice > 0 && choice <= petList.PetCount() )
            {
                petList.RemovePet( choice - 1 );
            }

            DisplayMainMenu();
        }

        public void DisplayPetInspectionMenu()
        {
            DisplayTitle();
            for ( int i = 0; i < petList.PetCount(); i++ )
            {
                Console.WriteLine( "[{0}]{1}", ( i + 1 ), petList[i] );
            }

            int choice = input.GetChoice( "Enter number for pet" );

            if ( choice > 0 && choice <= petList.PetCount() )
            {
                petList.ShowData( choice - 1 );
            }

            DisplayPetActionMenu( choice - 1 );

            Console.ReadKey( true );

            DisplayMainMenu();
        }

        private void DisplayTitle()
        {
            Console.Clear();
            Console.WriteLine( "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n" +
                                "           Pet Application 1.0\n" +
                                "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-" );
        }

        public void MenuChoice( int choice )
        {
            switch ( choice )
            {
            case 1:
                DisplayPetTypeMenu();
                PetTypeChoice( input.GetChoice( "Enter choice" ) );
                break;

            case 2:
                DisplayPetRemovalMenu();
                break;

            case 3:
                DisplayPetInspectionMenu();
                break;

            case 4:
                Environment.Exit( 0 );
                break;

            default:
                Console.Write( "\n\nNot a valid selection. Press any key to return" );
                Console.ReadKey( true );
                DisplayMainMenu();
                break;
            }
        }

        public void PetTypeChoice( int choice )
        {
            switch ( choice )
            {
            case 1:
                petList.AddPet( new Cat( input.GetString( "\n\nName" ), input.GetString( "Breed" ), PetMood.Content,
                                        HungerLevel.Content, false ) );
                DisplayMainMenu();
                break;

            case 2:
                petList.AddPet( new Dog( input.GetString( "\n\nName" ), input.GetString( "Breed" ), PetMood.Content,
                                        HungerLevel.Content, false ) );
                DisplayMainMenu();
                break;

            case 3:
                petList.AddPet( new Shark( input.GetString( "\n\nName" ), input.GetString( "Breed" ), PetMood.Content,
                                            HungerLevel.Content, false ) );
                DisplayMainMenu();
                break;

            case 4:
                petList.AddPet( new Bird( input.GetString( "\n\nName" ), input.GetString( "Breed" ), PetMood.Content,
                                        HungerLevel.Content, false ) );
                DisplayMainMenu();
                break;

            case 5:
                DisplayMainMenu();
                break;

            default:
                Console.Write( "\n\nNot a valid selection. Press any key to return>" );
                Console.ReadKey( true );
                DisplayPetTypeMenu();
                break;
            }
        }

        public void PetActionChoice( int choice, int petIndex )
        {
            switch ( choice )
            {
            case 1:
                petList.Feed( petIndex );
                DisplayPetInspectionMenu();
                break;

            case 2:
                petList.Starve( petIndex );
                DisplayPetInspectionMenu();
                break;

            case 3:
                petList.PlayWith( petIndex );
                DisplayPetInspectionMenu();
                break;

            case 4:
                petList.Punish( petIndex );
                DisplayPetInspectionMenu();
                break;

            case 5:
                petList.GiveShot( petIndex );
                DisplayPetInspectionMenu();
                break;

            case 6:
                DisplayMainMenu();
                break;

            default:
                Console.Write( "\n\nNot a valid selection. Press any key to return>" );
                Console.ReadKey( true );
                DisplayPetTypeMenu();
                break;
            }
        }
    }

    public class Input
    {
        public string GetString( string prompt )
        {
            Console.Write( "{0}> ", prompt );
            return Console.ReadLine();
        }

        public int GetInt( string prompt )
        {
            Console.Write( "{0}> ", prompt );
            return int.Parse( Console.ReadLine() );
        }

        public int GetChoice( string prompt )
        {
            Console.Write( "{0}> ", prompt );
            return int.Parse( Console.ReadKey().KeyChar.ToString() );
        }
    }

    class Program
    {
        static void Main( string[] args )
        {
            var menu = new Menu();

            menu.DisplayMainMenu();
        }
    }
}
\$\endgroup\$
3
  • \$\begingroup\$ Excellent advise and good refactoring of the stuff you did. I've learned a lot! \$\endgroup\$
    – Zionmoose
    Commented Dec 24, 2013 at 7:57
  • 1
    \$\begingroup\$ DisplayPetInformation() - take the guts out and override ToString(). Then DisplayPetInformation() will simply be: Console Writeline(this). Typically where a string is expected ToString() is implicitly called. \$\endgroup\$
    – radarbob
    Commented Dec 27, 2013 at 22:25
  • \$\begingroup\$ (int) this.Mood > 0 defeats the purpose of enums don't you think? The default value of enum in C# is zero, but let's roll that into every enum: Undefined = 0. Then you can test like this if(! Mood.Undefined) …. Finally, if we ever add values to the enums, we probably just broke the code. \$\endgroup\$
    – radarbob
    Commented Dec 27, 2013 at 22:33
10
\$\begingroup\$

A huge amount of that code is 'garbage', afraid to say.

You already have all the basic pet data stored in the Pet class... so there is no need to duplicate it all in each pet type class (Dog/Cat, etc.).

For example, your Cat class should remove all the duplication in then simply be:

public class Cat : Pet
{
    public Cat(string name, string breed, PetMood mood, HungerLevel hunger, bool isVaccinated) : 
        base(name, breed, mood, hunger, isVaccinated)
    {
        // base constructor takes care of everything.
    }

    ......

}

Then, in your other methods you should reference the 'public' base variables Name instead of _name, etc.

Finally, you should add values to the Pet class that indicate thresholds for things like mood and hunger. All the currently 'abstract' methods on the Pet should instead be full methods, but should be parameterized. For example, the method on Dog:

    public override PetMood PlayWithPet()
    {
        if ((int)_mood < 4)
        {
            Console.WriteLine("You threw a frisby!");
            return _mood += 1;
        }
        return _mood;
    }

Should instead be on Pet, and would look like:

    public PetMood PlayWithPet()
    {
        if ((int)Mood < MoodThreshold)
        {
            Console.WriteLine(PlayMessage);
            return Mood += 1;
        }
        return Mood;
    }

Then, when you construct Dog you should also add all the thresholds and messages that are needed in the Pet class.

By doing this, the actual implementations ( Dog, Cat, etc.) become simple classes with just a constructor and no methods at all. The Pet Base class does all the heavy-lifting, and the code is in one place only.

\$\endgroup\$
2
  • \$\begingroup\$ I definitely see where you are coming from, but if I'm not mistaken, your solution appears to not meet the parameters of what the homework was designed to be. Three of the methods in the base class Pet had to be abstract so that you could define the functionality. The idea, even if it is more complicated then it needs to be, is to just get us to understand how things like abstract, override and virtual work. \$\endgroup\$
    – Zionmoose
    Commented Dec 23, 2013 at 19:46
  • 2
    \$\begingroup\$ In which case, have abstract methods that return: getMoodThreshold(), getHungryThreshold(), getFeedMessage(), etc. \$\endgroup\$
    – rolfl
    Commented Dec 23, 2013 at 19:49
8
\$\begingroup\$

There is a lot of repetition here; although @rolfl already explained that very well.

Aside from moving all of the base variables into the Pet class I would add one more piece of advice: Writing code is like writing a book. Try to make it read like one.

For example:

public override PetMood PlayWithPet()
{
    if (inABadMood)
    {
        Console.WriteLine("You threw a frisby!");
        IncreaseMood();
    }
    return Mood;
}

These are simple to implement and are nice and easy to read. Once you go over Interfaces there will be a lot more power to this but right now it improves readability.

Those extra parts can be made like:

protected int _goodMoodAmount = 4;
protected int _badMoodAmount = 0; 

public Boolean InABadMood
{
    get
    {
        return (int)_mood > _goodMoodAmount;
    }
}

Now, if this was someone else's code and you were trying to figure out what it was doing, which would you prefer? Because that is the situation your lecturer will be in!

\$\endgroup\$
4
\$\begingroup\$

Another thing to consider. Instead of sending the output of your methods directly to the console, make them return a string. This way a person using your class can output it to a console or a form or a webpage whatever.

You might want to consider having the menu display and the switch block, that processes the input, in the same method. If you decide to change a menu item all your code for that is in one place.

If you want the ability to use a foreach loop with your petlist you'll have to implement an enumerator as well.

\$\endgroup\$
1
  • \$\begingroup\$ Good points. Haven't come to enumerators yet which is why I did it the way I did. Thanks! \$\endgroup\$
    – Zionmoose
    Commented Dec 23, 2013 at 19:49
3
\$\begingroup\$
(int)_mood < 4

If you want to compare enum values with numbers, then you should specify them explicitly in the definition of the enum. But even better option would be to compare the enum values directly:

_mood < PetMood.Happy

if ((int)_mood < 4)
{
    Console.WriteLine("You gave the cat a ball!");
    return _mood += 1;
}
Console.WriteLine("You gave the cat a ball!");
return _mood;

You should try to avoid repetition in your code (this is called Don't Repeat Yourself, or DRY). The problem with repeating is that when you want to modify the code, you will need to modify all instances. And you are going to forget that sooner or later, which leads to unnecessary bugs.

So, you could write this code instead like this:

if ((int)_mood < 4)
    _mood += 1;

Console.WriteLine("You gave the cat a ball!");
return _mood;

Your menu code also contains lots of repetition. What you could do is to create a type that represents a menu entry and the associated action and then work with collections of these.

\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.