I'm currently going through The Odin Project, in an attempt to learn some Javascript. I'm a junior in a CS program, and I realize that I am not very good at programming, but I want to change that.
I made a very simple rock-paper-scissors implementation with JS and HTML. I plan on adding CSS later and making it not look horribly ugly, but for the time being I am only concerned with the Javascript.
There are a few things that I am not happy with in my code, that I couldn't really figure out how to improve. One of them being the win checking; I essentially used 9 if statements for all the possible outcomes, and its very inelegant. Another thing I am not a fan of is my usage of global variables for the round results. I have been told often to avoid using global vartiables when possible. Another thing is the implementation of the eventlisteners. I wanted to just directly use the playRound()
function on click, but I couldn't figure out how to pass in the computerPlayer()
result as a parameter.
Here is the HTML:
<body>
<h1>Rock Paper Scissors</h1>
<div id="button-container">
<button id="rock">Rock</button>
<button id="paper">Paper</button>
<button id="scissors">Scissors</button>
</div>
<div id="results">
<p id="player-score">Your score is: 0</p>
<p id="computer-score">The computer score is: 0</p>
<p id="result-tie">Tie rounds: 0</p>
</div>
<script src="script.js"></script>
</body>
And here is the Javascript:
// Accessing the buttons and text labels
const rockButton = document.getElementById("rock");
const paperButton = document.querySelector("#paper");
const scissorsButton = document.querySelector("#scissors");
const playerScore = document.getElementById("player-score");
const computerScore = document.getElementById("computer-score");
const tieText = document.getElementById("result-tie");
// Global variables to keep track of round results that I am not a fan of
let computerWinAmount = 0;
let playerWinAmount = 0;
let tieAmount = 0;
//Event listeners to monitor button press and assign
//corresponding choice
rockButton.addEventListener("click", function(){
let playerSelection = "rock";
let computerSelection = computerPlay();
playRound(playerSelection,computerSelection);
});
paperButton.addEventListener("click", function() {
let playerSelection = "paper";
let computerSelection = computerPlay();
playRound(playerSelection, computerSelection);
});
scissorsButton.addEventListener("click", function() {
let playerSelection = "scissors";
let computerSelection = computerPlay();
playRound(playerSelection, computerSelection);
});
// Function that pseudo-randomly generates a computer selection
function computerPlay() {
// Uses Math.random() to generate a number between 0-2
let choice = Math.floor(Math.random() * 3);
// Reassigns string value depending on which number
switch(choice) {
case 0:
choice = "rock";
break;
case 1:
choice = "paper";
break;
case 2:
choice = "scissors";
break;
}
return choice;
}
// Group of functions to change text labels after rounds
function playerWin() {
++playerWinAmount;
playerScore.innerHTML = "Your score is: " + playerWinAmount;
}
function computerWin() {
++computerWinAmount;
computerScore.innerHTML = "The computer score is: " + computerWinAmount;
}
function tieWin() {
++tieAmount;
tieText.innerHTML = "Tie rounds: " + tieAmount;
}
// Function that checks winning very inelegantly
function playRound(playerSelection, computerSelection) {
if (playerSelection == "rock" &&
computerSelection == "rock") {
tieWin();
} else if (playerSelection == "rock" &&
computerSelection == "scissors") {
playerWin();
} else if (playerSelection == "rock" &&
computerSelection == "paper") {
computerWin();
}
if (playerSelection == "paper" &&
computerSelection == "rock") {
playerWin();
} else if (playerSelection == "paper" &&
computerSelection == "paper") {
tieWin();
} else if (playerSelection == "paper" &&
computerSelection == "scissors") {
computerWin();
}
if(playerSelection == "scissors" &&
computerSelection == "rock") {
computerWin();
} else if (playerSelection == "scissors" &&
computerSelection == "paper") {
playerWin();
} else if (playerSelection == "scissors" &&
computerSelection == "scissors") {
tieWin();
}
if(computerWinAmount == 5) {
alert("You lost! Better luck next time :(");
reset();
} else if (playerWinAmount == 5) {
alert("You won! Congratulations! :)")
reset();
}
}
// Helper function to reset after game end
function reset() {
playerScore.innerHTML = "Your score is: 0";
computerScore.innerHTML = "The computer score is: 0";
tieText.innerHTML = "Tie rounds: 0";
}
```
playRound
, etc. are also in global scope. Wrap the entire JS program inside a function, sayRockAroundTheClock
. This function must be executed to instantiate all the variables, functions, etc. A technique for doing this is called IIFE - Immediately Invoked Function Expression. GoogleIt. This is rare in code examples one comes across. This is because we get lucky and don't have some other code stomping on our variable names at run time. I've had that happen. It's not fun. \$\endgroup\$eventHandler
function is needed. \$\endgroup\$aFunction( computerPlayer() )
passes its return value;aFunction( computerPlayer )
passes the function itself. \$\endgroup\$