Code Monkey home page Code Monkey logo

rock-papers-scissors's Introduction

Long Practice: Rock, Paper, Scissors Refactor

In this practice, you will be refactoring code to follow the Single Responsibility Principle and the DRY Principle. You will also practice reading test specs.

Set Up

Clone the practice from the starter.

Run npm install to install all dependencies.

Background and Context

You will be refactoring a working terminal game of the classic Rock, Paper, Scissors game.

In this game, you either pick either rock, paper or scissors while an AI opponent does the same. Then the choices are compared to determine the winner.

  • Rock beats scissors, loses to paper and ties with rock.
  • Paper beats rock, loses to scissors and ties with paper.
  • Scissors beats paper, loses to rock and ties with scissors.

To play the game, run node game.js in your terminal. Follow the intructions on the screen and input one letter commands and press enter to commit the command.

Play the terminal game a few times to see how it works and how the game state displayed gets updated based on wins, losses, and ties between you and the AI.

Now, take a look at the game.js file.

At the top of the file, you should notice the VALID_MOVES constant which is an object that contains nested objects. The nested objects contains information about each valid move in the game, rock, paper, and scissors.

Take a look at the next section that contains the data of the game state. Initially, the game state should note that there are zero wins, losses, and ties between the player and the AI.

Don't change the VALID_MOVES constant or the initial game state.

In the next section are helper functions that are not filled out yet. More on those later.

Next, there's the main function, promptInput(rl) that takes in a readline interface and will ask the player in the terminal to input commands. Based on those commands, the game state will change. Take a moment to read each line of code and figure out what each line is doing.

The final section contains code to initialize and start the game by printing the list of valid commands available to the player, creating a readline interface, and calling promptInput(rl) with the created interface.

The code is working and all the test specs for the promptInput(rl) main function should be passing. You can run the following command to make sure promptInput(rl) is working as intended:

npm test -- --bail test/promptInput-spec.js

Your task is to refactor the code in the main function, promptInput(rl), for readability and maintainability using DRY and SRP principles. The helper functions are skeletons to guide you in refactoring the code. They have been provided to you for this practice, but it will normally be up to you to use your experience and judgment to decide the best way to do this.

Follow the instructions to fill out the code in each helper function and refactor the promptInput(rl) main function.

Phase 1: printHelp()

In this phase, you will fill out the code in the printHelp() helper function and refactor the promtInput(rl) main function to use the printHelp() function.

Take a look at the test specs for the printHelp() function in test/phase-01-printHelp-spec.js. You can run the test specs in the file with the following command:

npm test test/phase-01-printHelp-spec.js

npm test is equivalent to running mocha, a testing framework for Node.js that you'll learn more about later this module. test/phase-01-printHelp-spec.js is the name of the test spec file that you want to run. (If you don't specify the file you wish to run, it will just run all the test specs in every file in the test folder.)

Can you guess what the test specs for printHelp() are testing for? Take at least 5 minutes to practice skimming and reading the test specs.

Don't peak below until you make an educated guess about what the test specs are testing for!

. . . . . . . . . .

printHelp()test specs:The function should print outputs in the following order:
"  Type 'r' for Rock"
"  Type 'p' for Paper"
"  Type 's' for Scissors"
"  Type 'q' to quit"
"  Type 'h' for a list of valid commands\n"

Now, make the test specs for the printHelp() helper function pass!

Once you pass the test specs, refactor the promptInput(rl) main function to use the printHelp() helper function. Which coding principles are you applying by refactoring the code this way?

Once you finish refactoring promptInput(rl), are there any patterns that could be DRYed up in the printHelp() helper function that you missed? Eliminate those patterns now!

Phase 2: getWinner(move1, move2)

In this phase, you will fill out the code in the getWinner(move1, move2) helper function and refactor the promtInput(rl) main function to use the getWinner(move1, move2) function.

Take a look at the test specs for the getWinner(move1, move2) function in test/phase-02-getWinner-spec.js. You can run the test specs in the file with the following command:

npm test test/phase-02-getWinner-spec.js

Can you guess what the test specs for getWinner(move1, move2) are testing for? Take at least 10 minutes to practice skimming and reading the test specs.

Don't peak below until you make an educated guess about what the test specs are testing for!

. . . . . . . . . .

getWinner(move1, move2)test specs:The function should return 1 if move1 beats move2. It should return -1 if move1 loses to move2. And finally, it should return 0 if move1 ties with move2. The move1 and move2 parameters should be valid move keys which are strings of `r`, `s`, or `p`.

