You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python强化学习游戏环境下跨类关系最优构建方式咨询

类关联结构优化方案

先修正原有代码的笔误

你现有代码存在类名不统一的问题:Game初始化时实例化的是Table类,但你实际定义的类名是Tables,后续方案统一使用Table作为牌桌类名。

核心设计思路

采用双向关联+统一操作入口的设计,既保证数据一致性,又满足两类需求:

  • Player实例保留table_no字段,Game层可快速索引玩家所属牌桌,全局管理状态
  • Table实例存储当前桌存活玩家的实例引用,无需跨层查询即可直接执行手牌相关逻辑
  • 所有玩家淘汰、转移操作统一封装在Game类的方法中,避免手动修改属性导致的数据不一致

具体实现代码

class Chips:
    # 你原有Chips类的实现,这里补个空实现避免报错
    def __init__(self, amount):
        self.amount = amount
    def __repr__(self):
        return str(self.amount)

class Game:
    def __init__(self, n_players, avg_hands_blinds, starting_chips, table_cnt, verbose):
        self.n_players = n_players * table_cnt
        self.starting_chips = starting_chips
        self.table_cnt = table_cnt
        self.tables = []
        per_table_players = int(n_players / table_cnt)
        for table_id in range(self.table_cnt):
            self.tables.append(Table(table_id, per_table_players))
        # 全局玩家列表,存所有存活/淘汰的玩家实例
        self.all_players = []
        for player_id in range(self.n_players):
            table_id = int(player_id / per_table_players)
            player = Player(player_id, starting_chips, table_id)
            self.all_players.append(player)
            # 初始化时把玩家加入对应牌桌的活跃列表
            self.tables[table_id].active_players.append(player)

    def eliminate_player(self, player_id):
        """淘汰指定玩家,同时更新全局状态和所属牌桌的玩家列表"""
        player = next(p for p in self.all_players if p.player_no == player_id)
        player.is_eliminated = True
        # 从所属牌桌的活跃列表中移除
        table = self.tables[player.table_no]
        table.active_players.remove(player)

    def transfer_player(self, player_id, target_table_id):
        """转移玩家到指定牌桌,自动同步双方数据"""
        player = next(p for p in self.all_players if p.player_no == player_id)
        if player.is_eliminated:
            return
        # 从原牌桌移除
        origin_table = self.tables[player.table_no]
        origin_table.active_players.remove(player)
        # 加入新牌桌
        target_table = self.tables[target_table_id]
        target_table.active_players.append(player)
        # 更新玩家的所属桌ID
        player.table_no = target_table_id

    def rebalance_tables(self):
        """全局牌桌负载均衡,可根据你的规则实现分配逻辑,这里仅给出示例结构"""
        # 先收集所有存活玩家
        active_players = [p for p in self.all_players if not p.is_eliminated]
        per_table_max = max(int(len(active_players)/self.table_cnt), 2) # 最少2人开局
        # 清空所有牌桌的活跃列表
        for table in self.tables:
            table.active_players.clear()
        # 重新分配玩家
        current_table_idx = 0
        for player in active_players:
            if len(self.tables[current_table_idx].active_players) >= per_table_max:
                current_table_idx += 1
            self.tables[current_table_idx].active_players.append(player)
            player.table_no = self.tables[current_table_idx].table_id

class Table:
    def __init__(self, table_id, max_players):
        self.table_id = table_id
        self.max_players = max_players
        self.active_players = [] # 存储当前桌存活的玩家实例引用
        self.table_hands = []

    def run_hand(self):
        """执行单局手牌逻辑示例,直接遍历当前桌玩家即可操作"""
        for player in self.active_players:
            # 直接调用玩家实例的方法/属性执行业务逻辑
            print(f"向玩家{player.player_no}发牌,当前筹码{player.chips.amount}")
        # 剩余手牌逻辑...

class Player:
    def __init__(self, player_no, starting_chips, table_no):
        self.player_no = player_no
        self.table_no = table_no
        self.chips = Chips(starting_chips)
        self.is_eliminated = False # 新增淘汰标记

    def __repr__(self):
        return f'player_no: {self.player_no} table_no: {self.table_no} chips: {self.chips} 淘汰状态:{self.is_eliminated}'

关键优势说明

  • 不需要冗余存储玩家数据,Table存储的是玩家实例的引用,修改玩家状态时全局同步
  • 所有变更操作都有统一入口,不会出现玩家所属桌和Table的玩家列表不一致的问题
  • 符合RL训练的需求:Game层可以快速拉取全局状态,Table层可以单独执行单局环境逻辑,和RL算法的接口完全适配

内容的提问来源于stack exchange,提问作者C. Cooney

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 02:48:05