Ruby中的二十一点模拟导致奇怪的概率
问题描述:
下面是一个简单的二十一点游戏的模拟代码。玩家和经销商(房子)抽两张牌。玩家然后击中,直到他达到17点。经销商(房子)然后击中,直到他与球员画或被破坏。考虑到球员首先出场,他的获胜几率应该低于任何策略的50%。但是,由于某些原因,当我重复模拟时,玩家似乎赢得了超过50%的时间。我的代码中必须有一些错误才能给出这个结果。Ruby中的二十一点模拟导致奇怪的概率
one_suit = [2,3,4,5,6,7,8,9,10,10,10,10,11]; #the value of the cards for blackjack
$full_deck = one_suit*4; #clubs, diamonds, hearts and spades
$deck = $full_deck.dup; #start off the game with a full deck
class Player
attr_accessor :ace_count
attr_accessor :hand_value
def initialize(ace_count,hand_value)
@ace_count = ace_count;
@hand_value = hand_value;
end
def hit #instance method, vs. self.hit = class method
choice_of_card = rand($deck.length); #choose a random card out of the deck
drawn_card = $deck[choice_of_card]; #draw that random card from the deck
$deck.delete_at(choice_of_card); #remove that card from the array
if drawn_card == 11 #if you draw an ace
self.ace_count += 1;
end
self.hand_value += drawn_card;
end
def flip_aces
while self.hand_value > 21 && self.ace_count > 0 #repeat until hand is below 21 or aces are all flipped
self.ace_count -= 1 #ace gets flipped to a 1
self.hand_value -= 10 #ace goes from 11 to 1
end
end
end
def oneplayergame
$deck = $full_deck.dup; #start a new game with a full deck
#generate the house and the player
house = Player.new(0,0);
player1 = Player.new(0,0);
#both the house and the player draw two cards
house.hit; house.hit; player1.hit; player1.hit;
while player1.hand_value <= 17 #PLAYER STRATEGY: ON WHAT CARD DOES THE PLAYER STAND
player1.hit;
player1.flip_aces;
end
while house.hand_value < player1.hand_value && player1.hand_value <=21 #HOUSE DRAWS CARDS IF UNDER PLAYER VALUE AND PLAYER IS NOT BUST
house.hit;
house.flip_aces;
end
#outcome
if player1.hand_value < house.hand_value && house.hand_value <= 21
return -1;
elsif player1.hand_value > house.hand_value && player1.hand_value <= 21
return 1;
elsif player1.hand_value < house.hand_value && house.hand_value > 21
return 1;
elsif player1.hand_value > house.hand_value && player1.hand_value > 21
return -1;
else return 0;
end
end
#the simulation
wins = 0;
losses = 0;
rounds=10000;
for i in 1..rounds
oneplayergame;
if oneplayergame >0
wins +=1;
elsif oneplayergame <0
losses +=1
end
end
print wins/(wins+losses).round(3)*100;
答
此代码
for i in 1..rounds
oneplayergame;
if oneplayergame >0
wins +=1;
elsif oneplayergame <0
losses +=1
end
是错误的:正在调用oneplayergame
三次:如果一个球员失去了第二次和第三次的呼叫,这将扭曲的结果的损失仅计算在内。您只应拨打oneplayergame
一次,将结果分配给本地变量
谢谢,这是完美的!学习到教训了! –