0

0

Java 多米诺骨牌记忆游戏:揭示机制与游戏结束逻辑修复教程

花韻仙語

花韻仙語

发布时间:2025-07-07 20:04:20

|

983人浏览过

|

来源于php中文网

原创

Java 多米诺骨牌记忆游戏:揭示机制与游戏结束逻辑修复教程

本教程旨在解决Java多米诺骨牌记忆游戏中,匹配成功的多米诺骨牌无法保持揭示状态,且游戏无法正常结束的问题。核心解决方案包括:正确重写 Domino 类的 equals() 和 hashCode() 方法以实现基于内容的比较,而非内存地址比较;以及在 MemoryLane 类的 guess() 方法中调用 setRevealed() 方法来更新多米诺骨牌的显示状态。通过这些修正,游戏将能够正确识别匹配,并按照预期逻辑结束。

问题分析:多米诺骨牌未正确揭示与游戏未结束的原因

在提供的多米诺骨牌记忆游戏代码中,存在两个主要问题导致游戏功能不完整:

  1. 多米诺骨牌匹配判断不准确: MemoryLane 类中的 guess 方法使用 board[i] == board[k] 来判断两个多米诺骨牌是否匹配。在 Java 中,对于对象类型,== 运算符比较的是两个引用是否指向内存中的同一个对象实例,而不是它们的内容是否相等。因此,即使两个多米诺骨牌具有相同的 top 和 bottom 值,如果它们是不同的对象实例,== 也会返回 false。这导致了即使玩家猜对了,多米诺骨牌也无法被正确识别为匹配。
  2. 多米诺骨牌状态未更新: Domino 类中包含 setRevealed(boolean revealed) 方法用于设置多米诺骨牌的揭示状态,但在 MemoryLane 类的 guess 方法中,当匹配成功时,并未调用此方法来将匹配的多米诺骨牌设置为已揭示。这使得 isRevealed() 方法始终返回 false(因为 revealed 成员变量的默认值为 false),从而导致 MemoryLane 的 gameOver() 方法无法正确判断所有多米诺骨牌是否都被揭示,进而游戏无法结束。

解决方案一:正确实现对象比较——重写 equals() 和 hashCode()

为了使 Domino 对象能够基于其内容(即 top 和 bottom 值)进行比较,我们需要在 Domino 类中重写 equals() 方法。同时,根据 Java 规范,如果重写了 equals() 方法,也必须重写 hashCode() 方法,以维护它们之间的契约:如果两个对象通过 equals() 方法比较是相等的,那么它们的 hashCode() 方法必须产生相同的整数结果。

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

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

    public Domino(int x, int y) {
        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; // 简化了原有的 if-else 结构
    }

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

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 59 * hash + this.getTop();
        hash = 59 * hash + this.getBottom();
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) { // 检查是否是同一个对象实例
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) { // 检查是否为null或类型不匹配
            return false;
        }
        final Domino other = (Domino) obj; // 类型转换
        if (this.getTop() != other.getTop()) { // 比较 top 值
            return false;
        }
        if (this.getBottom() != other.getBottom()) { // 比较 bottom 值
            return false;
        }
        return true; // 如果 top 和 bottom 都相等,则认为对象相等
    }
}

说明:

  • equals(Object obj):
    • 首先检查是否为同一个对象引用(this == obj),如果是则直接返回 true。
    • 然后检查传入对象是否为 null 或类型不匹配(getClass() != obj.getClass()),如果是则返回 false。
    • 将 obj 强制转换为 Domino 类型。
    • 最后,比较 top 和 bottom 属性是否相等。
  • hashCode():
    • 使用 top 和 bottom 属性计算哈希值。一种常见的做法是使用一个质数(如59)乘以当前哈希值并加上字段值,以分散哈希码并减少碰撞。

解决方案二:确保匹配多米诺骨牌保持揭示状态

在 MemoryLane 类的 guess 方法中,当两个多米诺骨牌被正确匹配时,需要调用它们的 setRevealed(true) 方法,将它们的状态设置为已揭示。

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

Bika.ai
Bika.ai

打造您的AI智能体员工团队

下载

以下是 MemoryLane 类中 guess 方法的修正:

import java.util.Arrays;
import java.util.Random;

public class MemoryLane {
    private Domino[] board;

    public MemoryLane(int max) {
        board = new Domino[(max * max) + max];

        int i = 0;
        for (int top = 1; top <= max; top++) {
            for (int bot = 1; bot <= max; bot++) {
                if (top <= bot) {
                    board[i] = new Domino(top, bot);
                    i++;
                    board[i] = new Domino(top, bot);
                    i++;
                }
            }
        }
        shuffle();
    }

