Java 如何使两个子类在游戏中相互通信

Java 如何使两个子类在游戏中相互通信,java,swing,Java,Swing,链接: 我正在创建一个战舰游戏,有两个网格。用户将把他们的船只放在一个网格上,然后轰炸另一个网格 我有一个名为Grid的抽象类,它创建了一个10x10的单元格网格(扩展了JPanel类)。它为每个单元格提供一个侦听器,如下所示: public Grid() { setPreferredSize(new Dimension(300, 300)); setLayout(new GridLayout(GRID_SIZE,GRID_SIZE)); for (int x = 0;

链接:

我正在创建一个战舰游戏,有两个网格。用户将把他们的船只放在一个网格上,然后轰炸另一个网格

我有一个名为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);
                }
            });
        }
}
然后我有两个具体的子类——一个是“玩家网格”,另一个是“计算机网格”。主要区别在于,在播放器网格中,侦听器被立即用于放置船只。在计算机网格中,船舶自动放置(在构建类的对象时完成)

这意味着Computer grid类中的侦听器仅用于响应用户试图轰炸正方形的行为。玩家网格,一旦船只被放置,应该会被计算机自动轰炸


这就是我遇到困难的地方。我在PlayerGrid类中编写了一个名为computerAttack()的方法,但我不知道如何从类外访问它。如何使这两个子类通信?此外,这是正确的方法吗,还是我在这两门课上做得太多了?我试图在这里提供尽可能多的必要信息,但如果需要这两个子类的实际内容,我可以提供它们。

这是一个典型的应用程序,其中应用了类似的模式。一种是单独实现游戏逻辑,并用于常见用途,包括
computerAttack()
等方法。因此,游戏逻辑将包含对两个网格/玩家的引用,并且还将实现两个网格/玩家的事件接口。这样,网格就不需要相互了解

M-电网状态的内部表示(船/水、轰炸/未轰炸等)

V-GUI组件(网格、按钮、UI事件侦听器界面等)


C-游戏逻辑(在单独的类或包中实现)

也许不要单独考虑
PlayerGrid
ComputerGrid
。将它们视为网格。
网格
将保持
网格
的游戏状态。您将有一个
Grid
用于播放器,一个用于计算机

然后您可以有一个
GridListener
接口,它可以回调
Grid
上的重要事件。像
attackSuccess(intx,inty)
attackFailed(intx,inty)

因此,如果有一种类似于
Grid.attack(intx,inty)
的方法,那么它大概是:

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

游戏的整体流程是如何协调的?你们有单独的课程吗?如果不是,那可能是一个需要考虑的问题。我有一个主要的类别叫做“Mauni”。它初始化JFrame并将两个网格放置在其上的边框布局中。就这么多了。你会建议构建一个功能,一旦棋盘被设置成这样,就可以真正玩游戏吗?MVC建议的一个有趣的思想实验是“我可以不用一段GUI代码玩一个完整的战舰测试游戏吗?”。如果答案是肯定的,那么您可能已经实现了模型和视图的良好分离;引用了一个基于网格的示例。谢谢。我一直在努力学习MVC,但最近有点迷路了!MVC也是+1。我不确定仅仅提到它是否会有点抽象,但在我看来这肯定是最好的方法。作为后续,在我的两个网格类中,我有鼠标侦听器。这些用于在放置船只时在单元格中着色,但我目前有更改网格内部表示的代码,因此它知道船只放置的位置。这是属于侦听器的,还是应该抽象出来并通过方法调用来完成?还是应该在游戏逻辑类中?谢谢-有点迷路了MVC!我会这样做:按照Paul Grime的建议,创建一个自己的监听器接口,如
GridListener
。在
GridPanel
(GUI/view类)中,将
MouseEvent
s转换为
GridEvent
s。然后,让游戏控制器实现
GridListener
,它相应地修改内部
GridState
(一个单独的类),从而通过调用
GridPanel.setFieldState(int x,int y,int state)
+1:Following MVC,您的
GridListener
可以通过类似
GridPanel
的视图类来实现。除了在
网格中部分实现的逻辑(假设这是一个模型类),我同意您的回答。依我看,这些事件应该只是状态更改事件。我倾向于在单独的
ViewContoller
渲染器
,甚至是单个公共控制器中处理视图更新。
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);
    }
}