Pirates, Ninjas, and C++

Last night, in the C++ course that I teach at a local community college, we worked through a code sample that was a little more interesting than what I’ve done in past semesters.  I like choosing fun examples (i.e. class SushiChef : Person) and generally see good results- the class is engaged in conversation and the code and most students end up learning something new.  Yesterday I decided to try a new example and it went so well that I thought I’d post it here.

The course is more of an introduction to Object Oriented Programming than a strict C++ syntax seminar.  The three big tenants of OOP that we learn in this course are encapsulation, inheritance, and polymorphism.  In my day there was a fourth: data-hiding.  But it’s whatever.  We’re very early in the semester right now so the class is still coming to grips with encapsulation.

To demonstrate a decent use of encapsulation, which is the aggregation of multiple pieces of data and even behaviors into a single entity or “class,” while also showing how encapsulated ideas can work together, I usually set up a Request-Processor-Response pattern of sorts.  One boring example that I did one was a BankAccount (request) gets passed to an AccountValidator.Validate method (processor) and hands back a ValidationResult (response).  Once I did a SushiOrder getting passed to a SushiChef.Prepare method and returning a SushiPlate.  I think you get the idea.

Well the new idea I wanted to try, in the interest of garnering more class engagement, was a Pirates Vs. Ninjas theme.  The idea is that Pirates are bad, and we want to kill them.  We do this by hiring their natural enemy, Ninjas, to destroy them.  And we gauge the resulting attack with a FightResult object.

To explicitly conform to our pattern of Request-Processor-Response, we are saying that:

  • Request = Pirate
  • Processor = Ninja
  • Result = FightResult

There is something fun about the idea of a processor being a Ninja.

Anyway, to keep things simple, we decided that both the Pirate and the Ninja classes should each contain a SkillLevel (int) and that conflict is resolved by checking if the Ninja’s skill level is equal-to or greater-than the target Pirate’s SkillLevel.

I had already decided on throwing a fun wrench into this equation later on by having an IsTurtle property on the Ninja, since we do have 4 precedents of ninjas being turtles, and that any Ninja that IsTurtle will get a 5 point boost on his/her skill level when fighting a pirate.

That was really the only spin I put on the thing, and with hardly any prompting my students came up with some wonderful ideas for extending the example.  Some of them we added to the code, but most we didn’t.  The reason being is that I would like for them to download the source that I wrote last night and implement their ideas.

Before I even had a chance to get to my IsTurtle idea, one of my students raised his hand with the very same notion!  Another student said that the Pirate class should have a boolean for IsDrunk, and I think that might be my favorite line of code I’ve ever written.  Another student wanted to add a boolean HasParrot to the pirate.  Yet another student wanted the Ninja to have a WasSeen flag, which brings up the idea of having style points factor into the equation.  And yet another student had the brilliant idea the if the Pirate.HasParrot then the Ninja.WasSeen!  And if the Ninja is detected then the Pirate gets an advantage- that is one handy parrot!

Again, the code that I demonstrated is very simple and only really the starting point for a much more deep and complex example.  This is deliberate, so that the students (and yourself!) can download it and start tinkering and extending it.  One student pointed out that we had practically come up with a Pokemon game and I hope he takes the code in that direction and finishes it!

So, let’s take a look at the code!  All of this is compiled using Visual Studio 2010, as a 32-bit console app.

First up, here is our Pirate class- this is only the .h file.  The corresponding implementation (.cpp) file is unnecessary as all funtionality here is inline:

#pragma once
#include <string>

using namespace std;

class Pirate
{
public:

    string Name;
    int SkillLevel;
    string Weapon;
    bool IsDrunk;
    bool HasParrot;

    Pirate() { Name = "Black Beard"; SkillLevel = 5; Weapon = "Musket"; IsDrunk = true; HasParrot = true; }
    ~Pirate(void);
};

Next up is our FightResult class- again, all that is needed is the .h file:

#pragma once
#include <string>

using namespace std;

class FightResult
{
public:

    bool Success;
    string Message;

    FightResult(void) { Success = false; Message = ""; }
    ~FightResult(void);
};

Now let’s take a look at the Ninja class, both the .h file and the relevant piece of the .cpp are presented here:

#pragma once
#include <string>
#include "FightResult.h"
#include "Pirate.h"

using namespace std;

class Ninja
{
public:

    int SkillLevel;
    string Weapon;
    float HitFee;
    bool WasSeen;
    bool IsTurtle;

    FightResult Attack(Pirate p);

    Ninja(void) { SkillLevel = 5; Weapon = "Katana"; HitFee = 200.0; WasSeen = false; IsTurtle = false;}
    ~Ninja(void);
};

FightResult Ninja::Attack(Pirate p)
{
    FightResult result;

    int bonus = 0;
    if(IsTurtle)
    {
        bonus = 5;
    }

    if((bonus + SkillLevel) >= p.SkillLevel)
    {
        result.Success = true;
        result.Message = "The Ninja we hired successfully destroyed " + p.Name + " with his " + Weapon + "!";
    }
    else
    {
        result.Success = false;
        result.Message = p.Name + " has killed the Ninja we hired!  Yaarrrrrr!";
    }

    return result;
}

Here is a sample of the test main that we wrote to put these classes to work:

#include "stdafx.h"

#include <iostream>

#include "Ninja.h"

#include "Pirate.h"

#include "FightResult.h"

using namespace std;

int _tmain(int argc, _TCHAR* argv[])

{

    Pirate pete;

    pete.Name = "Pete";

    pete.IsDrunk = true;

    pete.HasParrot = true;

    pete.SkillLevel = 7;

   
    Ninja leonardo;

    leonardo.IsTurtle = true;

   
    FightResult result;

    result = leonardo.Attack(pete);

    cout << result.Message << endl;

    system("pause");

    return 0;

}

And that’s it!  It’s not fancy, but its some straight-forward, basic OOP.  I’ve never seen my class so energized and alive and willing to participate in a code example!

Leave a comment