简体   繁体   English

我在哪里失去随机性?

[英]Where am I losing randomness?

So I'm building a rock, paper, scissors game. 因此,我正在构建一个石头,纸,剪刀的游戏。 I want to get math.random() to give me a random result that I compare to the one chosen by the user. 我想获得math.random()来给我一个随机的结果,并将其与用户选择的结果进行比较。

It mostly works. 它主要工作。 I even thought it fully worked for a while, but I'm losing randomness at some point. 我什至以为它可以完全工作一段时间,但是在某些时候我正在失去随机性。

To try it, I input a fixed "user" choice and ran the code a few hundred times with setInterval(myfunction, 20). 为了进行尝试,我输入了一个固定的“用户”选项,并使用setInterval(myfunction,20)将代码运行了数百次。 They're always lopsided victories, and always with the same outcome: 他们总是取得不平衡的胜利,并且总是有相同的结果:

If I run it with playerPick = 1, the computer always wins. 如果我使用playerPick = 1来运行它,则计算机将始终获胜。

If I run it with playerPick = 2 or 3, the user always wins. 如果我使用playerPick = 2或3运行它,则用户总是获胜。

Can anyone see where I goofed? 谁能看到我发呆的地方?

//Global variable and constants.

const ROCK = 1;
const PAPER = 2;
const SCISSORS = 3;

//This is the game.

function whoWins(){
    const playerPick = 2; //for debugging, it can be 1, 2, or 3.
    const computer = computerPick();
    if (playerPick == computer){
        return draw();
    } else if (playerPick == 1 && computer == 2){
        return lose();
    } else if (playerPick == 2 && computer == 3){
        return lose();
    } else if (playerPick == 3 && computer == 1){
        return lose();
    } else {
        return win();
    }
}

//These are the inputs for the game.

rockButton.addEventListener('click', () => {
    playerPick = ROCK;
    return whoWins()});
paperButton.addEventListener('click', () => {
    playerPick = PAPER;
    return whoWins()});
scissorsButton.addEventListener('click', () => {
    playerPick = SCISSORS;
    return whoWins()});

function computerPick() {
    let computerChoice = '';
    const getRandom = Math.random;
    if (getRandom() >= 2/3) {
        computerChoice = ROCK;
    } else if (getRandom() >= 1/3){
        computerChoice = PAPER;
    } else {
        computerChoice = SCISSORS;
    }
    return computerChoice;
}

I'm very new to all this, but still, this is not random. 我对这一切都很陌生,但这仍然不是随机的。

This should be a simple fix, as mentioned in the comments you need to call Math.random once, otherwise the probabilities are skewed. 正如应该在一次调用Math.random的注释中所提到的那样,这应该是一个简单的解决方法,否则概率会发生偏差。

I think the probabilities of a PAPER would have been 0.66 * 0.66 = ~ 44% with the original code, the probability of SCISSORS would have been 0.66 * 0.33 = ~ 22%. 我认为,使用原始代码,PAPER的概率应为0.66 * 0.66 =〜44%,SCISSORS的概率将为0.66 * 0.33 =〜22%。 The new function should resolve this. 新功能应解决此问题。

 const ROCK = 1; const PAPER = 2; const SCISSORS = 3; // Original computerPick function function computerPickOriginal() { let computerChoice = ''; const getRandom = Math.random; if (getRandom() >= 2/3) { computerChoice = ROCK; } else if (getRandom() >= 1/3){ computerChoice = PAPER; } else { computerChoice = SCISSORS; } return computerChoice; } // Fixed computerPick function. function computerPick() { let computerChoice = ''; const choice = Math.random(); if (choice >= 2/3) { computerChoice = ROCK; } else if (choice >= 1/3){ computerChoice = PAPER; } else { computerChoice = SCISSORS; } return computerChoice; } function decodeChoice(choice) { if (choice == ROCK) return "Rock"; if (choice == PAPER) return "Paper"; if (choice == SCISSORS) return "Scissors"; } // Check the distribution of each version of the code. console.log("Checking distributions (10000 picks).."); let original_counts = {}; let counts = {}; for(let i = 0; i < 10000; i++) { let k = computerPick(); counts[k] = (counts[k] || 0) + 1; let k2 = computerPickOriginal(); original_counts[k2] = (original_counts[k2] || 0) + 1; } console.log('Computer Pick Distribution (original): ', Object.entries(original_counts).map(([key,value]) => `${decodeChoice(key)}: ${value}`)); console.log('Computer Pick Distribution (fixed): ', Object.entries(counts).map(([key,value]) => `${decodeChoice(key)}: ${value}`)); 

For future reference, you might find it easier to work with an array. 为了将来参考,您可能会发现使用数组更容易。

 const getRandomChoice = () => { const options = ['Rock', 'Paper', 'Scissors']; const randomIndex = Math.floor(Math.random() * options.length); const choice = options[randomIndex]; return choice; } const counts = {}; for(let i = 0; i < 10000; i++) { let p = getRandomChoice(); counts[p] = (counts[p] || 0) + 1; } console.log(counts); 

By multiplying the result of Math.random by the length of the array (3) we can get a value that is between [0, 3) (not inclusive of 3). 通过将Math.random的结果乘以数组的长度(3),我们可以得到一个介于[0,3)之间的值(不包括3)。 We then call Math.floor to "chop" off any decimals. 然后,我们调用Math.floor来“截断”所有小数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM