我的情况如下:我正在开发BlackJack的实现。我有卡,手,球员,甲板和游戏课程。主要游戏对象存储玩家和牌组,而玩家存储存放牌的牌。
我经常做以下事情。在这个例子中,我正在向每个玩家发放初始牌。
num_cards = 2
for player in self.players:
new_hand = Hand()
for i in range(num_cards):
new_hand.add_card(self.deck.get_next_card())
player.assign_hand(new_hand)
这非常有效。我现在的问题是我希望从玩家的手牌中删除一手牌(玩家可以在BlackJack中分割,从而导致生成多手牌)。在下面的函数中,我打算遍历每个玩家的手。如果手的值大于21,我想删除手。 (请注意,下面的remove()函数通常在Player类中执行,通过名为fold_hand()的Player方法调用。我遇到了同样的问题,所以我已经将代码移到了更为明显的位置用于说明目的。)< / p>
for player in self.players:
for hand in player.hands:
if hand.smallest_value() > 21:
player.hands.remove(hand)
这不起作用。为了清楚起见,我可以在remove()行之前打印出手,之后不会打印出来。也就是说,它似乎被删除了。然而,在下一轮比赛中,手又回来了。因此,球员的双手每一次都会成长。
上面的代码位于Game类中名为validate_player_hands()的函数中。此函数从名为play.py的文件中调用,该文件用于开始/结束游戏并促进主游戏循环。因此,对validate_player_hands()的唯一调用是在游戏循环中的play.py文件中,一个缩进。我打电话给:
game.validate_player_hands()
我也试过找到手的索引并使用'del'关键字,但结果是一样的。
为什么列表元素(名为player.hands的列表中的Hand对象)在看起来已被删除时无法删除?
提前致谢,
ParagonRG
答案 0 :(得分:3)
如何使用简单的列表理解消除手:
for player in self.players:
player.hands = [hand for hand in player.hands if hand.smallest_value() <= 21]
修改强>
使用过滤器:
for player in self.players:
player.hands = filter(lambda x: x.smallest_value() <= 21, player.hands)
答案 1 :(得分:2)
创建一个副本并使用与对象长度相关的索引迭代该对象。使用0设置要删除的每个元素,然后过滤手以清除零。
for player in self.players:
for hand_idx in range(len(player.hands)):
if player.hands[hand_idx].smallest_value() > 21:
player.hands[hand_idx]=0
player.hands=filter(None,hands)
答案 2 :(得分:0)
您需要执行以下操作:
newList = hands[:]
for hand in newList:
if hand.smallest_value() > 21: #your code here
player.hands.remove(hand)
这允许您在迭代该副本时制作要修改的列表的副本,从而避免Mihai提到的“树枝”场景。
答案 3 :(得分:0)
这可以通过在“for”语句的末尾添加[:]
来解决。这将创建列表的副本。然后,您可以在更改原始列表时循环复制副本:
for player in self.players:
for hand in player.hands[:]:
if hand.smallest_value() > 21:
player.hands.remove(hand)
(这是Python的list slicing语法。它是复制列表的fastest方法之一。更常见的是,这种语法以some_list[3:8]
的形式用于从索引中获取列表条目3到7(包括3和7),但是通过省略第一个数字,您可以从列表的开头获取所有内容,并且通过省略最后一个数字,您可以获得列表末尾的所有内容。)