Javascript - Math.random函数在for循环中调用时返回相同的结果

问题描述 投票:1回答:3

我有一个function{computerPlay()}每次调用时都会生成一个新的随机数。它返回顶部声明的数组中的项。当我在console中测试它时,它的工作原理我喜欢它。但是,为了让我的游戏正常工作,我把它放在一个for循环中,它会保持返回相同的值,除非我刷新页面。我无法在任何地方找到答案,这是我的第一个问题。我确定代码很草率所以请忽略它。这是代码。

  let playOptionsArray = ["Rock", "Paper", "Scissors"];
let totalTies = 0;
let playerPoints = 0;
let computerPoints = 0;
let round = 1;

//formats a player's entry so it will match playOptionsArray
  function firstLetterUppercase(string){
    let firstLetter = string.charAt(0);
    let firstLetterCapitalized = firstLetter.toUpperCase();
    let restOfResponse = string.slice(1);
    let formattedResponse = firstLetterCapitalized + restOfResponse;
    return formattedResponse;
  }

//compares player entry to ensure it matches an item on the playOptions array
  function checkPlayerResponse(response){
    if (response === "Rock" || response === "Paper" || response === "Scissors") {
      return response;
    } else {
      return alert("You must choose either 'Rock', 'Paper', or 'Scissor' as your play. Please try again.");
    }
  }

//generates a random option for the computer's play

  function computerPlay() {
    let computerSelection = playOptionsArray[Math.floor(Math.random()*(playOptionsArray.length))];
    return computerSelection;
  }

  let computerSelection = computerPlay();

  function getPlayerSelection() {
    let playerEntry = window.prompt("You are playing the computer in a game of Rock, Paper, Scissors. First player to five points wins. Choose either Rock, Paper, or Scissors as your play", "Rock");
    if (playerEntry != null) {
    let playerEntryLowercase = playerEntry.toLowerCase();
    playerSelection = firstLetterUppercase(playerEntryLowercase);
  } else {
    getPlayerSelection();
  }
    checkPlayerResponse(playerSelection);
    return playerSelection;
  }

  let playerSelection = getPlayerSelection;

//emulates a single round of rock paper scissor
  function singleRound(){
    if (playerSelection === "Rock" && computerSelection === "Scissors"){
      alert('You have won this round. The computer chose ' + computerSelection + '.');
      playerPoints++;
      round++;
    } else if (playerSelection === "Scissors" && computerSelection === "Paper"){
      alert('You have won this round. The computer chose ' + computerSelection + '.');
      playerPoints++;
      round++
    } else if (playerSelection === "Paper" && computerSelection === "Rock"){
      alert('You have won this round. The computer chose ' + computerSelection + '.');
      playerPoints++;
      round++
    } else if (playerSelection === computerSelection){
      alert('You have tied this round. The computer chose ' + computerSelection + '.');
      totalTies++;
    } else {
      alert('Something went wrong. Refresh the page.')
    }
  }

  function updateScore() {
    document.getElementById("player-points").innerHTML = playerPoints;
    document.getElementById("round").innerHTML = round;
    document.getElementById("computer-points").innerHTML = computerPoints;
    document.getElementById("total-ties").innerHTML = totalTies;
  }

//keeps track of player points and ends when a player gets 5 points
 function game() {
    for (round = 0; computerPoints < 5 && playerPoints < 5; round) {
      getPlayerSelection();
      computerPlay();
      singleRound();
      updateScore();
      }
  }

game();
javascript loops for-loop
3个回答
0
投票

您从computerPlay返回的值不会存储在循环中的任何位置。 (应该注意到你的playerSelection也会发生这种情况)。尝试

for (round = 0; computerPoints < 5 && playerPoints < 5; round) {
  playerSelection = getPlayerSelection();
  computerSelection = computerPlay();
  singleRound();
  updateScore();
}

编辑:@ kavakava的回答提供了一些有关为什么会这种情况的见解。


1
投票

你的问题是两个众所周知的错误来源的组合:variable shadowingglobal state

在JavaScript中,每个函数都创建一个新范围:

var foo = 3;
function() { var bar = 2; };
console.log(foo + bar); // ERROR, bar is local to the function

内部范围可以从外部访问东西(你仍然可以在函数内部看到foo),但不是相反。当您在内部作用域中声明与外部相同的名称时,会发生阴影:

var foo = 3;
(function() {
  var foo = 2;
  console.log(foo); // 2
})();
console.log(foo); // 3 the outer foo isn't change by the inner.

如果省略声明(即var,let,const),程序将在范围内搜索以查找它:

var foo = 3;
(function() {
  foo = 2; // will reach up to the outer foo
})();
console.log(foo); // 2

如果您没有以这种方式混合范围,则不会出现此问题。解决问题的最简单方法是防止它发生。修改你的singleRound函数,取两个参数:

function singleRound(computerSelection, playerSelection) {
  // everything else the same
}

现在当你在循环中调用它时:

singleRound(computerPlay(), getPlayerSelection());

当您使用返回值时,您不会轻易出错。


0
投票
function computerPlay() {
    let computerSelection = playOptionsArray[
            Math.floor(Math.random()*(playOptionsArray.length))
         ]; // Line #1

     return computerSelection;
}

let computerSelection = computerPlay(); // Line: #2

这似乎是你的问题。它永远不会改变的原因是因为你从未改变它。删除第1行上的'let',你应该全部设置好。你在computerPlay中返回var,而不是全局。

© www.soinside.com 2019 - 2024. All rights reserved.