Java MVC - 如何将已完成的文字游戏划分为MVC模式?

9

我已经坐在这里几个小时了,试图弄清楚这个问题,所以请对这个大问题给予一点同情。:)

目标:我只是想将我的代码划分为MVC(模型视图控制器)部分。我已经完成了游戏逻辑和基于文本的部分 - 代码运行良好。

问题:那么,我想将这个代码实现到MVC中,但是在哪里解释MODEL应该使用基于文本的方式?因为VIEW仅用于布局(图形上)正确?我真的很难找到从何处开始的方向。任何指针都会很好!

这是我的游戏逻辑代码:

import mind.*;
import javax.swing.*;
import java.util.*;
import java.lang.*;
import java.awt.*;

public class Drive {
String[] mellan;
boolean gameEnd, checkempty, checkempty2, enemy, enemy2;
String gr,rd,tom;
int digits;

public Drive() {
    // Gamepieces in textform
    gr="G"; rd="R"; tom=" ";


    mellan = new String[7];
    String[] begin = {gr,gr,gr,tom,rd,rd,rd};
    String[] end = {rd,rd,rd,tom,gr,gr,gr};

    //input
    Scanner in = new Scanner(System.in);

    mellan=begin;
    gameEnd=false;
    while (gameEnd == false) {
        for(int i=0; i<mellan.length; i++) {
            System.out.print(mellan[i]);
        }
        System.out.print("        Choose 0-6: ");

        digits = in.nextInt();
        move();
        checkWin();
    }
}

void move() {
    //BOOLEAN for gameruls!!!
    checkempty = digits<6 && mellan[digits+1]==tom;
    checkempty2 = digits>0 && mellan[digits-1]==tom;
    enemy = (mellan[digits]==gr && mellan[digits+1]==rd &&     mellan[digits+2]==tom);
    enemy2 = (mellan[digits]==rd && mellan[digits-1]==gr && mellan[digits-2]==tom);

    if(checkempty) {
        mellan[digits+1]=mellan[digits];
        mellan[digits]=tom;
    } else if (checkempty2) {
        mellan[digits-1]=mellan[digits];
        mellan[digits]=tom;
    } else if (enemy) {
        mellan[digits+2]=mellan[digits];
        mellan[digits]=tom;
    } else if (enemy2) {
        mellan[digits-2]=mellan[digits];
        mellan[digits]=tom;
    }
}

void checkWin() {
    String[] end = {rd,rd,rd,tom,gr,gr,gr};
    for (int i=0; i<mellan.length; i++){
    }
    if (Arrays.equals(mellan,end)) {
        for (int j=0; j<mellan.length; j++) {
            System.out.print(mellan[j]);
        }
        displayWin();
    }
}

void displayWin() {
    gameEnd = true;
    System.out.println("\nNicely Done!");
    return;
}

// Kör Drive!
public static void main(String args[]) {
    new Drive();
}
}

这是我迄今为止定义DriveView的方式:(只是尝试让一个按钮工作)

import mind.*;
import javax.swing.*;
import java.util.*;
import java.lang.*;
import java.awt.*;
import java.awt.event.*;

public class DriveView extends JFrame {
JButton ruta1 = new JButton("Green");
JButton ruta2 = new JButton("Green");
JButton rutatom = new JButton("");
JButton ruta6 = new JButton("Red");
private DriveModel m_model;

public DriveView(DriveModel model) {
    m_model = model;

    //Layout for View
    JPanel myPanel = new JPanel();
    myPanel.setLayout(new FlowLayout());
    myPanel.add(ruta1);
    myPanel.add(ruta2);
    myPanel.add(rutatom);
    myPanel.add(ruta6);
    this.setContentPane(myPanel);
    this.pack();
    this.setTitle("Drive");
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

void addMouseListener(ActionListener mol) {
    ruta2.addActionListener(mol);
}

同时,DriveController在编译时出现错误。

import mind.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.lang.*;

public class DriveController {
private DriveModel m_model;
private DriveView m_view;

public DriveController(DriveModel model, DriveView view) {
    m_model = model;
    m_view = view;

    view.addMouseListener(new MouseListener());
}

class MouseListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        String mening;
        mening = e.getActionCommand();
        if (mening.equals("Green")) {
            setForeground(Color.red);
        }
    }
}

}

2个回答

17
你的游戏模型可以有多个视图:GUI视图、控制台视图、状态视图等。通常每个视图都会监听模型的变化,并查询模型以获取渲染其特定视图所需的信息。这个简单的game是专门为了说明概念而设计的。名为“设计”的部分详细阐述了更多内容。
补充说明:这个大纲大致对应于下面所表示的architecture

MVC diagram

public class MVCOutline {

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            //@Override
            public void run() {
                new MVCOutline().create();
            }
        });
    }

    private void create() {
        JFrame f = new JFrame("MVC Outline");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new MainPanel());
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

class MainPanel extends JPanel {

    public MainPanel() {
        super(new BorderLayout());
        Model model = new Model();
        View view = new View(model);
        Control  control = new Control(model, view);
        this.add(view, BorderLayout.CENTER);
        this.add(control, BorderLayout.WEST);
    }
}

class Control extends JPanel implements ... {

    private Model model;
    private View view;

    public Control(Model model, View view) {
        this.model = model;
        this.view = view;
    }
}

class View extends JPanel implements Observer {

    private Model model;

    public View(Model model) {
        this.model = model;
        model.addObserver(this);
    }

    public void update(Observable o, Object arg) {
        // update GUI based on model
    }
}

class Model extends Observable {

    public void next() {
        this.notifyObservers(...);
    }
}

感谢您的回复,trashgod。有一件事让我有点困惑,例如,假设我已经创建了DriveModel.java、DriveView.java、DriveController.java和一个主要的DriveMVC.java...为了确保一切正常工作,当我运行DriveMVC.java时,终端会让我先进行文本视图,然后自动启动GUI视图吗?我一回家就会查看您的链接!谢谢! - Zopyrus
很好,我在上面添加了一个大纲。 - trashgod
1
请参考此相关示例 - trashgod
1
我的理解是控制器应该只是动作监听器,为什么你的示例中控制器要扩展JPanel? - Koray Tugay
这个视图 = 视图; <- 耦合的视图/控制器 - Yousha Aleayoub
显示剩余2条评论

2
为了更加通俗易懂,我建议你创建一个游戏状态bean来表示当前游戏的状态,这将是一个“模型对象”。根据您的代码,它可能包含字符串[] mellan。然后,您需要创建一个数据访问对象,其中包含对游戏状态bean的引用,并且该对象具有更新游戏状态的方法。
不同操作的游戏逻辑应该在服务对象中,该服务对象具有对数据访问对象的引用,而控制器则具有对服务对象的引用。根据从界面(视图)接收到的交互,控制器会调用不同的操作方法。
总之,这种方式可能有些冗余。

+1 对于绑定属性的赞赏,它是实现MVC中观察者模式的一种方式。抱歉之前我忽略了这一点。 - trashgod

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接