我正在用Ruby写一个卡片游戏框架,我发现了一个问题。我做了一个混乱方法,混合卡,它工作正常。但是我打电话给Deck #shuffle而不是Deck #shuffle!它保持了洗牌,这是我不想要的。
我也觉得奇怪的是,当我添加:riffle作为一个参数时,然后洗牌不会让我想要的牌组洗牌。
我很感激有关如何防止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)
答案 0 :(得分:2)
您的Deck
班级有一个实例变量 - @cards
- 用于存放卡片。 @cards
实际上是对一系列卡片的引用。
使用它时没有实现Deck#dup
,使用Object#dup
执行浅拷贝 - 它将所有实例变量复制为引用。 它不会复制实例变量!
这意味着dup
ed Deck
拥有不同的 @cards
变量,该变量引用与原始数据相同的数组Deck
的{{1}}。当你@cards
时,同一个数组被洗牌。它可以通过不同的引用变量访问,但它仍然是相同的数组。
如果您尝试shuffle
或:riffle
改组,它将不会影响原始对象,因为您使用:farro
这些随机播放类型中的那些将@cards = []
设置为a新阵列。
尽管如此,我要说即使你没有@cards
类型,实现仍然是错误的 - 因为新:random
与旧版本的分离不应该在@cards
- 它应该在shuffle!
!
那么,您需要覆盖dup
方法并使其重复dup
。您可能还想更改@cards
以支持此功能:
initialize
答案 1 :(得分:0)
在对象上dup
Deck
时。这意味着当您获得新的Deck
实例时,原始@cards
和新{{1}}都会引用相同的{{1}}实例变量。
答案 2 :(得分:0)
这一行...
dup.shuffle!(type, precision)
...正在创建Deck对象的浅表副本。
虽然它有自己的实例变量@cards
,但实例变量实际上引用的是与原始对象中的实例变量相同的对象。