Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

C# Intermediate C# Polymorphism Accessor Access Modifiers

Questions and Review the code on my Tower types

So the teacher in the end of this lesson gave the task to write 3 types of Towers by our own. After i finished to write mine, I looked into his solution, however mine quite different than his, this is mine:

The class for PowerfulTower:

namespace TreehouseDefense
{
    class PowerfulTower : Tower
    {
        public PowerfulTower(MapLocation location) : base(location)
        {

        }


        //this type of Tower can decrease the haelth of an Invader by 2 evrey shot.
        protected override int towerPower {get; } = 2;

    }
}

the class for LongrangeTower:

namespace TreehouseDefense
{

    //this type of Tower is a special towe who  has a range of 3, this Tower can spot invaders that their range from the tower is 3.
    class LongrangeTower : Tower
    {
        protected override int towerRange {get;} = 3;


        public LongrangeTower(MapLocation location) : base(location)
        {

        }

    }
}

the class for SniperTower:

using System;

namespace TreehouseDefense
{
    //this type of Tower is with higher accuracy to hit an Invader.
    class SniperTower : Tower
    {
        private static  Random _random =  new Random();
        protected override double accuracy{get;} = .86;// .86 is 0.86?

        public SniperTower(MapLocation location) : base(location)
        {

        }

        public override bool isSuccessfulShot()
        {
            //there is 86% to hit an invader.
            if(_random.NextDouble() < accuracy)
            {
                Console.WriteLine("The SniperTower Shot at and HIT an invader Hurray! :]");
                return true;
            }
            else
            {
                Console.WriteLine("The SniperTower Shot at a invader but missed :[");
                return false;
            }

        }




    }
}

I did an expirement and added a setter to each property, and runned it and it worked, why is it? The other thing that was quite different from the teacher's solution is my SniperTower class, I overriden the isSuccessful() method and added a condtion to get a new output to the console such as "The SniperTower Shot at and HIT an invader Hurray! :]", is it ok?

Bonus i tried to build a SuperTower

namespace TreehouseDefense
{
    class SuperTower : Tower
    {
        protected override int towerRange {get; } = 3;
        protected override int towerPower {get; } = 3;
        protected override double accuracy{get;} = .95;

        public SuperTower (MapLocation location) : base(location)
        {
        }


    }
}

and a class for SuperInvader:

using System;

namespace TreehouseDefense
{
    class SuperInvader : Invader
    {
        private static Random _random =  new Random();

        public SuperInvader(Path path) : base(path)
        {
        }


        public override int health {get; protected set;} = 4;
        protected override int stepSize {get;} = 3;

        public override void decreaseHealth(int factor)
        {
            //if the generated number is less than .5
            if(_random.NextDouble() <.2) // .2 is 0.20?
            {
                //we decrease the health
                base.decreaseHealth(factor);
            }
            else
            {
                Console.WriteLine("Shot at a shileded invader but it sustained no damage :[");  
            }

        }


    }
}

Steven Parker Jennifer Nordell

:]

5 Answers

Steven Parker
Steven Parker
231,198 Points

You've been pretty busy! And having different code from the video examples is fine, as long as you've tested them and they work, that's what's important. At first glance these all look good. :+1:

One question, doesn't adding messages to "IsSuccesfulShot" give duplicates, since "FireOnInvaders" already outputs messages based on the return value?

Steven Parker this is my current snapshot: https://w.trhou.se/gw5zvvpei7

I tested it again and this is the result: https://gyazo.com/c58c628a9a1fcd6c5857dbfd2a0ff1ee

it seems like it dosent give duplicates, can u run it as well?

one other question i have is when i write .5 or .75 it is >> 0.50, 0.75 and so on? and u didnt answered this: I did an expirement and added a setter to each property, and runned it and it worked, why is it?

Steven Parker ur online? ^^

Steven Parker
Steven Parker
231,198 Points

Here's an example of the duplicate message I was anticipating:

The SniperTower Shot at and HIT an invader Hurray! :]
Shot at and HIT an invader :D

Of course, with mutiple towers and multiple invaders it's hard to see that it's a duplicate. But to be sure who is firing on whom you could possibly add coordinates to the messages. Then they might look like this:

Tower at 2,1 shot at and HIT the invader at 3,1   :D

And there's a default output format for floating/double numbers. There are ways to set your own format if you don't like the default one. See the documentation on Custom Numeric Format Strings for more details.

I struggle to add the coordinates to the Tower and to the Invader. How excatly i get the coordinate for example, in the Invader.cs file for both the Tower and The Invader? in the invader class, i have a property called Location so im quite sure it legit to get the location like this for the invader, but what about the Tower?, do i need to add a Tower paramter to the method just like i did and use the _location field in Tower?, i dont know if its even run.. I tried this, it seems like i get invader location but im not quite sure..

    public virtual void decreaseHealth(int factor,Tower tower)
        {
            health -= factor;
            Console.WriteLine("Tower at {0},{1}  Shot and HIT an Invader at ({2},{3}) :D "tower._location.x, tower._ location.y,Location.x, Location.y);
        }

same with what happend when i netrualize an invader

      if(invader.isNeutralized)
     {
           Console.WriteLine("You just netrualized an invader at ({0},{1}) :]", invader.Location.x, invader.Location.y);
         }  

And How i can fix this duplicate problem?, If i can't override the messege to get a output for a SniperTower how i can do it? thanks in advance..

Steven Parker

Steven Parker
Steven Parker
231,198 Points

The second example seems OK, but the first one has some issues:

  • there's a comma missing between the string and the first coordinate (tower._location.x)
  • you cannot have spaces inside an identifier ("tower._ location.y")
  • the "_location" in a tower is private and cannot be accessed from the invader
  • you can fix that by passing the MapLocation itself (instead of the Tower) to "decreaseHealth"

The duplicate cannot be fixed with an override because the message is coming from a class other than the parent. You might do something similar to what you did here and pass additional arguments to extend the original message instead of adding another message in a different class.

Steven Parker
Steven Parker
231,198 Points

I only get one notice when I connect no matter how many tags were added while I was away. :stuck_out_tongue_winking_eye:

Steven Parker this is what i tried to do now:

public virtual void decreaseHealth(int factor, MapLocation towerLocation)
        {
            health -= factor;
            Console.WriteLine("Tower at {0},{1} Shot and HIT an invader At {2} :D",towerLocation.x, towerLocation.y,Location);

i get this errors:

ShieldedInvader.cs(25,10): error CS1501: No overload for method `decreaseHealth' takes
 `1' arguments                                                                        
Invader.cs(102,23): (Location of the symbol related to previous error)                
SuperInvader.cs(23,10): error CS1501: No overload for method `decreaseHealth' takes `1
' arguments                                                                           
Invader.cs(102,23): (Location of the symbol related to previous error)                
Tower.cs(54,17): error CS1501: No overload for method `decreaseHealth' takes `1' argum
ents      

i added a MapLocation param to each to the shilededinvader and the superinvader how i can fix it? it says that that this method take 1 argument, but in order to get the tower location i need to have 1 more paramater

Steven Parker
Steven Parker
231,198 Points

It sounds like when you added the extra parameter to "decreaseHealth" you did not add an extra argument to go with it in every place it is called.

Also, you probably can't pass the "Location" directly to WriteLine unless you have given MapLocation an override for "ToString", but that would be a cool thing to do.

This thread seems to be getting long and wandering, perhaps this question should be closed and a new one started for anything else. :wink: