Help needed on step 3 of Find your hat project in Full-Stack course. Updating array position using a function

Hey Forum,

I’m currently working through the “Find your Hat” Javascript project on the Full-Stack course. The aim of the project is to create an interactive terminal game. The scenario is that the player has lost their hat in a field full of holes, and they must navigate back to it without falling down one of the holes or stepping outside of the field. More details can be found here: [https://www.codecademy.com/paths/full-stack-engineer-career-path/tracks/fscp-javascript-syntax-part-iii/modules/fecp-challenge-project-find-your-hat/projects/find-your-hat]

An example of the game is below too.
Find Your Hat gameplay

My current code is below. I am having difficulty with understanding how to to update the current tile( this.current_position) as well as then updating the next tile selected when a user inputs “Up”, “Left”, “Down” or “Right”. I’ve tried to update the array in the “direction” function but i’ve been unable to log an updated field. Should these steps be built outside of the class? Any help on this would be greatly appreciated! Thank you! :slight_smile:

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

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


class Field {
    constructor(field_array) {
        this.field = field_array;
        this.x = 0;
        this.y = 0
        this.current_position = field_array[this.x][this.y];
    }

    get fieldArray () {
        return this.field;
    }

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

        
    }

    direction(step) {
        step = prompt('Which direction would you like to move in?');
        if ((step == 'r' && ((this.current_position == fieldCharacter)))) {
                this.current_position = pathCharacter;
                this.current_position = this.field[this.x + 1][this.y];
                this.field[x+1][y] = pathCharacter; 
                console.log(this.field);


                // this.current_position = "*";
                // this.current_position[index2] += 1;
           // this.current_position = this.new_field[index1][index2 + 1];
            
        } else if ((step == 'd' && ((this.current_position == fieldCharacter)))) {
            this.current_position = this.field[this.x][this.y += 1];
            this.current_position = '*';
            
        } else if (this.current_position == hole){
            console.log('Game over');
            process.exit;
        }
    }
}


const myField = new Field ([
    ['*', '░', 'O'],
    ['░', 'O', '░'],
    ['░', '^', '░'],
]);

myField.print();

console.log(myField.direction('r'));


follow the instructions in the project and a create getter and setter methods for the x and y . positions.

class Field {
 constructor(field_array) {
//this.ox , this.oy :- previous x and previous  y
      this.field = field_array;
        this.ox = this._x =  0;
        this.oy = this._y =  0;
        this.current_position = field_array[this.x][this.y];
    }

get y() {
        return this._y
    }
    get x() {
        return this._x
    }
    set x(v) {
        this.ox = this._x;
        this._x = v;
    }
    set y(v) {
        this.oy = this.y;
        this._y = v
    }
}
/* more methods*/

after you make this change you will see that updating the current tile is straightforward. I don’t think giving you the answer is appropriate because it will take the fun out of it :grinning:

@design1243427263 if you are still facing challenges you can give me a signal. I am ready to help. I still have my complete solution.

the essence of that project is to solidify your understanding of javascript classes and the importance of using getters and setters to keep internal state private. So circumventing that process is likely to make completing the project more difficult. Always remember that the course writers on codeacademy always have a course aim/purpose for each project.

don’t cut corners , follow the instructions.

Secondly, when thinking about movement the best way is to think in terms of vectors. This is the logic which mathematicians , physicists and engineers have used for centuries successfully.

consider the no movement to be the vector let [x,y]=[0,0];(base case);

direction(step) {
let [x,y]=[0,0];
//compute the necessary movement vector
        if (step === "l" || step === "L") {
            x--
        } else if (step === "r" || step === "R") {
            x++
        } else if (step === "d" || step === "D") {
            y++
        } else if (step === "u" || step === "U") {
            y--
        }

//take care  of cases where movement isn't possible because of the rules of the game
//return early here if the user violates any
/*    write your code here */

//if the user does not violate any rule 
//add your vector to the current position to get new position
        this.x += x;
        this.y += y

//update your field with the new position
this.field[this.x][this.y]=pathCharacter;
 console.log(this.field);
}

Hi @ [cloud3049056726],

Thank you very much for taking the time to look at my issue. I think i understand your guidance so i will go take a look at making the relevant changes and will post again if i come across any more issues. Currently moving the position is now ok so just need to include process for when user encounters a hole/hat as well as fix the newly generated field after each iteration of the direction function. Will let you know if any more issues. Thanks again!

1 Like

Hi there,

I’m working my way through the project but currently having issues with a couple of things below:

  1. Ending the game when the user passes the top or bottom of the grid. The horizontal axis is working.

This section here looks to being skipped and i can’t work out why:

            } else if ((this.x <= -1|| this.x >= 3)){
                console.log('End of game');
                gameStatus = 'Lost';
                return;
            }
  1. In the generateField static method, i can generate the random multistring but have been unable to use the join function previously used here:
print() {
        for (let i = 0; i < this.field.length; i++){
            console.log(this.field[i].join(""));

I’ve been looking into how split the string into 3 rows/columns (using another loop function) but have not been able to. Any clarification or guidance on these two points would be very helpful! Thank you

Full code here:

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

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


class Field {
    constructor(field_array) {
        this.field = field_array;
        this.ox = this._x = 0;
        this.oy = this._y = 0
        this.current_position = field_array[this.x][this.y];
    }

    get fieldArray () {
        return this.field;
    }

    get x () {
        return this._x;
    }

    set x(v) {
        this.ox = this._x;
        this._x = v;
    }
    get y () {
        return this._y;
    }

    set y(v) {
        this.oy = this._y;
        this._y = v;
    }

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

    direction(step) {
        while (gameStatus === '') {
            step = prompt('Which direction would you like to move in? ');
            let [x,y]=[0,0];
            if ((step === 'r' || step === 'R')){
                y++;
            } else if (step === 'd' || step ==='D'){
                x++;
            } else if (step === 'l' || step === 'L'){
                y--;
            } else if (step === 'u' || step === 'U'){
                x--;
            }
            this.x += x;
            this.y += y;
            console.log(this.x)
            if (this.field[this.x][this.y] === hat)  {
                console.log('You have won the game')
                gameStatus = 'Won';
                return;
            } else if (this.field[this.x][this.y] === hole) {
                console.log('End of game');
                gameStatus = 'Lost';
                return;
            } else if ((this.y >= 3 || this.y <= -1)){
                console.log('End of game');
                gameStatus = 'Lost';
                return;
            } else if ((this.x <= -1|| this.x >= 3)){
                console.log('End of game');
                gameStatus = 'Lost';
                return;
            }
            this.field[this.x][this.y] = pathCharacter;
            for (let i = 0; i < this.field.length; i++){
                console.log(this.field[i].join(""));}
            }
    }
    static generateField() {
      let new_field = [];
      const field_items = ['░', 'O', '^'];
      let counter = 0;
      for (let i = 0; i < 9; i++){
        let item = field_items[Math.floor(Math.random()*field_items.length)]
        if (item === '^'){
          counter++
        } if (counter > 1){
          item = '░';
        }
        new_field.push(item);
      }
      console.log(new_field.join(""));
     

              

            

    }
    
}

    // playGame() {
    //     while (gameStatus === '') {
    //         console.log('Hello')
    //     }
    //     // print();
    //     // direction();
    // }
    


const myField = new Field ([
    ['*', '░', '░'],
    ['O', '░', '░'],
    ['░', '^', '░'],
]);

myField.print();

myField.direction();

Field.generateField();

// myField.playGame();