优化MCTS AI中提取棋子/基地所属队伍ID的高效方法
问题描述
我正在为一款游戏开发MCTS AI,当前遇到CPU瓶颈,其中一个占比约20%处理资源的方法,用于从二维String网格的指定位置提取棋子或基地的所属队伍ID:
- 基地格式为
"b:000",其中000为队伍ID - 棋子格式为
"p:000_1",其中000为队伍ID
当前使用的代码如下:
public static int getOccupantTeam(String[][] grid, int[] pos, StringBuilder sb) { sb = sb.delete(0, sb.length()).append(grid[pos[0]][pos[1]]); int indexUnderscore = sb.indexOf("_"); return Integer.parseInt(sb.substring(sb.indexOf(":")+1, indexUnderscore == -1 ? sb.length() : indexUnderscore)); }
注:使用StringBuilder是为了复用实例、减少对象创建,希望找到更高效的优化方式。
优化方案
1. 直接操作原String,消除StringBuilder冗余开销
当前代码里的StringBuilder并未带来实际收益,反而多了一次字符串复制操作。直接对原String进行索引查找和解析,能省去清空、复制StringBuilder的步骤,同时使用Integer.parseInt的重载方法,直接指定起止索引,避免创建子字符串对象:
public static int getOccupantTeam(String[][] grid, int[] pos) { String s = grid[pos[0]][pos[1]]; int colonIdx = s.indexOf(':'); int underscoreIdx = s.indexOf('_'); int endIdx = underscoreIdx == -1 ? s.length() : underscoreIdx; return Integer.parseInt(s, colonIdx + 1, endIdx, 10); }
2. 手动解析数字,绕过通用解析逻辑
由于队伍ID是固定3位数字,完全可以跳过Integer.parseInt的通用处理逻辑(如符号判断、基数适配),直接通过字符ASCII值计算数值,这是单调用场景下性能最优的方案:
public static int getOccupantTeam(String[][] grid, int[] pos) { String s = grid[pos[0]][pos[1]]; // 固定跳过前两位的"b:"或"p:",直接取第3-5位字符计算 return (s.charAt(2) - '0') * 100 + (s.charAt(3) - '0') * 10 + (s.charAt(4) - '0'); }
注意:该方案依赖ID格式固定为3位数字的前提,若后续格式变动需同步修改代码。
3. 预解析缓存,彻底移除高频解析成本
如果网格数据不会频繁变更,可以提前将整个网格的队伍ID预解析并存储到int[][]缓存数组中,后续查询直接读取缓存值,把解析成本从MCTS的高频调用中彻底剥离:
// 初始化或网格更新时预生成缓存 int[][] teamGrid = new int[grid.length][grid[0].length]; for (int i = 0; i < grid.length; i++) { for (int j = 0; j < grid[i].length; j++) { String s = grid[i][j]; teamGrid[i][j] = (s.charAt(2) - '0') * 100 + (s.charAt(3) - '0') * 10 + (s.charAt(4) - '0'); } } // 后续获取队伍ID直接读取缓存 public static int getOccupantTeam(int[][] teamGrid, int[] pos) { return teamGrid[pos[0]][pos[1]]; }
内容的提问来源于stack exchange,提问作者Simon
相关产品推荐
相关产品推荐

