在一个简单的文本冒险游戏中集成Swing

我对Java中的一些中间概念相当新。 最近我制作了一款名为DazzleQuest的文本冒险游戏,完全在开发者控制台/终端中运行。 它涉及我的朋友作为角色所以我想向他们展示并通过将命令行的function和控制台的输出转移到由JTextArea组成的简单Swing界面以显示游戏的输出和JTextField来获得Java经验,使用ActionListener来处理来自用户的命令。

我的主要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(); } } } 

这是我在Frame类中的当前JFrame设置:

 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() ,或者我是否应该在主类或类似的东西中设置一个动作监听器。 任何实施的例子都将非常感谢。

再次感谢你能告诉我的任何事情!

首先,关于包含代码,您应该查看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 ,该interface具有print(string) (或类似)方法,该接口应该是将文本打印到用于的任何text-element的方法显示文本,无论是System.out还是JTextArearun()方法永远不需要知道。 handleCommand()也应该只接受一个值(我假设一个String)并按照它应该处理它,无论是谁调用它。

没有代码,我很难给你更多的建议。 但我的一般建议是:不要将表示逻辑与业务逻辑混合在一起。 并且尽可能少地给每个方法提供信息,因为给予它们超过它们实际需要的量通常会导致流动性和结构不那么灵活。


编辑现在添加了一些代码。

我知道如何将输出打印到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.out还是JTextArea

commandHandler是新的。 这是你的游戏逻辑应该在的地方。 它有一个方法handle(string) ,它是你的旧handleCommand(string) 。 它有一个返回布尔值的continue()方法。 每当您希望故事继续时,布尔值应设置为true,例如,当用户输入命令时。 最后, events() (这是一个坏名称)返回自上一个命令发送以来发生的事情,并为用户提供下一步操作的选项。 我没有做过那样的实现,因为我只是想给你这个概念。 UI不进行任何逻辑处理。 run()方法没有任何期望,它只是继续检查continue()是否为true。 commandHandler是所有bizz的所在。

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