问题
Below is my JS file for a rock, paper, scissors game activity we had to do in my web development class. I was able to get everything to work, however I do not like how long my if-else statements made my code and was wondering how can I make this more concise and have it in less lines of code.
const imagePath=[];
imagePath.push("img/paper.png");
imagePath.push("img/rock.png");
imagePath.push("img/scissors.png");
let counter=1;
let counter2=1;
let images=document.querySelector("#player");
let images2=document.querySelector("#computer");
function ImageChange()
{
images.src=imagePath[counter];
counter++;
if (counter == imagePath.length)
{
counter=0;
}
images2.src=imagePath[counter2];
counter2++;
if (counter2 == imagePath.length)
{
counter2=0;
}
}
let intervalObject=setInterval(ImageChange,500);
const playButton=document.querySelector("#play");
const div= document.querySelector("#message");
playButton.addEventListener("click",function(){
clearInterval(intervalObject);
let randomIndex=Math.floor(Math.random()*imagePath.length);
images.src=imagePath[randomIndex];
let randomIndex2=Math.floor(Math.random()*imagePath.length);
images2.src=imagePath[randomIndex2];
//paper=0,rock=1,scissors=2
if(randomIndex==randomIndex2)
{
div.innerHTML="<h1>Tie!</h1>";
}
else if(randomIndex==0)
{
if(randomIndex2==1)
{
div.innerHTML="<h1>Player Wins</h1>";
}
else
{
div.innerHTML="<h1>Computer Wins</h1>";
}
}
else if(randomIndex==1)
{
if(randomIndex2==2)
{
div.innerHTML="<h1>Player Wins</h1>";
}
else
{
div.innerHTML="<h1>Computer Wins</h1>";
}
}
else if(randomIndex==2)
{
if(randomIndex2==0)
{
div.innerHTML="<h1>Player Wins</h1>";
}
else
{
div.innerHTML="<h1>Computer Wins</h1>";
}
}
});
Like I said everything works and I have my html/css files. However, my concern is just with the if statements I have. Is there a better way I can write them?
回答1:
I'd think something more like this would save you a lot of lines of code:
if(randomIndex==randomIndex2) {
div.innerHTML="<h1>Tie!</h1>";
}
else {
var playerWins = (randomIndex==0 && randomIndex2==1) || (randomIndex==1 && randomIndex2==2) || (randomIndex==2 && randomIndex2==0)
div.innerHTML = playerWins ? "<h1>Player Wins</h1>" : "<h1>Computer Wins</h1>"
}
Edit: (Here's a quick rewrite using the mod (%) suggestion below, see Megaptera novaeangliae)
const imagePath = ["img/paper.png", "img/rock.png", "img/scissors.png"];
const playButton = document.querySelector("#play");
const playerImage = document.querySelector("#player");
const computerImage = document.querySelector("#computer");
const div = document.querySelector("#message");
let computerChoice, playerChoice;
function randomChoice() {
return Math.floor(Math.random() * imagePath.length);
}
function randomize() {
playerChoice = randomChoice();
computerChoice = randomChoice();
playerImage.src = imagePath[playerChoice];
computerImage.src = imagePath[computerChoice];
}
let intervalObject = setTimeout(randomize, 500);
playButton.addEventListener("click", function() {
clearInterval(intervalObject);
// paper=0, rock=1, scissors=2
if (playerChoice == computerChoice) {
div.innerHTML = "<h1>Tie!</h1>";
} else if (playerChoice == (computerChoice + 1) % imagePath.length) {
div.innerHTML = "<h1>Player Wins</h1>";
} else {
div.innerHTML = "<h1>Computer Wins</h1>";
}
});
回答2:
This might be a personal preference, but I find things much neater when there is space between operators and operands. And I also properly despise the
else
{
...
}
Formatting scheme. I would recommend, for neatness purposes, use
else {
...
}
Most people will also tell you not to, but I find it helps with neatness further: on single statement conditions or clauses, you can omit braces.
else
console.log("Else Clause")
console.log("Outside of Else");
I would also suggest using switch statements as these make code far more readable, although they have their own quirks, they are fantastic for making code readable. Further, I would also suggest to avoid one-liners. I fell into that habit for a while and it hit me hard. You haven't really done that in this case, but I'm just adding it for future references.
Another thing you might find useful is grouping variables of similar usage/purpose. So don't put newlines between them.
Again, another personal preference is using 4-space indentation. Makes it more visible where the indents start and end.
So in summary:
- Leave enough space between tokens
- Place braces on the same line
- Blocks (Except
try
/catch
) with only one statement can omit their braces - Use a
switch
statement - Group variables
- Use four spaces (spaces, not tabs)
Hope that helps
回答3:
To put the entire game logic into a simple script:
Rock, Paper, Scissors to indexes: 0, 1, 2
result = PL === AI ? 2 : (AI + 1) % 3 === PL ? 0 : 1;
// | | |
// 0 = PL wins --------------------------------┘ |
// 1 = AI wins ------------------------------------┘
// 2 = draw ------┘
Having those three indexes in place you can now easily retrieve the respective played figure-names and the needed won/draw message from Arrays:
// RPS // 0=PLwon 1=AIwon 2=Draw!
const RPS = (PL, AI) => PL === AI ? 2 : (AI + 1) % 3 === PL ? 0 : 1;
const msg = ["Player won", "AI won", "Draw!"];
const fig = ["Rock", "Paper", "Scissors"];
// Example Demo:
const rnd = n => ~~(Math.random() * n);
const pl = rnd(3);
const ai = rnd(3);
const result = RPS(pl, ai);
console.log(`PL:${fig[pl]} AI:${fig[ai]} - ${msg[result]}`);
Dive deeper into the logic, see this answers:
- js-rock-paper-scissors
- how-do-i-make-a-function-that-reset-the-game-on-click
来源:https://stackoverflow.com/questions/58924599/how-can-i-write-a-neater-set-of-code-for-my-rock-paper-scissors-game