2016-08-02 63 views
-1

我对Java中的某些中间概念相当陌生。最近我做了一个名为DazzleQuest的文本冒险游戏,它完全在开发者控制台/终端中运行。它让我的朋友们成为角色,所以我想通过将命令行和控制台输出的功能转移到一个简单的Swing界面中,让他们看到他们并获得Java体验,包括一个JTextArea以显示游戏输出和一个JTextField,与ActionListener,处理来自用户的命令。将Swing集成到一个简单的文本冒险游戏中

我的主要DazzleQuest类包含的方法称为run()handleCommand(),我想我需要用我的Frame类和它的子类TextFieldHandler [延伸ActionListener]集成。 我在想,一般来说,整合这些方法和类的最好方法是什么。我目前的尝试一直令人困惑,尽管我对如何让不同的课程和方法进行沟通有基本的把握,但这是暂定的。

道歉的单调性和缺乏特异性。我会分享我的代码,但我不确定要给出多少和确切的内容。如果你认为你可以回答我的问题,但需要我的例子,请说出来。即使伪代码作为答案,将不胜感激。谢谢!了解这可能对我作为程序员的教育非常有帮助。

编辑:这里是我完全在开发人员控制台中运行的游戏版本的代码简化示例。这是我的主要DazzleQuest类:

public class DazzleQuest { 

public void run() { 
    listCommands(); 
    for (;;) { 
     StdOut.println(new StringBuilder("You are in ").append(currentRoom.getName()).append(".").toString()); 
     StdOut.println(new StringBuilder("You can go to: ").append(currentRoom.listExits()).toString()); 
     StdOut.print("> "); 
     handleCommand(StdIn.readLine()); 
     StdOut.println(); 
    } 

public void handleCommand(String line) { 
     String[] words = line.split(" "); 
     if (words[0].equals("look")) 
      look(); 
     } 
    } 

} 

这里是我目前的JFrame设置,在Frame类:

import java.awt.FlowLayout; 

import javax.swing.JFrame; 
import javax.swing.JTextField; 
import javax.swing.JTextArea; 

import java.awt.event.ActionListener; 
import java.awt.event.ActionEvent; 

public class Frame extends JFrame { 

    public static JTextField field; 
    public JTextArea area; 

    public Frame() { 
     setLayout(new FlowLayout()); 

     area = new JTextArea(20, 40); 
     area.setEditable(false); 

     field = new JTextField(20); 
     add(area); 
     add(field); 
     pack(); 
     setVisible(true); 

     TextFieldHandler handler = new TextFieldHandler(); 

      field.addActionListener(handler); 
     } 

     public class TextFieldHandler implements ActionListener{ 

      public void actionPerformed(ActionEvent event) 
      { 
       String line = field.getText(); 
       area.append(line + "\n"); 
       field.setText(""); 
      } 
     } 


    public static void main(String args[]) { 

     Frame test = new Frame(); 
     test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    } 
} 

我知道如何打印输出到JTextArea,而不是到控制台。我的问题是如何得到handleCommand()Frame类中使用actionPerformed(),或者我应该在主类中设置一个动作侦听器或类似的东西。任何实施的例子将不胜感激。

再次感谢您的任何事情,你可以告诉我!

回答

2

首先,关于包含代码,您应该查看https://stackoverflow.com/help/mcve以了解如何帮助我们为您提供帮助。

现在,考虑到你还没有提供任何代码(还!)给出你应该如何构建你的程序的建议是有点棘手。但是,无论如何我会进行一次尝试,并在您提供MWE时编辑答案。

在你的情况下,JTextArea真的只是一个看中System.out.print因为你只会用它来显示冒险游戏输出的文本(如果我正确理解你的话)。所以基本上,您可以编写一个接受字符串的方法,该方法会将该字符串附加到您的JTextArea。然后用这个方法替换你当前的输出行。

然后你有你的JTextField你想替换你的(我猜)Scanner(System.in)与。我假设您知道如何设置响应Entersubmit按钮的动作侦听器。 如何设置这些并不奇怪,很多指南都会讨论如何去做。 https://docs.oracle.com/javase/tutorial/uiswing/components/textfield.html就是一个很好的例子。

