Find Your Hat Challenge Project (JavaScript)

Here’s my solution. Didn’t add in any of the optional challenges yet, but will probably revisit that a little later. Uses WASD for navigation (not case sensitive), and I got rid of the end-the-game if you hit a border check as that was a little annoying (it simply doesn’t move if you’re up against an edge).

You can determine grid-size at the command-line.
(ex. node main.js 10 10 – this will create a 10x10 field)

Very neatly put together! All I can see is that each time you call your direction variable you use .toUpperCase.
Methods can be applied at any stage so this can be put into the variable declaration and so only written once.

const direction = (prompt(‘text’)).toUpperCase

@callmej9 hey, Your code would require some in depth analysis because there seems to be a lot wrong but I’ll just try to point out a few.

This is the reason for your output, your game array variable stores a an array that would have a length of 25 for a 5 by 5 field. However what you need for this project is a nested array, so a 5 by 5 field would be [ […], […],[…],[…],[…] ]. So try to change that. One option is:

static generateField(width,height){

let myField = [];

for (let i = 0; i < height; i++){

  myField.push([]);

}

secondly, you only defined a bunch of functions within your your generateField functions, while I can see some errors within those functions themselves, you never called the functions within generate field,so the functions never alter game array.

thirdly

This print condition is wrong too, if the height of the array is greater than 3 it still prints an array of 3. the check condition should be something like i< this.field.length; this way you can handle any size of field.

this is wrong too, in this game we are to enter d,r,l or u, so checking for “down” wouldn’t work.
also

pathCharacter and fieldCharacter were defined as the above symbols at the top of the game so they are never going to be equal.
Also

This doesn’t work either since pathCharacter is a symby and field width is a number.
What you actually want to do is add variables like playerX and playerY to keep track of the player position and then you can compare it to the fieldW and fieldH.
It’s also worth noting that if the field width was 5,then since indexing starts from 0, the valid positions are 0,1,2,3,4. So your out of bounds comparison would be when playerX === fieldW.
I’ll advice to check various portions of your code with (console.log) to try to isolate issues and debug your code.
I know it’s a late reply but I hope it helps, good luck on your coding journey.

1 Like

that’s really helpful, thank you!

1 Like

I spent far more than the 2 hours it said this would take, and have something that’s minimally functional. This one was tough and required some digging outside of the scope of what we’ve learned so far:

  1. Step 4 broke me, and I had to look at someone else’s code in these comments to figure out how to implement a game loop.
  2. I almost crippled my Mac in the process of wiping node and NPM from the command line while trying to get Terminal to work within Atom.
  3. Figuring out how to generate a 2D array in Step 5 was a rabbit hole of its own, and I still don’t totally understand how it works.

I’m glad I dug into this one though, as it exposed me to a lot of new concepts. Here’s my code:

const prompt = require('prompt-sync')({sigint: true});

const hat = '^';
const hole = 'O';
const fieldCharacter = '░';
const pathCharacter = '*';

let playing = true;


class Field {
  constructor(field) {
    this._field = field
    this.x = 0;
    this.y = 0;
  }

  get field() {
    return this._field;
  }

  print() {
    let x = this.field.join('\n');
    console.log(x.replace(/,/g," "));
  }

  direction() {
    let input = prompt('Which way? (u,d,l,r)')
    switch(input.toLowerCase()) {
      case 'r':
          this.x++;
        break;
      case 'l':
          this.x--;
        break;
      case 'd':
          this.y++;
        break;
      case 'u':
          this.y--;
        break;
      default:
        console.log(`Please use u,d,l,r.`);
      }
  }

  static randTile () {
    let randomNum = Math.floor(Math.random()*10)
    if (randomNum > -1 && randomNum < 7) {
       return fieldCharacter
    } else {return hole}
  }

  static generateField (rows,columns) {
    let randArray = [];
    for (let i = 0; i < rows; i++) {
      randArray[i] = [];
      for (let j = 0; j < columns; j++) {
        randArray[i][j] = this.randTile();
      }
    }
    randArray[0].splice([0], 1, pathCharacter);
    randArray[Math.floor(Math.random() * rows)].splice([Math.floor(Math.random() * columns)], 1, hat);
    return randArray
  }

  gameState() {
    if (this.field[this.y] == undefined) {
         console.log('Game Over -- Out of bounds!');
         return playing = false;
     }

     // All this code is to try to prevent the player from going back. Maybe I can have a helper called isBack() that checks all this
     //let move = []
     //let x = this.x
     //let y = this.y
     //move.push({x, y})
     //let lastMove = move.shift()
     //console.log(lastMove.x, lastMove.y);

     //if ((this.x, this.y) !== (lastMove.x, lastMove.y)){
    switch (this.field[this.y][this.x]) {
      case fieldCharacter:
        this.field[this.y].splice([this.x], 1, pathCharacter);
        break;
      case hole:
        console.log('Game over -- You fell in a hole!');
        playing = false;
        break;
      case hat:
        console.log('You win -- you found your hat!');
        playing = false;
        break;
      case pathCharacter:
        console.log("You can't go back!")
        break;
      case undefined:
        console.log('Game over -- Out of bounds!')
        playing  = false;
      }
    //}
  }
};

const myField = new Field(Field.generateField(7,8))

const gameLoop = () => {
  while(playing) {
    myField.print();
    myField.direction();
    myField.gameState();
  }
}

gameLoop()

I’m sure there are a ton of things I could do better, and I plan on making incremental improvements over the next few weeks. I’d like to implement some of the challenge items, to make it so you can’t go back, so you don’t have to hit enter after each move, so you can play with the arrow keys instead of UDLR, and a few other things. Great project!

Hey n00bb0t,

I went to your GitHub and downloaded your upload for this project, but for some reason I’m having trouble getting the collections/ heap module through npm-- Terminal is giving me some kind of error that may be related to SSH. I’m interested in the maze solver you made and I want to play the game to see it working. Any way you could upload the game in a folder that includes your node_modules files?

Hi everyone,

This is my solution.

Hey guys!
Check my solution too.
Might be interesting :))

