[英]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.