Find Your Hat Challenge Project (JavaScript)

2 Likes

@annajiali This challenge is siginificantly too difficult for the point at which it’s given to learners in the Full Stack Dev course. Listing it as taking 90 minutes is a joke.

We need quite a bit more JS instruction before a project like this.

Please read through previous replies, this is a common sentiment.

2 Likes

@annajiali Any ideas how long we’ll be waiting for a fix?

It is a hard project for me. I used many ideas from the solutions. But still having a problem after several hours of trying.

  1. line 13 and and 27, typeerror: cannot read properties of undefined (reading ‘0’) javascrip. How to fix it in my code?

Thank you for your help.

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

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

class Field {
  constructor(fieldArray) {
    this._fieldArray = fieldArray;
    this._currentLocationX = 0;
    this._currentLocationY = 0;
    this._fieldArray[this._currentLocationY][this._currentLocationX] = pathCharacter;

    } 
  print() {
     for (let i= 0; i < this._fieldArray.length; i++)
  console.log(this._fieldArray[i].join(""));
   }  

  runGame() {
    let playGame = true;
    while (playGame){
      this.print();
      console.log(`Please Enter " L, R, U, D" For Direction`);
      this.askQuestion();
      if (this._fieldArray[this._currentLocationY][this._currentLocationX] === hat) {
        console.log("Yeah! you find the hat!")
        playGame = false;
      } else if (this._fieldArray[this._currentLocationY][this._currentLocationX] === hole) {
        console.log("Nooo! you fall into a hole!")
        playGame = false;
      } else if ( this._currentLocationY < 0 || this._currentLocationX < 0 || this._currentLocationY > this._fieldArray.length || this._currentLocationX > this._fieldArray[0].length) {
        console.log("You can not go beyond boundary")
        playGame = false;
      } 
      this._fieldArray[this._currentLocationY][this._currentLocationX] = pathCharacter;
      
    }
  }

  

  askQuestion () {
    let userInput = prompt("Which Direction?").toUpperCase();
    if (userInput === 'L') {
      this._currentLocationX -= 1
    } else if (userInput === 'R') {
      this._currentLocationX += 1
    } else if (userInput === 'U') {
      this._currentLocationY -= 1
    } else if (userInput === 'D') {
      this._currentLocationY += 1
    } else {
      return `Please Enter " L, R, U, D"`
    } 
  }

  static generateField(height, width, percentageHole) {
    let totalarea = height*width;
    let numOfholes = Math.floor(totalarea*percentageHole);
    let countholes = 0;
    const field = new Array(height).fill(0).map(el=> new Array(width).fill('░'))
    while (countholes < numOfholes) {
      const holeY = Math.floor(Math.random()*height);
      const holeX = Math.floor(Math.random()*width);
      field[holeY][holeX] = 'O'
      countholes ++;
    }
    field[Math.floor(Math.random()*height)][Math.floor(Math.random()*width)] = '^';
    field[0][0] = '*';
    console.log(field);
  };


}



// const myfield = new Field(Field.generateField(5, 5, 0.2));
// const myField = new Field([
//     ['*', '░', 'O'],
//     ['░', 'O', '░'],
//     ['░', '^', '░'],
//   ]);

//   myField.runGame();

const randomField = Field.generateField(5,5,0.3);
// [
//   [ '*', '░', '░', '░', '░' ],
//   [ '░', '░', '░', 'O', '░' ],
//   [ 'O', 'O', 'O', '░', '░' ],
//   [ '░', 'O', '░', '░', 'O' ],
//   [ '^', '░', '░', '░', '░' ]
// ]
const newgame = new Field(randomField);
console.log(newgame);
// TypeError: Cannot read properties of undefined (reading '0')


I would like to help you, because I managed to finish this project, but could you mark on color which lines exactly throw errors? The lines in your code don’t have numbers, so I can’t read which line is 13 or 27.

Wow, it was challenging!, really cool, haha. It’s more code than the solution but it works as expected:
Used ES modules for readline instead.

1 Like

I ran into this TypeError a bit too during this challenge! I figured out it’s caused by trying to pass array[index] as a variable. The engine evaluates the index passed and passes its value on as the variable, rather than keeping array[index] as the value, which is what we want.

// Correct version
const myArray = [0, 1, 2, 3];
const i = 0;
myArray[i] = "Zero"; 
console.log(myArray[i]); // Prints "Zero"

// TypeError version:
const myArray = [0, 1, 2, 3];
const myIndex = myArray[0]; // Sets myIndex to 0
myIndex = "Zero" // Throws TypeError because the number 0 cannot be reassigned as a string

I had fun solving this project!

https://github.com/empowermint/codecademy/blob/main/findTheHatGame.js

Solution

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

const hat = '^';
const hole = 'O';
const fieldCharacter = '░';
const pathCharacter = '*';
let gameStatus = true;
const validMoves = ['U','D','L','R'];
let moveIsValid = true;


class Field {
// takes in single arg representing the field
  constructor(map){
    this._map = map;
    this._xPos = 0;
    this._yPos = 0;
    this._move = '';
  };