Hi all,

I just completed Find Your Hat. I hadn’t touched command line for a while, so I found the project surprisingly difficult, especially in keeping with the bidirectional array requirement (which wasn’t at all necessary, IMO).

Please check out my solution if only to offer feedback or get some hints! Thank you!

P.S. You’ll need to run install the prompt-sync dependency before attempting to run the game from the file main.js

Hi space_horse,

I’m still kinda learning Git and Package Managers but I’ve uploaded what I think is a working solution. The package you need is called collections authored by Kris Kowal.

You can try this repo and see if it helps you:

Sorry for slow reply, been away.

Wow!
Here’s my solution.

THIS WAS… challenging. I learned a lot, though.

Most difficult for me, was implementind the fieldValidator (I used A*).
I added a shortest path detector, which tells you when you were really smart and took the most efficient path to your hat (although, let’s be honest, it’s sometimes not that hard :wink: ).

May have to revisit some time, to implement other extra challenges, I’m really tired now :frowning: .

I’d love to get some feedback… probably could improve so many things still.

Happy learning, everyone!

1 Like

No problem – thank for the upload, I got it to work. The maze solver seemed to work pretty well. This is a project I plan to come back to and improve, so I’m sure I’ll be looking at your solution and a few other soon.

this is my code whit all challenges completed

This was a fun challenge really made me go back and make sure i knew my basics.

I did not make this code able to keep you from going back if you get your char stuck but I did make it able to change the size of the field in the code. (pretty easy to add a user input for that but meh lol)

Take a look! I will add Comments tomorrow I know my code is a little messy. I really dont think I would use classes next time for this project.

Hey I dont know if you fixed it but your field is basically all holes and only one field space. check mine out to see how i did the 30%

Here’s what I ended up with. I’ll have to come back later and do the challenges, I don’t have time to do a maze solver right now.

The main difference in my approach was the way I scoped the gameplay. I kept my game functions and objects outside the Field class, it made sense to me to separate a class that generates and manages a field and player position from this one specific game application (Find Your Hat), because the Field class could theoretically be used to generate fields that could be used in lots of different games.

Link to my solution on github.

As someone with beginner-level programming experience it took me three days of trial & error, google searches, and youtube Node tutorials to figure out how to run this program locally rather than in the codecademy module, so maybe this advice will be helpful to someone else for how to make it work:

  1. Obviously download Node and a text editor. I started with Atom but switched to VSC because it has a built-in terminal that runs powershell right out of the gates. You can also easily install bash from GitHub, if you want the terminal that appears in the codeacademy module. Just create a .js file in VSC and then open the terminal from the drop-down menu at the top.
  2. When using the terminal to execute the script make sure you are in the right directory.
  3. INSTALL THE NPM PROMPT-SYNC MODULE. This is what took me the most time to figure out, I assumed it just comes with Node. You can do it right from the VSC terminal with the command “npm install prompt-sync.”
  4. If the command line does not recognize the “node” command (easy test is to type “node -v” with an expected output of the version of node you have installed) then troubleshoot here.

And it’s that easy! I’ve learned way more about Node than I anticipated but now I can get back to completing the challenge elements of the code.

So this is my implementation of the game. I realize it could be more efficient but it took me a long time to put it together and I can’t keep working on it forever. It was an interesting project. It forced me to look up all kinds of stuff and I ended up learning a lot.

Feedback welcome of course.

It was a very challenging project for me. I struggled with my limitations. I believe it could be done i a more efficient way, but I´m done with this. It took me a lot of time and I have to keep moving.
I just did not have the time for the maze validation.

Keep on coding!