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# C# Objects Loops and Final Touches Playing the Game

janeporter
PLUS
janeporter
Courses Plus Student 23,471 Points

getting several runtime errors when i try to run the game...

when I compile the programs, they compile fine:

treehouse:~/workspace$ mcs -out:TreehouseDefense.exe *cs    

but when I go to run the programs,

treehouse:~/workspace$ mono TreehouseDefense.exe

I get the following errors:

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object               
  at TreehouseDefense.Invader.get_HasScored () <0x4124d210 + 0x00016> in <filename unknown>:0                          
  at TreehouseDefense.Invader.get_IsActive () <0x4124d1b0 + 0x00033> in <filename unknown>:0                           
  at TreehouseDefense.Tower.FireOnInvaders (TreehouseDefense.Invader[] invaders) <0x4124d0d0 + 0x0004b> in <filename un
known>:0                                                                                                               
  at TreehouseDefense.Level.Play () <0x4124cf60 + 0x0007b> in <filename unknown>:0                                     
  at TreehouseDefense.Game.Main () <0x4124bd50 + 0x008c3> in <filename unknown>:0  

What am I doing wrong??

janeporter
janeporter
Courses Plus Student 23,471 Points

Invader.cs

namespace TreehouseDefense
{
  class Invader
  {
    private readonly Path _path;
    private int _pathStep = 0;

    public MapLocation Location => _path.GetLocationAt(_pathStep);

    public int Health { get; private set; } = 2;

    //returns true if the invader has reached the end of the path
    public bool HasScored { get { return _pathStep >= _path.Length; } }

    //returns true if the invader's health is 0 or less
    public bool IsNeutralized => Health <= 0;

    public bool IsActive => !(IsNeutralized || HasScored);

    public Invader(Path path)
    {
      path = _path;
    }

    public void Move() => _pathStep += 1;
    public void DecreaseHealth(int factor)
    {
      Health -= factor;
    }
  }
}

Tower.cs

namespace TreehouseDefense
{
  class Tower
  {    
    private const int _range = 1;
    private const int _power = 1;

    private readonly MapLocation _location;

    public Tower(MapLocation location)
    {
      _location = location;
    }

    public void FireOnInvaders(Invader[] invaders)
    {      
      foreach(Invader invader in invaders)
      {
        if(invader.IsActive && _location.InRangeOf(invader.Location, _range))
        {
          invader.DecreaseHealth(_power);
          break;
        }
      }
    }
  }
}

Level.cs

namespace TreehouseDefense
{
  class Level
  {
    private readonly Invader[] _invaders;

    public Tower[] Towers { get; set; }

    public Level(Invader[] invaders)
    {
      _invaders = invaders;
    }

    // returns: true if the player wins, false otherwise.
    public bool Play()
    {
      // run until all invaders are neutralized, or an invader reaches the end of the path.
      int remainingInvaders = _invaders.Length;

      while(remainingInvaders > 0)
      {
        // each tower has an opportunity to fire on invaders.
        foreach(Tower tower in Towers)
        {
          tower.FireOnInvaders(_invaders);
        }

        // count and move the invaders that are still active.
        remainingInvaders = 0;
        foreach(Invader invader in _invaders)
        {
          if(invader.IsActive)
          {
            invader.Move();

            if(invader.HasScored)
            {
              return false;
            }
            remainingInvaders++;
          }
        }
      }  
      return true;
    }
  }
}

and Game.cs

using System;

namespace TreehouseDefense
{
  class Game
  {
    public static void Main()
    {
      Map map = new Map(8, 5);

      try
      {
        Path path = new Path(
          new [] {
            new MapLocation(0,2,map),
            new MapLocation(1,2,map),
            new MapLocation(2,2,map),
            new MapLocation(3,2,map),
            new MapLocation(4,2,map),
            new MapLocation(5,2,map),
            new MapLocation(6,2,map),
            new MapLocation(7,2,map)
          }
        );

        Invader[] invaders =
        {
          new Invader(path),
          new Invader(path),
          new Invader(path),
          new Invader(path)
        };

        Tower[] towers = {
          new Tower(new MapLocation(1,3,map)),
          new Tower(new MapLocation(3,3,map)),
          new Tower(new MapLocation(5,3,map))
        };

        Level level = new Level(invaders)
        {
          Towers = towers
        };  

        bool playerWon = level.Play();

        Console.WriteLine("Player " + (playerWon? "won" : "lost"));
      }
      catch (OutOfBoundsException ex)
      {
        Console.WriteLine(ex.Message);
      }
      catch (TreehouseDefenseException)
      {
        Console.WriteLine("Unhandled TreehouseDefenseException.");
      }
      catch (Exception ex)
      {
        Console.WriteLine("Unhandled Exception: " + ex);
      }      
    }
  }
}

1 Answer

Steven Parker
Steven Parker
231,271 Points

:point_right: The constructor for the Invader class is assigning to it's argument.

I see one thing that might explain your error. Currently, the code for the constructor is:

      path = _path;

But you probably intended it to be:

      _path = path;

:information_source: In future, for something of this complexity you might consider providing a snapshot of your workspace, to facilitate analysis of the problem and testing of potential solutions.

janeporter
janeporter
Courses Plus Student 23,471 Points

that's exactly what it was. I can't believe I missed that.Thank you!