function rand(n) { return Math.floor(Math.random() * n); } function Game() { this.doors = ['closed', 'closed', 'closed']; this._goat = rand(3); // @private } Game.prototype.reveal = function(picked) { var options = []; for (var i = 0; i < 3; i++) { if (i !== picked && i !== this._goat) { options.push(i); } } this.doors[options[rand(options.length)]] = 'open'; return this; }; // Strategy prototype (abstract) function Strategy() { this.picked = null; } Strategy.prototype.firstPick = function() { return this.picked = rand(3); }; Strategy.prototype.finalPick = function() { throw new Error('unimplemented'); }; function HoldStrategy() { } HoldStrategy.prototype = Object.create(Strategy.prototype); HoldStrategy.prototype.finalPick = function(game) { return this.picked; }; function SwitchStrategy() { } SwitchStrategy.prototype = Object.create(Strategy.prototype); SwitchStrategy.prototype.finalPick = function(game) { for (var i = 0; i < 3; i++) { if (i !== this.picked && game.doors[i] !== 'open') { return i; } } return null; }; Game.monteCarlo = function(n, Strategy) { var total = 0; for (var i = 0; i < n; i++) { var game = new Game(); var strategy = new Strategy(); game.reveal(strategy.firstPick()); total += (strategy.finalPick(game) === game._goat) ? 1 : 0; }; return total / n; }; Usage: Game.monteCarlo(1000000, HoldStrategy); // => 0.333622 Game.monteCarlo(1000000, SwitchStrategy); // => 0.667626 More strategies are possible: function CheatStrategy() { } CheatStrategy.prototype = Object.create(Strategy.prototype); CheatStrategy.prototype.finalPick = function(game) { return game._goat; }; Game.monteCarlo(1000000, CheatStrategy); // => 1