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

Java开发Dungeon游戏时如何校验玩家是否遍历棋盘所有面板

问题根因

你现在的实现有3个核心问题,导致访问校验完全失效:

  • 用允许重复元素的List逐次记录每一步移动位置,会产生大量重复坐标:比如玩家在两个格子之间来回走,列表长度很快就能凑到总格子数,但实际根本没走遍全图,单纯比对两个列表的长度没有任何意义。
  • 用只存单个键值对的HashMap<Integer,Integer>存(x,y)坐标属于冗余设计,平白增加后续内容比对的复杂度。
  • 现有校验逻辑只统计两个列表的元素个数,完全没有做集合内容的匹配,哪怕长度相等,内容完全不相关也会误判。
修正方案

1. 替换存储结构

直接删掉用来存全图坐标的boardPlaces列表、存移动路径的movesRecorded列表,改用HashSet<String>存玩家已经到访过的坐标——HashSet自带去重特性,同一个格子不管走多少次,集合里只会存一次,不需要手动去重。
坐标直接拼成固定格式的字符串存储即可,比如x坐标 + "," + y坐标,不需要额外自定义类、重写equals和hashCode,适配这个练习的规模完全够用。
全图总格子数不需要提前遍历棋盘存列表,直接用棋盘长度 * 棋盘高度就能算出来,省掉无意义的初始化遍历。

2. 修正移动记录逻辑

每次处理单个移动指令、确认坐标不越界之后,再更新玩家位置,同时把新坐标加入访问记录集合。注意不要在移动无效(撞边界)的时候重复记录相同坐标。
修正后的移动方法代码:

// 类成员变量,替换原来的movesRecorded
private HashSet<String> visitedPositions = new HashSet<>();

// 玩家初始化到起点位置时,先把起点加入访问集合
visitedPositions.add(this.x + "," + this.y);

public void updatePosition(String m) {
    char[] moveSeq = m.toCharArray();
    for (char move : moveSeq) {
        int nextX = this.x;
        int nextY = this.y;
        // 先计算下一步坐标,判断是否越界
        if (move == 'w' && this.y - 1 >= 0) {
            nextY--;
        }
        if (move == 's' && this.y + 1 <= height - 1) {
            nextY++;
        }
        if (move == 'a' && this.x - 1 >= 0) {
            nextX--;
        }
        if (move == 'd' && this.x + 1 <= length - 1) {
            nextX++;
        }
        // 更新到合法位置,记录访问点
        this.x = nextX;
        this.y = nextY;
        visitedPositions.add(this.x + "," + this.y);
    }
    moves--;
    // 所有指令处理完成后再做棋盘渲染即可,位置计算不受渲染时机影响
}

3. 简化胜利校验逻辑

原来双重循环计数的代码可以全部删掉,校验逻辑只需要两行:

int totalCells = length * height;
// 敌人全灭 或者 访问过的格子数等于总格子数,即达成胜利条件
return vamps.isEmpty() || player.getVisitedPositions().size() == totalCells;

如果你非要保留原有两个List比对的写法(非常不推荐,冗余度很高),需要先把两个List都转为HashSet去重,再用containsAll做双向内容匹配:

HashSet<HashMap<Integer,Integer>> boardSet = new HashSet<>(boardPlaces);
HashSet<HashMap<Integer,Integer>> moveSet = new HashSet<>(playerMovesRecorded);
boolean allVisited = boardSet.containsAll(moveSet) && moveSet.containsAll(boardSet);

这种写法不仅性能差,还可能因为HashMap的键值匹配问题出现判断错误,没必要在这个小练习里用。

内容的提问来源于stack exchange,提问作者morloq

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 11:48:26