我正在用Ruby编写一个卡片游戏框架,我发现了一个问题。我做了一个洗牌方法,把牌混在一起,效果很好。但是,我叫Deck#shuffle而不是Deck#shuffle!它能让甲板保持混乱,而我不想这样。
我还发现奇怪的是,当我添加:里弗斯作为一个论点,然后洗牌并不保持我想要的牌洗牌。
我希望在如何防止Deck#shuffle修改甲板方面提供任何帮助。谢谢!
下面是我的代码(其中的一部分,如果有人需要我的话,我也可以发布其余的代码):
class Deck
def initialize
@cards = []
(1..4).each { |suit|
(1..13).each { |rank|
@cards << Card.new(rank, suit)
}
}
end
def size
@deck.length
end
def shuffle!(type = :random, precision = 100)
case type
when :random
@cards.shuffle!
when :riffle, :farro
i = 0
first, second = cut
@cards = []
while size != 52
pile = (i.even? ? first : second)
if pile.empty?
pile = (pile == first ? second : first)
end
add_card(pile.pop)
i += 1 if (1..precision) === rand(1..100)
end
else
warn "Invalid shuffle method."
end
end
def shuffle(type = :random, precision = 100)
dup.shuffle!(type, precision)
end
def add_card(card)
@cards << card
end
end
deck = Deck.new
deck.shuffle
p deck.cards.map(&:to_a)发布于 2014-05-16 22:52:32
您的Deck类有一个实例变量-- @cards --它持有卡片。@cards实际上是对一组卡片的引用。
您没有实现Deck#dup,当您使用它时,您使用的是Object#dup,它执行一个浅拷贝&它将所有实例变量复制为引用。它不复制实例变量!
这意味着duped Deck持有一个不同的 @cards变量,该变量引用与原始Deck的@cards相同的数组。当您shuffle时,相同的数组被洗牌。它可以通过不同的引用变量访问,但仍然是相同的数组。
如果您尝试:riffle或:farro洗牌,它不会影响原始对象,因为这些洗牌类型中的对象可以做@cards = [],这会将@cards设置为一个新数组。
尽管如此,我还是要说,即使您没有:random类型,实现仍然是错误的-因为新的@cards和旧的@cards的分离不应该在shuffle!中--它应该在dup中!
因此,您需要重写dup方法并使其复制@cards。您还可能希望更改initialize以支持以下内容:
def initialize(cards = nil)
if cards
@cards = cards
else
@cards = []
(1..4).each { |suit|
(1..13).each { |rank|
@cards << Card.new(rank, suit)
}
}
end
end
def dup
Deck.new(@cards.dup)
end 发布于 2014-05-16 22:52:43
当您对对象执行dup时,您只创建该对象的浅副本。。这意味着当您获得一个新的Deck实例时,您的原始Deck和这个新的Deck都将引用相同的@cards实例变量。
发布于 2014-05-16 22:54:52
这一行..。
dup.shuffle!(type, precision)..。正在创建Deck对象的浅副本。
尽管它有自己的实例变量@cards,但实际上该实例变量引用的对象与原始对象中的实例变量相同。
https://stackoverflow.com/questions/23705410
复制相似问题