Java多米诺游戏显示修复与结束逻辑详解
小伙伴们有没有觉得学习文章很有意思?有意思就对了!今天就给大家带来《Java多米诺牌游戏显示与结束逻辑修复教程》,以下内容将会涉及到,若是在学习中对其中部分知识点有疑问,或许看了本文就能帮到你!
问题分析
在提供的Java记忆游戏代码中,存在两个主要问题导致游戏无法按预期运行:
- 多米诺牌匹配判断不准确: MemoryLane类中的guess方法使用board[i] == board[k]来判断两个多米诺牌是否匹配。在Java中,==运算符对于对象类型而言,比较的是两个引用是否指向内存中的同一个对象实例,而不是它们所代表的逻辑内容是否相等。因此,即使两张多米诺牌(即两个Domino对象)的top和bottom值相同,只要它们是不同的对象实例,==比较就会返回false。
- 多米诺牌状态未更新: 当玩家成功猜对一对多米诺牌时,程序并未调用Domino对象的setRevealed(true)方法来将其标记为已揭示。这导致以下连锁问题:
- Domino类的isRevealed()方法始终返回false(因为revealed成员变量从未被设置为true)。
- MemoryLane类的toString()方法无法正确显示已匹配的多米诺牌(因为它依赖isRevealed()的状态)。
- MemoryLane类的gameOver()方法始终返回false(因为它统计的是已揭示的多米诺牌数量,而这个数量始终为零),导致游戏无法结束。
此外,Domino类中原有的equals方法也存在逻辑错误,它比较的是top == bottom,这实际上是检查多米诺牌是否为双牌(如[1|1]),而不是比较两个不同的Domino对象是否相等。
解决方案
针对上述问题,我们需要对Domino类和MemoryLane类进行修改。
1. 修复 Domino 类:重写 equals() 和 hashCode() 方法
为了使MemoryLane类中的guess方法能够正确地比较两个Domino对象的内容(即它们的top和bottom值),我们需要在Domino类中重写equals(Object obj)方法。同时,根据Java的约定,如果重写了equals()方法,就必须同时重写hashCode()方法,以确保对象在哈希表(如HashMap、HashSet)中能正确工作,并维护equals和hashCode之间的契约:如果两个对象通过equals()方法比较为相等,那么它们的hashCode()方法必须返回相同的值。
Domino 类修改示例:
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() { // 简化原始逻辑:直接返回revealed状态 return revealed; } 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) { // 1. 检查是否为同一个对象引用 if (this == obj) { return true; } // 2. 检查传入对象是否为null或类型不匹配 if (obj == null || !(obj instanceof Domino)) { return false; } // 3. 将传入对象向下转型 final Domino other = (Domino) obj; // 4. 比较关键属性(top和bottom) if (this.getTop() != other.getTop()) { return false; } if (this.getBottom() != other.getBottom()) { return false; } return true; // 所有属性都匹配,则认为对象相等 } }
注意事项:
- equals方法的实现遵循了标准的约定:自反性、对称性、传递性、一致性以及对null的判断。
- hashCode方法的实现确保了与equals方法的一致性,即相等的对象具有相同的哈希码。
2. 修复 MemoryLane 类:更新 guess() 方法
在MemoryLane类的guess方法中,我们需要将对象引用比较==替换为内容比较equals(),并在匹配成功时调用Domino对象的setRevealed(true)方法。
MemoryLane 类修改示例:
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方法比较Domino对象的内容 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 = 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); } // 可选:添加一个debug方法用于查看所有牌面,便于测试 public String debug() { String text = new String(); 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 = new String(); 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; } }
MemoryLaneDriver 类:
MemoryLaneDriver 类无需任何修改,因为它通过MemoryLane类的公共接口进行交互,而我们对MemoryLane和Domino类的修改都保持了其公共接口不变(或仅在内部逻辑上进行了优化)。
import java.util.Scanner; public class MemoryLaneDriver { public static void main(String[] args) { String message = "Welcome to Memory Lane!" + "\n" + "Choose two indexes to reveal the corresponding dominoes." + "\n" + "If the dominoes match, they stay revealed." + "\n" + "Reveal all the dominoes to win the game!" + "\n"; System.out.println(message); Scanner input = new Scanner(System.in); MemoryLane game = new MemoryLane(2); long start = System.currentTimeMillis(); while (!game.gameOver()) { // 可选:在实际游戏中可以移除或注释掉此行,它用于调试时显示所有牌面 // System.out.println(game.debug()); System.out.println(game); System.out.print("First: "); int first = input.nextInt(); System.out.print("Second: "); int second = input.nextInt(); game.guess(first, second); System.out.println(game.peek(first, second) + "\n"); } long stop = System.currentTimeMillis(); long elapsed = (stop - start) / 1000; System.out.println(game); System.out.println("\nYou win!"); System.out.println("Total time: " + elapsed + "s"); } }
总结
通过以上修改,我们解决了记忆游戏中的核心逻辑问题:
- 正确识别匹配: 重写Domino类的equals方法,使得MemoryLane.guess方法能够基于多米诺牌的实际数值(top和bottom)进行准确比较。
- 正确更新状态: 在guess方法中,当检测到匹配时,调用setRevealed(true)将匹配的多米诺牌状态更新为已揭示。
- 正确显示与游戏结束: Domino.isRevealed()现在能返回正确状态,进而MemoryLane.toString()能够正确显示已揭示的牌面,并且MemoryLane.gameOver()能够准确判断游戏是否所有牌都已揭示,从而使游戏能够正常结束。
这个案例强调了在Java中处理自定义对象比较时,正确重写equals()和hashCode()方法的重要性,以及理解对象状态管理在游戏逻辑中的关键作用。
以上就是《Java多米诺游戏显示修复与结束逻辑详解》的详细内容,更多关于的资料请关注golang学习网公众号!

- 上一篇
- Golang通道优化:缓冲通道与无锁队列对比

- 下一篇
- Win10驱动更新失败无法启动解决方法
-
- 文章 · java教程 | 1小时前 |
- SpringBoot整合Micrometer监控MongoDB教程
- 256浏览 收藏
-
- 文章 · java教程 | 2小时前 |
- Java正则表达式教程与替换技巧
- 337浏览 收藏
-
- 文章 · java教程 | 2小时前 |
- Java注解处理器实战教程
- 108浏览 收藏
-
- 文章 · java教程 | 2小时前 |
- JenkinsJava项目自动化部署指南
- 189浏览 收藏
-
- 文章 · java教程 | 3小时前 |
- ApacheFOP字体配置教程:fop.xconf跨平台设置
- 420浏览 收藏
-
- 文章 · java教程 | 3小时前 |
- SeleniumJava快捷键操作全攻略
- 158浏览 收藏
-
- 文章 · java教程 | 3小时前 |
- Java邮件发送配置及代码详解
- 193浏览 收藏
-
- 文章 · java教程 | 4小时前 |
- Java字符串分割成单词数组方法
- 262浏览 收藏
-
- 文章 · java教程 | 4小时前 |
- Spring单例Bean管理:生命周期与优化技巧
- 117浏览 收藏
-
- 文章 · java教程 | 4小时前 |
- 缓冲流的作用是什么?如何提升IO效率?
- 106浏览 收藏
-
- 文章 · java教程 | 5小时前 |
- Elasticsearch全文检索配置与使用教程
- 419浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 511次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 499次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 千音漫语
- 千音漫语,北京熠声科技倾力打造的智能声音创作助手,提供AI配音、音视频翻译、语音识别、声音克隆等强大功能,助力有声书制作、视频创作、教育培训等领域,官网:https://qianyin123.com
- 751次使用
-
- MiniWork
- MiniWork是一款智能高效的AI工具平台,专为提升工作与学习效率而设计。整合文本处理、图像生成、营销策划及运营管理等多元AI工具,提供精准智能解决方案,让复杂工作简单高效。
- 711次使用
-
- NoCode
- NoCode (nocode.cn)是领先的无代码开发平台,通过拖放、AI对话等简单操作,助您快速创建各类应用、网站与管理系统。无需编程知识,轻松实现个人生活、商业经营、企业管理多场景需求,大幅降低开发门槛,高效低成本。
- 739次使用
-
- 达医智影
- 达医智影,阿里巴巴达摩院医疗AI创新力作。全球率先利用平扫CT实现“一扫多筛”,仅一次CT扫描即可高效识别多种癌症、急症及慢病,为疾病早期发现提供智能、精准的AI影像早筛解决方案。
- 756次使用
-
- 智慧芽Eureka
- 智慧芽Eureka,专为技术创新打造的AI Agent平台。深度理解专利、研发、生物医药、材料、科创等复杂场景,通过专家级AI Agent精准执行任务,智能化工作流解放70%生产力,让您专注核心创新。
- 733次使用
-
- 提升Java功能开发效率的有力工具:微服务架构
- 2023-10-06 501浏览
-
- 掌握Java海康SDK二次开发的必备技巧
- 2023-10-01 501浏览
-
- 如何使用java实现桶排序算法
- 2023-10-03 501浏览
-
- Java开发实战经验:如何优化开发逻辑
- 2023-10-31 501浏览
-
- 如何使用Java中的Math.max()方法比较两个数的大小?
- 2023-11-18 501浏览