我做了一个21点游戏,我想让AI玩家在拿牌之间暂停一下。我试着简单地使用Thread.sleep(x),但这会让它冻结,直到AI玩家拿完所有的牌。我知道Swing不是线程安全的,所以我看了看计时器,但我不明白如何使用计时器来实现这一点。下面是我当前的代码:
while (JB.total < 21) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
System.out.println("Oh noes!");
}
switch (getJBTable(JB.total, JB.aces > 0)) {
case 0:
JB.hit();
break;
case 1:
break done;
case 2:
JB.hit();
JB.bet *= 2;
break done;
}
}顺便说一句,hit();方法更新GUI。
发布于 2011-08-31 22:50:56
下面的代码显示了一个带有JTextArea和JButton的JFrame。当单击按钮时,计时器会重复地将事件发送到与按钮相关的actionListener (在两个按钮之间有一秒的延迟),该按钮会在当前时间后追加一行。
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.Timer;
public class TimerTest extends JFrame implements ActionListener{
private static final long serialVersionUID = 7416567620110237028L;
JTextArea area;
Timer timer;
int count; // Counts the number of sendings done by the timer
boolean running; // Indicates if the timer is started (true) or stopped (false)
public TimerTest() {
super("Test");
setBounds(30,30,500,500);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(null);
area = new JTextArea();
area.setBounds(0, 0, 500, 400);
add(area);
JButton button = new JButton("Click Me!");
button.addActionListener(this);
button.setBounds(200, 400, 100, 40);
add(button);
// Initialization of the timer. 1 second delay and this class as ActionListener
timer = new Timer(1000, this);
timer.setRepeats(true); // Send events until someone stops it
count = 0; // in the beginning, 0 events sended by timer
running = false;
System.out.println(timer.isRepeats());
setVisible(true); // Shows the frame
}
public void actionPerformed(ActionEvent e) {
if (! running) {
timer.start();
running = true;
}
// Writing the current time and increasing the cont times
area.append(Calendar.getInstance().getTime().toString()+"\n");
count++;
if (count == 10) {
timer.stop();
count = 0;
running = false;
}
}
public static void main(String[] args) {
// Executing the frame with its Timer
new TimerTest();
}
}好吧,这段代码是如何使用javax.swig.Timer对象的一个示例。与问题的特殊情况有关。用于停止计时器的if语句必须更改,显然,还必须更改actionPerformed的操作。以下片段是解决方案actionPerformed的框架:
public void actionPerformed(ActionEvent e) {
if (e.getComponent() == myDealerComponent()) {
// I do this if statement because the actionPerformed can treat more components
if (! running) {
timer.start();
runnig = true;
}
// Hit a card if it must be hitted
switch (getJBTable(JB.total, JB.aces > 0)) {
case 0:
JB.hit();
break;
case 1:
break done;
case 2:
JB.hit();
JB.bet *= 2;
break done;
}
if (JB.total >= 21) { // In this case we don't need count the number of times, only check the JB.total 21 reached
timer.stop()
running = false;
}
}
}我想这解决了这个问题,现在@user920769必须考虑把actionListener和启动/停止条件放在哪里……
@kleopatra:感谢你向我展示了这个timer类的存在,我对它一无所知,它令人惊叹,让swing应用程序中的许多任务成为可能:)
发布于 2011-08-31 11:19:58
所以我看了一下计时器,但是我不明白我怎么能用它来做这件事
定时器就是解决方案,因为正如您所说的,您正在更新GUI,这应该在EDT上完成。
我不知道你在担心什么。你发一张牌并启动计时器。当计时器响起时,你决定拿另一张牌或持有。当你按住定时器停止的时候。
发布于 2011-08-31 15:58:23
好的,关于计时器的一个快速解释。
首先,在您的类中需要一个java.util.Timer变量,在项目中还需要一个从java.util.TimerTask扩展的类(让我们称其为Tasker)。
定时器变量的初始化非常简单:
Timer timer = new Timer();现在是Tasker类:
public class Tasker extends TimerTask {
@Override
public void run() {
actionToDo(); // For example take cards
}
// More functions if they are needed
}最后,安装计时器及其相关Tasker:
long delay = 0L;
long period = pauseTime;
timer.schedule(new Tasker(),delay,period);调度函数指示以下内容: Fisrt参数:执行每个周期毫秒的操作(执行TimerTask类或其扩展的运行函数)秒参数:计时器必须启动时。在本例中,它在调用调度函数时启动。下面的示例表示在调用schedule函数后1秒开始:timer.schedule(new Tasker(),1000,period); Third param: Tasker.run()函数的一次调用与下一次调用之间的毫秒。
我希望你能理解这篇微教程:)。如果您有任何问题,请询问更详细的信息!
致以亲切的问候!
https://stackoverflow.com/questions/7251625
复制相似问题