    private void shuffle() {
        int index;
        Random random = new Random();
        for (int i = board.length - 1; i > 0; i--) {
            index = random.nextInt(i + 1);
            if (index != i) {
                Domino temp = board[index];
                board[index] = board[i];
                board[i] = temp;
            }
        }
    }

    public boolean guess(int i, int k) {
        // 使用重写后的 equals 方法进行内容比较
        if (board[i].equals(board[k])) {
            board[i].setRevealed(true); // 设置第一个多米诺骨牌为已揭示
            board[k].setRevealed(true); // 设置第二个多米诺骨牌为已揭示
            return true;
        }
        return false;
    }

    public String peek(int a, int b) {
        String text = ""; // 使用空字符串初始化,避免 String new String()
        text += ("[" + board[a].getTop() + "] [" + board[b].getTop() + "]\n");
        text += ("[" + board[a].getBottom() + "] [" + board[b].getBottom() + "]\n");
        return text;
    }

    public boolean gameOver() {
        int count = 0;
        for (int i = 0; i < board.length; i++) {
            if (board[i].isRevealed()) {
                count++;
            }
        }
        return (count == board.length); // 当所有多米诺骨牌都已揭示时,游戏结束
    }

    // 调试方法,显示所有多米诺骨牌的真实值(可选,原答案中包含)
    public String debug() {
        String text = "";
        for (int i = 0; i < board.length; i++) {
            text += ("[" + board[i].getTop() + "] ");
        }
        text += ('\n');
        for (int i = 0; i < board.length; i++) {
            text += ("[" + board[i].getBottom() + "] ");
        }
        return text;
    }

    @Override
    public String toString() {
        String text = "";
        for (int i = 0; i < board.length; i++) {
            if (board[i].isRevealed()) {
                text += ("[" + board[i].getTop() + "] ");
            } else {
                text += ("[ ] ");
            }
        }
        text += ('\n');
        for (int i = 0; i < board.length; i++) {
            if (board[i].isRevealed()) {
                text += ("[" + board[i].getBottom() + "] ");
            } else {
                text += ("[ ] ");
            }
        }
        return text;
    }
}

说明:

  • guess(int i, int k): 现在使用 board[i].equals(board[k]) 进行比较,这将正确判断两个多米诺骨牌的内容是否相等。
  • 如果判断为匹配成功,则 board[i].setRevealed(true) 和 board[k].setRevealed(true) 将被调用,从而更新这些多米诺骨牌的 revealed 状态。
  • gameOver() 方法现在能够正确统计已揭示的多米诺骨牌数量,并在所有多米诺骨牌都被揭示时返回 true,从而使游戏正常结束。

注意事项与总结

  • equals() 与 hashCode() 契约: 再次强调,当您在 Java 中重写 equals() 方法时,务必同时重写 hashCode() 方法。这是 Java 集合框架(如 HashMap、HashSet)正确工作的基础,否则可能导致对象在集合中行为异常。
  • 对象比较的正确性: 理解 == 运算符和 equals() 方法在对象比较上的区别至关重要。== 比较引用地址,而 equals() 比较对象内容(如果被正确重写)。
  • 代码可读性与维护: 在 Domino 类的 isRevealed() 方法中,将 if (revealed) return true; return false; 简化为 return revealed; 可以提高代码的简洁性。同样,在 String text = new String(); 处,直接使用 String text = ""; 更为简洁高效。
  • 驱动类不变性: 由于 MemoryLaneDriver 类被设定为不可修改,所有的修正都必须集中在 Domino 和 MemoryLane 这两个核心业务逻辑类中,这正是本教程所遵循的原则。

通过以上修正,您的多米诺骨牌记忆游戏将能够正确地识别匹配、揭示多米诺骨牌,并最终判断游戏胜利,提供完整的游戏体验。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

443

2023.08.02

java中boolean的用法
java中boolean的用法

在Java中,boolean是一种基本数据类型,它只有两个可能的值:true和false。boolean类型经常用于条件测试,比如进行比较或者检查某个条件是否满足。想了解更多java中boolean的相关内容,可以阅读本专题下面的文章。

350

2023.11.13

java boolean类型
java boolean类型

本专题整合了java中boolean类型相关教程,阅读专题下面的文章了解更多详细内容。

29

2025.11.30

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

236

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

458

2024.03.01

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1501

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

232

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

87

2025.10.17

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

158

2026.01.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 0.9万人学习

光速学会docker容器
光速学会docker容器

共33课时 | 1.9万人学习

时间管理,自律给我自由
时间管理,自律给我自由

共5课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号