«

Java多米诺记忆游戏:修复对象比较与揭示状态问题

磁力搜索 • 14 小时前 • 2 次点击 • 资讯分享


Java多米诺记忆游戏:修复对象比较与揭示状态问题

本教程详细探讨了Java多米诺记忆游戏中常见的两个核心问题:对象比较不准确导致的多米诺牌无法正确匹配,以及匹配后牌面未能持续揭示的问题。文章深入分析了Java中equals()和hashCode()方法的正确重写方式,强调了其在对象值比较中的重要性。同时,指导读者如何在游戏逻辑中正确更新多米诺牌的揭示状态,从而确保游戏能按预期进行并最终结束。

问题剖析:为何多米诺牌无法正确揭示与游戏不结束

在构建java多米诺记忆游戏时,开发者常会遇到两个关键挑战:

  1. 对象比较不准确: 游戏未能正确识别两个多米诺牌是否匹配。原始代码中,MemoryLane类的guess方法使用了board[i] == board[k]进行比较。在Java中,==运算符对于对象类型而言,比较的是两个引用是否指向内存中的同一个对象实例,而不是它们的内容(即多米诺牌的顶部和底部数字)是否相同。这导致即使两个多米诺牌的数字完全一致,但只要它们是不同的对象实例,==比较就会返回false。
  2. 牌面状态未更新: 即使玩家猜测正确,对应的多米诺牌也没有保持揭示状态。Domino类提供了setRevealed(boolean revealed)方法来控制牌的显示状态,但MemoryLane类的guess方法在判断匹配成功后,并没有调用此方法来更新多米诺牌的revealed属性。这直接导致了MemoryLane的toString()方法在渲染棋盘时,无法根据isRevealed()的返回值正确显示已匹配的牌。

这两个问题共同导致了游戏无法按照预期进行:牌面无法保持揭示,并且由于gameOver()方法依赖于所有牌都被揭示的计数,游戏也永远无法判断为结束。

解决方案一:正确重写 equals() 与 hashCode() 方法

要解决对象比较不准确的问题,我们需要在Domino类中重写equals()方法。Java的Object类默认的equals()方法行为与==运算符相同,即比较内存地址。为了实现基于内容的比较,我们必须提供自定义的逻辑。

当重写equals()方法时,强烈建议同时重写hashCode()方法。这是Java契约的一部分:如果两个对象根据equals()方法是相等的,那么它们的hashCode()方法必须产生相同的整数结果。违反这一契约会导致在使用基于哈希的集合(如HashMap、HashSet)时出现不可预测的行为。

以下是Domino类中equals()和hashCode()的正确实现:

立即学习“Java免费学习笔记(深入)”;

public class Domino {
    private int top, bottom;
    private boolean revealed;

    public Domino(int x, int y) {
        // 确保top <= bottom,使(x,y)和(y,x)被视为同一个多米诺牌
        if (x > y) {
            top = y;
            bottom = x;
        } else {
            top = x;
            bottom = y;
        }
    }

    public int getTop() {
        return top;
    }

    public int getBottom() {
        return bottom;
    }

    public boolean isRevealed() {
        return revealed; // 简化逻辑,直接返回revealed
    }

    public void setRevealed(boolean revealed) {
        this.revealed = revealed;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        // 使用top和bottom的值计算哈希码
        hash = 59 * hash + this.getTop();
        hash = 59 * hash + this.getBottom();
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        // 1. 检查是否是同一个对象引用
        if (this == obj) {
            return true;
        }
        // 2. 检查传入对象是否为null或类型不匹配
        if (!(obj instanceof Domino)) {
            return false;
        }
        // 3. 类型转换
        final Domino other = (Domino) obj;
        // 4. 比较关键属性
        if (this.getTop() != other.getTop()) {
            return false;
        }
        if (this.getBottom() != other.getBottom()) {
            return false;
        }
        return true; // 所有属性都匹配,则认为相等
    }
}
登录后复制


    还没收到回复