Now, make the test specs for the getWinner(move1, move2) helper function pass!

Once you pass the test specs, refactor the promptInput(rl) main function to use the getWinner(move1, move2) helper function. Which coding principles are you applying by refactoring the code this way?

Once you finish refactoring promptInput(rl), are there any patterns that could be DRYed up in the getWinner(move1, move2) helper function that you missed? Eliminate those patterns now!

Phase 3: getCPUMove()

In this phase, you will fill out the code in the getCPUMove() helper function and refactor the promtInput(rl) main function to use the getCPUMove() function.

Take a look at the test specs for the getCPUMove() function in test/phase-03-getCPUMove-spec.js. You can run the test specs in the file with the following command:

npm test test/phase-03-getCPUMove-spec.js

Can you guess what the test specs for getCPUMove() are testing for? Take at least 10 minutes to practice skimming and reading the test specs.

Don't peak below until you make an educated guess about what the test specs are testing for!

. . . . . . . . . .

getCPUMove()test specs:The function should randomly return 'r', 's', or 'p'. 'r' should be returned at least once after multiple calls to the function. 's' should be returned at least once after multiple calls to the function. 'p' should be returned at least once after multiple calls to the function.

Now, make the test specs for the getCPUMove() helper function pass!

Once you pass the test specs, refactor the promptInput(rl) main function to use the getCPUMove() helper function. Which coding principles are you applying by refactoring the code this way?

Once you finish refactoring promptInput(rl), are there any patterns that could be DRYed up in the getCPUMove() helper function that you missed? Eliminate those patterns now!

Phase 4: processMove(cmd, cpu)

In this phase, you will fill out the code in the processMove(cmd, cpu) helper function and refactor the promtInput(rl) main function to use the processMove(cmd, cpu) function.

Take a look at the test specs for the processMove(cmd, cpu) function in test/phase-04-processMove-spec.js. You can run the test specs in the file with the following command:

npm test test/phase-04-processMove-spec.js

Can you guess what the test specs for processMove(cmd, cpu) are testing for? Take at least 10 minutes to practice skimming and reading the test specs.

Don't peak below until you make an educated guess about what the test specs are testing for!

. . . . . . . . . .

processMove(cmd, cpu)test specs:The function should print to the terminal the moves of the player and the CPU and an explanation of if the player beat, lost to, or tied with the CPU. Then:
  • If the cpu move is 'r', and the cmd move is 'r', then "You tie.\n" should be printed to the terminal.
  • If the cpu move is 'r', and the cmd move is 'p', then "You win!\n" should be printed to the terminal.
  • If the cpu move is 'r', and the cmd move is 's', then "You lose...\n" should be printed to the terminal.
  • If the cpu move is 'p', and the cmd move is 'r', then "You lose...\n" should be printed to the terminal.
  • If the cpu move is 'p', and the cmd move is 'p', then "You tie.\n" should be printed to the terminal.
  • If the cpu move is 'p', and the cmd move is 's', then "You win!\n" should be printed to the terminal.
  • If the cpu move is 's', and the cmd move is 'r', then "You win!\n" should be printed to the terminal.
  • If the cpu move is 's', and the cmd move is 'p', then "You lose...\n" should be printed to the terminal.
  • If the cpu move is 's', and the cmd move is 's', then "You tie.\n" should be printed to the terminal.

Now, make the test specs for the processMove(cmd, cpu) helper function pass!

Once you pass the test specs, refactor the promptInput(rl) main function to use the processMove(cmd, cpu) helper function. Which coding principles are you applying by refactoring the code this way?

Once you finish refactoring promptInput(rl), are there any patterns that could be DRYed up in the processMove(cmd, cpu) helper function that you missed? Eliminate those patterns now!

Hint:Are there any helper functions that you should use in processMove(cmd, cpu) instead of the promptInput(rl) main function?

Phase 5: Anything else?

Do you see in any of the helper functions, main function, or when initializing the game that can use refactoring?

Hint:Take a look at the section for initializing the game, is there any familiar code there that you can refactor using the printHelp() function?

Bonus Phase 6: Improve the Experience

Now you have refactored the code, see if you can improve the experience of the game for the player. Identifying which part of the code needs to be changed for a certain point of improvement should be easier now after the refactor!

rock-papers-scissors's People

Contributors

shahriyark avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.