
在提供的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号