在提供的java记忆游戏代码中,存在两个主要问题导致游戏无法按预期运行:
此外,Domino类中原有的equals方法也存在逻辑错误,它比较的是top == bottom,这实际上是检查多米诺牌是否为双牌(如[1|1]),而不是比较两个不同的Domino对象是否相等。
针对上述问题,我们需要对Domino类和MemoryLane类进行修改。
为了使MemoryLane类中的guess方法能够正确地比较两个Domino对象的内容(即它们的top和bottom值),我们需要在Domino类中重写equals(Object obj)方法。同时,根据Java的约定,如果重写了equals()方法,就必须同时重写hashCode()方法,以确保对象在哈希表(如HashMap、HashSet)中能正确工作,并维护equals和hashCode之间的契约:如果两个对象通过equals()方法比较为相等,那么它们的hashCode()方法必须返回相同的值。
Domino 类修改示例:
立即学习“Java免费学习笔记(深入)”;
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; // 所有属性都匹配,则认为对象相等 } }
注意事项:
在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"); } }
通过以上修改,我们解决了记忆游戏中的核心逻辑问题:
这个案例强调了在Java中处理自定义对象比较时,正确重写equals()和hashCode()方法的重要性,以及理解对象状态管理在游戏逻辑中的关键作用。
以上就是Java 记忆游戏多米诺牌显示与游戏结束逻辑修复教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号