石头剪刀布的更有效的选择比较

时间:2018-12-11 19:14:44

标签: javascript

这是一个正在进行的学校项目,我想改进。关键是使代码尽可能高效(或简短)。在比较计算机的选择和用户的选择时,我想通过找到所有其他if的替代方法来减少它。

代码如下:

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's 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语句,但是由于我们仍然是初学者,所以我还没有完全掌握该主题。任何帮助表示赞赏。

6 个答案:

答案 0 :(得分:26)

您可以定义一个对象,该对象定义您的移动相对于其他移动是弱还是强。示例:

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

答案 1 :(得分:3)

您还可以使用数组检查获胜者。订购阵列,使获胜者始终在右侧。然后比较机器的选择是否是用户选择的选择,如下所示:

.g-recaptcha{
   transform:scale(0.8);
   -webkit-transform:scale(0.8);
   transform-origin:0 0;
   -webkit-transform-origin:0 0;
}

一个fiddle一起玩。

取模运算符在数组末尾产生魔力。如果用户选择了“ rock”,则下一个将是未定义的,但是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);的模运算符返回0,因此将“ paper”与“ rock”进行比较。

答案 2 :(得分:1)

我删除了一些变量并将它们组合在一起,只是为了使其更短。我也摆脱了if/else的大部分内容,因为这里并不需要它。有关switch的工作方式的更多信息,请查看https://javascript.info/switch

我还更改了您的选择,以便您可以为每个选择添加多个获胜或失败条件,以防您想升级到Rock,Paper,Scissors,Lizard,Spock(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's 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 + "." ;
    }
}

注意::我也在constlet之间切换。有关差异,请参见https://codeburst.io/part-2-var-vs-const-vs-let-69ea73fe76c1。我主要使用const表示我不会更改的变量,而let则是我可以更改的变量(在其适当范围内)。还有var,但我在这里不需要。

答案 3 :(得分:0)

Switch语句就是这样。 尝试看看例如我给您的内容,并尝试了解代码的流程。

最好的学习方法就是用手! 随机开关,例如:

   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's 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 :(得分:0)

晚会很晚,但这与这里的其他答案略有不同。我已经在TypeScript中包含了答案,但是如果愿意,您显然可以删除类型。

type Weapon = "Rock" | "Paper" | "Scissors";
type Result = "Player" | "Computer" | "Draw";
type GameLogic = Record<Weapon, Array<Weapon>>;

// Map that tracks what each weapon beats.
const outcomes: GameLogic = {
  Rock: ["Scissors"],
  Paper: ["Rock"],
  Scissors: ["Paper"]
};

const determineWinner = (playerOneWeapon: Weapon, playerTwoWeapon: Weapon): Result => {
  if (playerOneWeapon === playerTwoWeapon) {
    return "Draw";
  }

  return outcomes[playerOneWeapon].includes(playerTwoWeapon)
    ? "Player One"
    : "Player Two";
}

此实现也可以很好地扩展。您可以在混合中添加其他武器,并且determineWinner的实现不会改变-通过添加Weapon类型和outcomes映射:

type Weapon = "Rock" | "Paper" | "Scissors" | "Lizard" | "Spock";
const outcomes: GameLogic = {
  Rock: ["Scissors", "Lizard"],
  Paper: ["Rock", "Spock"],
  Scissors: ["Paper", "Lizard"],
  Lizard: ["Spock", "Paper"],
  Spock: ["Rock", "Scissors"]
};

我们现在可以支持一个游戏,其中每把武器击败每把武器两次,而每把武器输掉一次,武器正好两次(这与经典的变体相反,凡事都会击败一个武器而输给一个武器)。

答案 5 :(得分:-1)

由于已经提供了更多简单明了的答案,因此我为您编写了使用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's 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's a tie! Try again to win"
}

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