Skip to main content

Part 3: Implementing the Game Logic

The Resources folder structure should look something like this.

  resources
β”œβ”€β”€ images
β”‚ └── .gitkeep
β”œβ”€β”€ scripts
++β”‚ β”œβ”€β”€ rock_paper_scissors.js
β”‚ └── index.js
└── styles
└── styles.css

The marked file is the file you'll be using in the part of the assignment.

SOLID is a mnemonic acronym for five design principles intended to make software designs more understandable, flexible, and maintainable. It stands for:

  • Single responsibility
  • Open–closed
  • Liskov substitution
  • Interface segregation
  • Dependency inversion

In this exercise, we will introduce the first principle which states that "every class should have only one responsibility". We will do this by separating the code that controls the game logic from the code that controls and manipulates the DOM.

In the scripts/rock_paper_scissors.js, we will make a RockPaperScissors class that will contain all "logic" for the game (properties and methods). and in the scripts/index.js file, we will handle the user input and call methods from the RockPaperScissors class as needed.

This file, we will use JavaScript Classes.

RockPaperScissors Class​

The class will include a few properties:

  • username
  • score: {user: 0, cpu: 0}
  • gameHistoryLog: []

This class will only contain 4 methods:

  1. constructor(username)
  2. generateCPUResponse()
  3. determineWinner(userSelection, cpuSelection)
  4. play(userSelection)
class RockPaperScissors {
constructor(username) {
...
}

generateCPUResponse() {
...
}

determineWinner(userSelection, cpuSelection){
...
}

play(userSelection) {
...
}
}

Let's start with one function at a time...

constructor(username)​

This function will take in the username as a parameter and set it as a property to the class. In the constructor, we will also defined all our variables and set them to some initial values/

class RockPaperScissors {
constructor(username) {
this.username = username;
this.score = {
user: 0,
cpu:0
},
this.gameHistoryLog = [];
}
...
}

Note:​

  • class property are declared with the this keyword.

generateCPUResponse()​

For this function:

  1. Create an array with the following values
const acceptedValues = [ `rock`, `paper`, `scissors` ]
  1. Using both Math.random and Math.floor() methods, generate a random index number (0,1,2)
  2. return the value of acceptedValue at the random index generated in the previous step.

determineWinner(userSelection, cpuSelection)​

This function will take 2 parameters userSelection and cpuSelection and will return one of the following values (win, lose, tie).

  • it would return (tie) if the user selection is the same as the cpu random selection.
  • it would return (win) if:
    • user selection is rock and cpu selection is scissors
    • OR
    • user selection is paper and cpu selection is rock
    • OR
    • user selection is scissors and cpu selection is paper
  • it would return (lose) in any other case.

play(userSelection)​

This method takes in 1 parameter: the userSelection. It will:

  • Get the CPU Random selection using the generateCPUResponse()
  • Determine the winner using the determineWinner(userSelection, cpuSelection)
  • update the score tally this.score
        // if the user won the round
    this.score.user ++;
    // if the user cpu the round
    this.score.cpu ++;
    OR
        this.score = {
    user: NEW_SCORE,
    cpu: NEW_SCORE
    }
  • Add another historyLog entry to the game history array.
    • the log entry should look something like this Yahya selected Scissors, CPU selected Paper: Yahya wins wins
    this.gameHistoryLog.push(`Yahya selected Scissors, CPU selected Paper: Yahya wins wins`);

Result​

Running the unit tests should pass

initial look

Testing​

  • Run the tests with npm run test:logic. This will run the Unit tests for the logic component only of this assignment.