已关联:Using MouseListener to select a range of cells in a grid
我正在创建一个有两个网格的战舰游戏。用户将他们的船只放在一个网格上然后轰炸另一个网格。
我有一个名为Grid的抽象类,它创建一个10x10的单元格网格(扩展JPanel类)。它为每个单元格提供了一个监听器,如下所示:
public Grid() {
setPreferredSize(new Dimension(300, 300));
setLayout(new GridLayout(GRID_SIZE,GRID_SIZE));
for (int x = 0; x < GRID_SIZE; x++)
for (int y = 0; y < GRID_SIZE; y++) {
final Cell cell = new Cell(x, y);
cellArray[x][y] = cell;
add(cell);
cell.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent e) {
mouseClick(e, cellArray);
}
@Override
public void mouseEntered(MouseEvent e) {
mouseEnter(e, cellArray);
}
@Override
public void mouseExited(MouseEvent e) {
mouseExit(e, cellArray);
}
@Override
public void mousePressed(MouseEvent e) {
mousePress(e, cellArray);
}
@Override
public void mouseReleased(MouseEvent e) {
mouseRelease(e, cellArray);
}
});
}
}
因此可以从两个子类访问这些侦听器,侦听器调用另一个方法,如上面的代码所示。这些方法包含在构造函数中,并且都是抽象的:
public abstract void mouseClick(MouseEvent e, Cell[][] cellArray);
public abstract void mouseEnter(MouseEvent e, Cell[][] cellArray);
public abstract void mouseExit(MouseEvent e, Cell[][] cellArray);
public abstract void mousePress(MouseEvent e, Cell[][] cellArray);
public abstract void mouseRelease(MouseEvent e, Cell[][] cellArray);
然后我有两个具体的子类 - 一个用于“播放器网格”,另一个用于“计算机网格”。主要区别在于,在播放器网格中,听众立即用于放置船只。在计算机网格中,船只是自动放置的(在构建类的对象时完成)。
这意味着计算机网格类中的侦听器仅用于响应用户炸弹正方形的尝试。一旦放置了船只,播放器网格应该被计算机自动轰炸。
这是我遇到困难的地方。我在PlayerGrid类中编写了一个名为computerAttack()的方法 - 但我不知道如何从类外部访问它。如何让两个子类进行通信?另外,这是否是正确的方法,或者我是否尝试在这两个类中做太多?我试图在这里提供尽可能多的信息,但是如果需要两个子类的实际内容,我可以提供它们。
答案 0 :(得分:5)
这是一个典型的应用程序,其中应用了MVC之类的模式。人们可以单独实现游戏逻辑并实现常用,包含computerAttack()
等方法。因此,游戏逻辑将包含对网格/玩家的引用,并且还将实现两个网格/玩家的事件接口。这样,网格就不需要彼此了解。
M - 网格状态的内部表示(船舶/水,轰炸/未轰炸,......)
V - GUI组件(网格,按钮,UI事件监听器接口,......)
C - 游戏逻辑(在单独的类或包中实现)
答案 1 :(得分:1)
也许不要分别考虑PlayerGrid
和ComputerGrid
。将它们视为Grid
s。 Grid
将维持Grid
的游戏状态。您将有一个Grid
用于播放器,一个用于计算机。
然后你可以有一个GridListener
接口,它对Grid
上的重要事件进行回调。与attackSuccess(int x, int y)
和attackFailed(int x, int y)
一样。
因此,如果存在类似Grid.attack(int x, int y)
的方法,则大致为:
boolean shipRemoved = removeShipAt(x, y);
if (shipRemoved) {
// return true means that a ship was present and was removed.
for (GridListener l: gridListeners) {
l.attackSuccess(x, y);
}
} else {
// return false means that a ship was not present.
for (GridListener l: gridListeners) {
l.attackFailed(x, y);
}
}
这样,Grid
不会直接相互通信,但可以收听对方的事件。或者更高级别的游戏控制器可以监听Grid
的两个事件,并适当地通知其他Grid
。