-1

可能重复:
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; #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
    if drawn_card != 0 #if there is a card there 
     $deck[choice_of_card] = 0; #remove that card from the deck by making the space blank
     if drawn_card == 11 #if you draw an ace
      self.ace_count += 1;
     end 
     self.hand_value += drawn_card ;
    else hit; #if there is no card at that space then redraw (recursion)
    end
  end

  def flip_aces
    while self.hand_value > 21 && 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; #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 <= 16 #PLAYER STRATEGY: ON WHAT CARD DOES THE PLAYER STAND
  player1.hit;
  if player1.hand_value > 21
   player1.flip_aces; 
  end
 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;
  if house.hand_value > 21
   house.flip_aces; 
  end
 end
 #outcome
 #puts player1.hand_value;
 #puts house.hand_value;
 if player1.hand_value < house.hand_value
  return -1;
 elsif player1.hand_value > house.hand_value
  return 1;
 else return 0;
 end
end

#the simulation
wins = 0;
losses = 0;
rounds=5;

for i in 1..rounds
 if oneplayergame >0 
  wins +=1;
 elsif oneplayergame <0
  losses +=1
 end
end

print wins/(wins+losses).round(3)*100;

但是,尝试运行超过 5 轮时,我遇到了以下错误:

错误:您的应用程序使用的堆栈内存超过了安全上限 2048K。

我想知道是否有人可以看到我在代码中的哪些地方非常低效地使用了内存。会不会是递归?但是,在每次模拟开始时,卡片会被放回套牌中。

4

1 回答 1

0

我不懂游戏,但这是我对您的代码的重构。自己检查差异,想想我为什么要这样改变它。

$full_deck = [2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 11] * 4

class Player
    attr_reader :ace_count, :hand_value
    def initialize(ace_count, hand_value)
        @ace_count, @hand_value = ace_count, hand_value
    end
    def hit
        drawn_card = $deck.shift
        @ace_count += 1 if drawn_card == 11
        @hand_value += drawn_card
    end
    def flip_aces
        while @hand_value > 21 and @ace_count > 0
            @ace_count -= 1
            @hand_value -= 10
        end
    end
end

def oneplayergame
    $deck = $full_deck.dup.shuffle!
    house, player1 = Player.new(0,0), Player.new(0,0)
    [house, house, player1, player1].each{|player| player.hit}
    while player1.hand_value <= 16
        player1.hit
        player1.flip_aces
    end
    while house.hand_value <= player1.hand_value and player1.hand_value <=21
        house.hit
        house.flip_aces
    end
    player1.hand_value <=> house.hand_value
end

wins = 0.0
losses = 0.0
rounds = 5

rounds.times do
    result = oneplayergame
    wins +=1 if result > 0 
    losses +=1 if result < 0
end
puts wins/(wins+losses).round(3)*100
于 2012-10-04T13:24:08.473 回答