Sample Video Frame

24: OOP Game

You are now going to complete a reworking of your game into an OOP version. What I've done is created the structure for you using classes and objects, but I've left blank what goes in each room. Your job is to take this and fill in your code from your first game but keep the structure and make it all work with what I have.

You will need to study this code very carefully as it is convoluted on purpose. I am making it more convoluted that it needs to be so that you can have some practice studying code like this. Then in the video for this exercise I do something called "re-factoring". This is where I take a code that is not very good and attempt to improve it by redesigning it or reworking it to be better.

I recommend that you take this code very slowly and work it in chunks. Do not type all of this in in one giant go expecting it to work the first time. Nobody who is a working professional programmer writes mountains of code in one shot and expects it to work. The majority of programmers I know right there code in tiny chunks and confirm that each little chunk works as they code. If you are not sure what I'm talking about then watch the video where I demonstrate this.

The Code

Remember this code is longer than almost anything you've encountered and it is more complicated. You are expected to take some time with this and figure out how it all works! If you attempt this and then give up after 30 minutes you are not doing it right. This code could potentially take anywhere from two days to a week.

If you want an additional challenge then you can attempt to refactor the code to be cleaner before watching me do it in the video. As I said before, this code if convoluted on purpose so that I can show you how I might refactor it, and so you can try to understand OOP code like this. If you want to test your understanding of the code, then try to clean it up and make it simpler on your own before seeing how I do it in the video.

const readline = require('readline-sync');

class Game {
  constructor () {
    this.hp = Math.floor(Math.random() * 10) + 1;
  }

  say(prompt) {
      console.log(prompt);
  }

  die(message) {
      this.say(message);
      process.exit(1);
  }

  ask(prompt) {
      console.log(`[[You have ${this.hp} hit points.]]`);
      if(this.hp <= 0) {
          this.die("You died!");
      } else {
          return readline.question(prompt + ' ');
      }
  }

  addRoom(room) {
    this[room.name] = room;
    room.game = this;
  }

  play(name) {
    this[name].enter();
  }

  hit(amount) {
    this.hp -= amount;
  }
}

class Room {
  constructor (name) {
    this.name = name;
  }

  enter() {
    console.log("Implement me!");
  }
}

class Door extends Room {
    enter() {
      // they have to open the door to get the gold
      // what kind of puzzle will they solve?
    }
}

class Spider extends Room {
  enter() {
    // they enter here, and the spider takes 10 hit points
    // if they live then they can run away
  }
}

class Gold extends Room {
  enter() {
    // end of the game they win if they get the gold
  }
}

class Rope extends Room {
  enter() {
    // they are at the bottom of the well
    // they can go through the door to the gold
    // or go take a wrong turn to the spider
  }
}

class Well extends Room {

  enter() {
    this.game.say("You are walking through the woods and see a well.");
    this.game.say("Walking up to it and looking down you see a shiny thing at the bottom.");
    let next = this.game.ask("What do you do?");

    if(next === "climb") {
        this.game.say("You climb down the rope.");
        this.game.rope.enter();
    } else if(next === "jump") {
        this.game.say("Yikes! Let's see if you survive!");
        this.game.hit(5);
        this.game.rope.enter();
    } else {
        this.game.say("You can't do that here.");
        this.game.well.enter();
    }
  }
}


let game = new Game();
game.addRoom(new Well("well"));
game.addRoom(new Rope("rope"));
game.addRoom(new Gold("gold"));
game.addRoom(new Spider("spider"));
game.addRoom(new Door("door"));
console.log(Object.entries(game));
game.play("well");
As of 2022 the video is missing an important refactoring where I remove using this[] from the game. I completely forgot to do this, so you should fix it for me. The problem is that when you use this[] you're directly modifying the attributes of that object with the names of rooms. These names can conflict with the names of attributes on the object. A better solution is to have a separate this.rooms attribute and add the rooms to that variable, not directly on the `this` object. My original intention was to demonstrate this since I saw people doing it on accident but I totally forgot. To fix it find everywhere you're doing this[] and change it to this.rooms[] then make the game work again.

What You Should See

When you run this code without any of your modifications you should see this as an output:

$ node ex24-oop-game/code.js
You are walking through the woods and see a well.
Walking up to it and looking down you see a shiny thing at the bottom.
[[You have 10 hit points.]]
What do you do? climb
You climb down the rope.
$ node ex24-oop-game/code.js
You are walking through the woods and see a well.
Walking up to it and looking down you see a shiny thing at the bottom.
[[You have 4 hit points.]]
What do you do? jump
Yikes! Let's see if you survive!
$ node ex24-oop-game/code.js
You are walking through the woods and see a well.
Walking up to it and looking down you see a shiny thing at the bottom.
[[You have 8 hit points.]]
What do you do? asdfsaf
You can't do that here.
You are walking through the woods and see a well.
Walking up to it and looking down you see a shiny thing at the bottom.
[[You have 8 hit points.]]
What do you do? jump
Yikes! Let's see if you survive!

Learn JavaScript Today

Register today for the Early Access course and get the all currently available videos and lessons, plus all future modules for no extra charge.


Still Not Sure? Try the next FREE Lesson!