现在,在一般的关于你的程序的结构。 你做要依赖于用户如何进入文本或你如何显示它。我的意思是,你不希望输入或显示逻辑干扰你的游戏(业务)的逻辑。你的游戏逻辑应该从任何地方接收输入,并将其输出到任何地方。如何以及调用函数决定如何处理这些信息并不是游戏逻辑关心的。

因此,应用于您发布的方法名称。我认为run()是你踢球的地方。当你有,你总是想显示输出,你可能想在interface这里有这应该是打印文本到任何文本元素,用于显示文本的方法方法print(string)(等)通过,无论是System.out还是JTextArearun()方法永远不需要知道。 handleCommand()也应该只接受一个值(我假设一个字符串),并处理它应该像它应该,不管是谁或什么叫它。

我无法给你,没有代码的意见。但是我的一般建议是:不要将表示逻辑与业务逻辑混合在一起。并且尽可能少地给每种方法提供信息,因为给予他们比实际需要的更多的信息通常会导致流程和结构的灵活性降低。


现在编辑一些代码已被添加。

我知道如何将输出打印到JTextArea而不是控制台。我的问题是如何获得handleCommand()与Frame类中的actionPerformed()一起使用

使用actionPerformed()方法。我建议这样做,因为如果你决定在将来某个时候(多人游戏)决定使用Thread,那么你就不必费尽心机。 https://docs.oracle.com/javase/tutorial/uiswing/events/actionlistener.html给出了一些关于如何编写监听器的好信息。但我也会给你一些建议代码。

... 
area.setEditable(false); 

field = new JTextField(20); 
field.addActionListener(new SendText());  
.... 

class SendText implements ActionListener{ 
    public void actionPerformed(ActionEvent ae){ 
     if(ae.getSource() == field){ 
      String str = field.getText(); 
      if(!str.equals("")){ 
       commandHandler.handle(str); 
      } 
     } 
    } 
} 

然后重写你的run()方法

public void run(){ 
    ui.print(commandHandler.listCommands()); 

    while(true){ 
     if(commandHandler.continue()){ 
      ui.print(commandHandler.events()); 
     } 
    } 
} 

所以,现在你有没有真正的搭配要么逻辑或显示一个非常小的run()方法。 ui.print(str)是一种方法,你UI类(Frame你的情况),只是什么附加给它的绘图区域曾经串发送给它的,是它System.outJTextArea

commandHandler是新的。这是你的游戏逻辑应该在的地方。它有一个方法handle(string)这是你的旧handleCommand(string)。它有一个返回布尔值的方法continue()。无论何时您希望故事继续,布尔值应该设置为true,例如,当用户输入命令时。最后是events()(这是一个不好的名字),它返回自从发送上一个命令后发生的事情,并为用户提供关于下一步做什么的选项。我没有完成这个,因为我只是想把这个概念给你。用户界面不执行任何逻辑处理。 run()方法不期望任何东西,它只是继续检查是否continue()为真。commandHandler是所有bizz的地方。

现在,你确实有一个无限循环运行。所以如果你有任何性能问题,你可以看看Thread。这个模型应该支持它。

+0

非常感谢您的回答!演示文稿和业务逻辑的分离对我来说是一个有趣的主题 - 我曾经做过一个游戏,其中包含游戏规则和逻辑的“Model”类与包含显示方法,控件的主游戏类分离以及游戏的开始和结束。这是你的意思吗?我将尝试明天复制我的实现示例,并提供更具体的建议。 – speers

+0

@speers是的。这听起来像我的意思。 [MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller)模式非常标准,并有很好的理由。它使得更换用户界面变得更加容易,而不会改变执行数据处理的逻辑。 – Chewtoy

+0

我会牢记这一点。我目前的程序非常简单,我想我可以很容易地将模型与显示分开,但是在我已经想出如何使其在GUI中运行后,可能会这样做。我只是用代码示例更新了我的帖子,所以如果你可以再看一看,那将是非常棒的! – speers