Более эффективное сравнение выбора для Rock Paper Scissors

Это постоянный школьный проект, который я хотел бы улучшить. Дело в том, чтобы сделать код максимально эффективным (или коротким). Я хотел бы уменьшить его, найдя альтернативу всем остальным операциям, сравнивая выбор компьютера с выбором пользователя.

Вот код:

let weapons = ["Rock", "Paper", "Scissors"];
let random = Math.floor(Math.random()*3);
let chosenOne = weapons[random];

let rps = prompt("Welcome to Rock, Paper, Scissors. Would you like to play?" 
+ '\n' + "If you do, enter number 1." + '\n' + "If you don't, enter number 
2.");

if (rps === "1") {
    alert("Remember:" + '\n' + " - Rock beats the scissors" + '\n' + " - 
    Paper beats the rock" + '\n' + " - The scissors cut the paper");

let weapon = prompt("Make your choice:" + '\n' + "Rock, Paper, Scissors");
    weapon = weapon.charAt(0).toUpperCase() + weapon.slice(1).toLowerCase();
    alert("You chose: " + weapon + '\n' + "The computer chose: " + 
    chosenOne);
if (weapon === chosenOne) {
        alert("It a tie! Try again to win!");
    } else if (weapon === "Rock" && chosenOne === "Paper") {
        alert("You lost! Paper beats the rock.");
    } else if (weapon === "Paper" && chosenOne === "Scissors") {
        alert("You lost! The scissors cut the paper.");
    } else if (weapon === "Scissors" && chosenOne === "Rock") {
        alert("You lost! The rock beats the scissors.");
    } else if (weapon === "Scissors" && chosenOne === "Paper") {
        alert("You won! Scissors cut the paper.");
    } else if (weapon === "Paper" && chosenOne === "Rock") {
        alert("You won! Paper beats the rock.");
    } else if (weapon === "Rock" && chosenOne === "Scissors") {
        alert("You won! The rock beats the scissors.");
    }
} else if (rps === "2") {
    alert("Thanks for visiting! See you later.");
} else if (rps !== "1" || rps !== "2") {
    alert("Invalid option. Closing game.");
}

Я думал об использовании операторов switch, но так как мы все еще новички, я не полностью понял предмет. Любая помощь приветствуется.

Ответ 1

Вы можете определить объект, который определяет, является ли ваш ход слабым или сильным по отношению к другому. Пример:

const myChoice = 'Rock'
const enemyChoice = 'Scissors' 

const weapons = {
   Rock: {weakTo: 'Paper', strongTo: 'Scissors'},
   Paper: {weakTo: 'Scissors', strongTo: 'Rock'},
   Scissors: {weakTo: 'Rock', strongTo: 'Paper'}
}

if (weapons[myChoice].strongTo === enemyChoice) {
    // I won
    return;
}

if (weapons[myChoice].weakTo === enemyChoice) {
    // I Lost
    return;
}

// tie

Ответ 2

Вы также можете использовать массив для проверки победителя. Расположите массив так, чтобы победитель всегда был справа. Затем сравните, является ли выбор машины рядом с выбором пользователя, например, так:

var weapons = ['paper', 'scissors', 'rock'],
  user = 'scissors',
  machine = 'paper',
  uIdx = weapons.indexOf(user),
  mIdx = weapons.indexOf(machine),
  winner;
if (uIdx !== mIdx) {
  winner = (mIdx === (uIdx + 1) % 3) ? 'machine' : 'user';
} else {
  winner = 'tie';
}

console.log(winner);

Ответ 3

Переключатель заявления идет так. Попробуйте взглянуть на пример, который я вам дал, и попытаться понять поток кода.

Лучший способ учиться своими руками! Случайное переключение, например:

   switch(expression) {
   case x:
    code block
    break; // after every statement e.g: (console.log) you need to use 
   "break"
    case y:
    code block
    break;
    default:
    code block

}

Ваш код:

switch (weapon) {
 case chosenOne:
    return console.log(alert("It a tie! Try again to win!"));
    break;
 case "Rock":
 case "Paper":
 alert("You lost! Paper beats the rock.");
   break;
  case "Paper":
 case "Scissors":    
  console.log(alert("You lost! The scissors cut the paper."))
   break;
  case "Scissors":
 case "Rock": 
console.log(alert("You lost! The rock beats the scissors."))
break;
case "Scissors":
   case "Paper" :
    alert("You won! Scissors cut the paper.");
  break;
case "Paper":
case "Rock":
    console.log(alert("You won! Paper beats the rock."))
   break;
  case "Rock": 
  case "Scissors": 
        alert("You won! The rock beats the scissors.");
    default:
   return "somthing went wrong"
      break;

Ответ 4

Я удалил некоторые из ваших переменных и соединил некоторые, просто чтобы сделать его короче. Я также избавился от большей части if/else поскольку он здесь не очень нужен. Для получения дополнительной информации о том, как работает switch, проверьте https://javascript.info/switch.

Я также изменил ваш выбор, чтобы вы могли добавить несколько условий выигрыша или проигрыша для каждого варианта на случай, если вы захотите перейти на Рок, Бумага, Ножницы, Ящерица, Спок (https://www.youtube.com/watch?v). = cSLeBKT7-s).

// Set up our various choices, how they rank, and their action (can also be array if desired).
const choices = {
    Rock     : { win:["Scissors"]        , action:"beats" } ,
    Paper    : { win:["Rock"]            , action:"beats"  } ,
    Scissors : { win:["Paper"]           , action:"cuts" } ,
    Spock    : { win:["Rock","Scissors"] , action:"beats" }
} ;

// Use the keys in choices as our selectable items.
const weapons = Object.keys(choices) ;

// Our basic intro.
const rps = prompt("Welcome to Rock, Paper, Scissors. Would you like to play?" + '\n' + "If you do, enter number 1." + '\n' + "If you don't, enter number 2.");

// Set the computer choice.
const chosenOne = weapons[Math.floor(Math.random()*3)];

// This is an example of your switch.
switch (rps) {
  case "1" : // Since we used text input, we have to evaluate for a text "number".
      alert("Remember:" + '\n' + " - Rock beats the scissors" + '\n' + " - Paper beats the rock" + '\n' + " - The scissors cut the paper");

     // Make your choice.
     let weapon = prompt("Make your choice:" + '\n' + weapons, "");
     // Is our choice valid?
     if ( !weapons.includes(weapon) ) { 
         alert("Invalid choice. Closing Game."); break; 
     } else {
         alert("You chose: " + weapon + '\n' + "The computer chose: " + chosenOne);
     }
     // Did I win?
     alert( compareRPS(weapon,chosenOne) ) ;     
  break ; // This will break out of the switch. Otherwise will fall through to next case.

  case "2":    
    alert("Thanks for visiting! See you later.");
  break ;

  default :
    alert("Invalid option. Closing game.");       
  // No break needed here since this is the end of the switch.
}

// I broke the check-you-vs-cpu functionality out into its own function.
function compareRPS(youC,cpuC) {
    if ( youC === cpuC ) {
      return "It a tie! Try again to win." ;
    }
    if (choices[youC].win.includes(cpuC)) {
      return "You won! " + youC + " " + choices[youC].action + " " + cpuC + "." ;
    } else {
      return "You lost! " + cpuC + " " + choices[cpuC].action + " " + youC + "." ;
    }
}

ПРИМЕЧАНИЕ: я также переключаюсь между const и let. См. Https://codeburst.io/part-2-var-vs-const-vs-let-69ea73fe76c1 для различий. Я в основном использую const чтобы указать переменную, которую я не буду изменять, и let быть той, которую я могу (в пределах своей надлежащей области видимости). Там тоже var, но мне это здесь не нужно.

Ответ 5

Поскольку более точные ответы уже были предоставлены, я написал вам альтернативу, используя более продвинутые функции javascript. Эти функции являются избыточным решением для рассматриваемой проблемы, но полезны в качестве учебного упражнения.

// Create an array 'battle' as a result from mapping over the given options

const battle = ["Rock", "Paper", "Scissors"].map(
/* The resulting array is conformed of tuples (arrays of 2 values).
 The first value is the weapon of choice and the second value is a function.
 That function will receive as an argument another weapon and will return the outcome of battling the first option with the second.
 Positive number is win, 0 is tie and negative number is loose. */
  (weapon, index, array) => [weapon, enemy => {
    const res = index - array.findIndex(x => x === enemy)
    return !!(res%2)? res : res * -1
  }]
/* The reduce transform the array of tuples into an object,
 with each choice as a property key and each function as the property value */
).reduce((accumulator, current) => {accumulator[current[0]] = current[1]; return accumulator}, {})

/* Output is just a function that receives your weapon.
  It returns a function that receives your enemy weapon.
  Which in turn uses the previous object with functions to get the result.
  Finally it uses the result to print one sentence or other, using template strings. */

const output = mine => enemy => {
  const result = battle[mine](enemy)
  return result > 0 ? 'You won! ${mine} beats ${enemy}'
  : result < 0 ? 'You lost! ${enemy} beats ${mine}'
    : "It a tie! Try again to win"
}

console.log(output("Rock")("Paper"))