编写pontoon(21点)游戏时,如何替代全局变量?
嘿,这个问题提得特别实在——全局变量确实很容易让代码变得乱糟糟的,尤其是像21点这种需要管理多个状态(牌堆、手牌)的游戏里,后期维护起来头疼得很。我给你几个靠谱的替代方案,都是Python里常用的思路,你可以根据自己的代码规模选:
方案1:让函数返回抽取的牌(最直接的无副作用写法)
这是最简单的改进方式,把原来依赖全局变量card的逻辑改成让抽取牌的函数直接返回抽到的牌,然后在调用这个函数的地方,把返回值加到comp_cards里就行。这样函数的职责更清晰,也没有全局变量带来的副作用。
示例代码:
import random def draw_card(deck): # 这里可以加入每三轮洗牌的逻辑,比如维护一个计数器 # 假设外部有个shuffle_count变量记录洗牌次数 # if shuffle_count % 3 == 0: # random.shuffle(deck) # shuffle_count += 1 # 核心抽牌逻辑 drawn_card = deck.pop(0) return drawn_card # 调用示例 deck = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"] * 4 comp_cards = [] # 给电脑抽一张牌 card = draw_card(deck) comp_cards.append(card)
这样一来,card就变成了局部变量,完全不需要全局声明。如果需要维护洗牌计数器,也可以把计数器作为参数传入函数,或者用下面的方案封装起来。
方案2:用类封装游戏状态(最适合游戏的架构)
既然你是在做游戏,用类来封装所有相关的状态(牌堆、电脑手牌、洗牌计数器这些)是最专业的做法。把抽牌逻辑作为类的方法,所有状态都存在实例属性里,彻底告别全局变量,代码结构也更清晰,后期扩展功能(比如玩家手牌、计分逻辑)会非常方便。
示例代码:
import random class PontoonGame: def __init__(self): # 初始化一副标准52张牌 self.deck = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"] * 4 self.comp_cards = [] self.shuffle_count = 0 # 计数洗牌次数 random.shuffle(self.deck) # 开局先洗牌一次 def draw_for_computer(self): # 每三轮洗牌一次 self.shuffle_count += 1 if self.shuffle_count % 3 == 0: random.shuffle(self.deck) drawn_card = self.deck.pop(0) self.comp_cards.append(drawn_card) return drawn_card # 如果外部需要用到这张牌可以返回,不需要也可以省略 # 使用示例 game = PontoonGame() # 给电脑抽牌 game.draw_for_computer() # 查看电脑手牌 print(game.comp_cards)
这个方案把所有游戏相关的逻辑和状态都集中在一个类里,代码可读性和可维护性都会提升很多,是游戏开发的常规做法。
方案3:用字典传递状态(轻量替代方案)
如果暂时不想用类,也可以把所有需要共享的状态(牌堆、电脑手牌、洗牌计数器)放到一个字典里,然后把这个字典作为参数传给抽牌函数。函数可以直接修改字典里的内容,同时返回抽到的牌,避免全局变量的混乱。
示例代码:
import random def draw_for_computer(game_state): game_state["shuffle_count"] += 1 if game_state["shuffle_count"] % 3 == 0: random.shuffle(game_state["deck"]) drawn_card = game_state["deck"].pop(0) game_state["comp_cards"].append(drawn_card) return drawn_card # 初始化游戏状态 game_state = { "deck": ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"] * 4, "comp_cards": [], "shuffle_count": 0 } random.shuffle(game_state["deck"]) # 调用抽牌 draw_for_computer(game_state) # 查看电脑手牌 print(game_state["comp_cards"])
这个方案比全局变量更可控,状态是明确传递的,不会出现莫名其妙的全局变量修改问题,适合小型脚本或者快速原型开发。
总的来说,我最推荐方案2,用类来封装游戏状态,长远来看好处多多。如果只是小脚本快速实现,方案1或者3也完全够用~
内容的提问来源于stack exchange,提问作者TDale54