  print(){
  //prints map to terminal
    for (let i=0; i<this._map.length; i++){
      console.log(this._map[i].join(''))
    }
  };

  move(){
    //move left
    if (this._move === 'L'){
      this._xPos -= 1;
    }
    //move right
    if (this._move === 'R'){
      this._xPos += 1;
    }
    //move up
    if (this._move === 'U'){
      this._yPos -= 1;
    }
    //move down
    if (this._move === 'D'){
      this._yPos += 1;
    }
  };

  gameCheck(){
  //check if user has fallen into a hole or win
    if (this._map[this._yPos][this._xPos] === hole){
      console.log("You fell into a hole! You lost!");
      gameStatus = false;
    }
    else if(this._map[this._yPos][this._xPos] === hat){
      console.log("You found the hat! You Win!");
      gameStatus = false;
    }
    // // else if(this._yPos < this._map.length ||this._yPos > this._map.length || this._xPos < this._map[0].length || this._xPos > this._map[0].length){
    // //   console.log("You fell out of the map! you Lost!");
    // //   gameStatus = false;
    // }
  };

  mapUpdate(){
    this._map[this._yPos][this._xPos] = pathCharacter;
  };

  play(){
    this.print();
    do{      
      do{
        const selectMove = prompt("Which way? (U/L/D/R)").toUpperCase();
        if (validMoves.includes(selectMove)){
          this._move = selectMove;
          this.move();
          moveIsValid = false;
        } else{
          console.log('Invalid move')
          moveIsValid = true;
        }
      } while (moveIsValid)
      this.gameCheck();
      this.mapUpdate();
      this.print();
    }
    while (gameStatus)
      
  };
  generateField(height, width){
    //blank field canvas
    let genMap = []
    for (let i=0;i<height;i++){
      let genRow = new Array(width).fill(fieldCharacter);
      genMap.push(genRow);
    }
    //populate with holes, 1/4 of the map
    let holeNum = (height*width)/4;
    let holeCount = 0
    while(holeCount < holeNum){
      genMap[Math.floor(Math.random()*height)][Math.floor(Math.random()*width)] = hole;
      for(let i=0;i<height;i++){
        if (genMap[i].includes(hole)){
          holeCount += 1;
        }
      }
    }
    // add starting point
    genMap[this._yPos][this._xPos] = pathCharacter;
    // randomly place hat
    genMap[Math.floor(Math.random()*height)][Math.floor(Math.random()*width)] = hat;
    this._map = genMap
  };
  
}


//DEMO
const myField2 = new Field;
myField2.generateField(7,7);
myField2.play()

Still working on how to terminate the game if the player moves over the boundaries of the map. I made an attempt at line 57 of the gameCheck() method, but the game would immediately end when I make any valid move on the 1st step, saying I went out of bounds. I have an idea of further breaking it down into several ‘else if’ statements, but will work on that in the future. Map generation works, but came across a case where the hat is generated over the starting point.
Was a fun project, took me a few days. Will come back to it to work on the map validation method.

1 Like

Here’s my attempt, took me quite a long time but i’m proud to say i figured this out entirely on my own.

I don’t understand why everyone has such an issue with this project. All the tools needed, have been given already. It’s just the perception of this being different, that everyone is struggling with. Every concept and tool has been taught and certainly everyone should have the language required to search google for quick refreshers.

Hey you’re definitely getting somewhere!

I would like to say that you don’t necessarily need anything other than the field, in your constructor.

You could make a movement method, that when called on by your startGame method, would define your x and y axis.

Also you can end the program automatically, after a win or a loss, by using process.exit();

1 Like

Nicely done Meat! We’re quite similar in progress so if you’re ever looking for a partner, let me know :slight_smile:

hey,
sorry but the link got me to 404 page, maybe your repository is private?

1 Like

Ooops, thanks for letting me know. The code could be heavily condensed using export and import etc. The hard mode was retrofitted but the idea is there. Thanks for looking.

1 Like

This project took a lot of time compared to previous ones, but at the end of the day it was very satisfying.
Includes everything. Please feel free to comment. :smiley:

1 Like

Hi! Here’s my try on this project. Added several extra features: field size selection, difficulty selection.
This project was fun, thanks guys!

Continuing the discussion from Find Your Hat Challenge Project (JavaScript):

#Lavoro stimolante!

Ho terminato il progetto find your hat con qualche difficoltà e in maniera diversa dalla soluzione, ma sono contenta del risultato.

Ecco il risultato:

I totally understand the benefit of a “challenge”, but aiming too high, without building the skills progressively will only seed frustration.
There is a need for more practice exercises, build progressively… it will feel much better and be much more effective…
its the 1st time I have second thoughts about paying codecademy the pro fee.

2 Likes

This was fun! I’m going to figure out how to make this a webpage to add to my portfolio when I have more time!

I completely understand your frustration. This “90 minute” project took me days because I had to go research all of the things we didn’t actually cover leading up to this project. Codecademy definitely skipped some information. However, I learned so much from the process that I can’t be too mad.