英文:
JAVA: How can I make this work without using thread?
问题
public class CarGame extends JFrame {
class MyThread extends Thread{
private JLabel label;
private int x, y;
public MyThread(String fname, int x, int y) {
this.x = x;
this.y = y;
label = new JLabel();
label.setIcon(new ImageIcon(fname));
label.setBounds(x, y, 100, 100);
add(label);
}
public void run() {
for (int i=0; i<200; i++) {
x += 10 * Math.random();
label.setBounds(x, y, 100, 100);
repaint();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public CarGame() {
setTitle("Car Race");
setSize(600, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(null);
(new MyThread("car1.gif", 100, 0)).start();
(new MyThread("car2.gif", 100, 50)).start();
(new MyThread("car3.gif", 100, 100)).start();
setVisible(true);
}
public static void main(String[] args) {
CarGame t = new CarGame();
}
}
(Note: The provided code is the same as the original code you provided. If you want assistance in modifying the code to work without using threads, please let me know.)
英文:
public class CarGame extends JFrame {
class MyThread extends Thread{
private JLabel label;
private int x, y;
public MyThread(String fname, int x, int y) {
this.x = x;
this.y = y;
label = new JLabel();
label.setIcon(new ImageIcon(fname));
label.setBounds(x, y, 100, 100);
add(label);
}
public void run() {
for (int i=0; i<200; i++) {
x += 10 * Math.random();
label.setBounds(x, y, 100, 100);
repaint();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public CarGame() {
setTitle("Car Race");
setSize(600, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(null);
(new MyThread("car1.gif", 100, 0)).start();
(new MyThread("car2.gif", 100, 50)).start();
(new MyThread("car3.gif", 100, 100)).start();
setVisible(true);
}
public static void main(String[] args) {
CarGame t = new CarGame();
}
}
Hi, I'm a university student and I got a question while studying JAVA.
I want to make this Car Game works without using any thread.
Please help me!
Thank you
答案1
得分: 1
创建一个对象来保存每辆汽车的状态。将所有汽车放入一个列表中,并迭代它200次:
import java.util.Arrays;
import java.util.List;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class CarGame extends JFrame {
class Car {
private JLabel label;
private int x, y;
public Car(String fname, int x, int y) {
this.x = x;
this.y = y;
label = new JLabel();
label.setIcon(new ImageIcon(fname));
label.setBounds(x, y, 100, 100);
add(label);
}
public void move() {
x += 10 * Math.random();
label.setBounds(x, y, 100, 100);
repaint();
}
}
public CarGame() {
setTitle("Car Race");
setSize(600, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(null);
List<Car> cars=Arrays.asList(new Car("car1.gif", 100, 0),new Car("car2.gif", 100, 50),new Car("car3.gif", 100, 100));
setVisible(true);
for(int i=0;i<200;i++) {
cars.forEach(car->car.move());
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
CarGame t = new CarGame();
}
}
您将始终有一个线程。
注:出于这个目的,使用Thread.sleep()并不是一个很好的方法,因为它会阻塞线程的其他工作。更好的做法是使用一个定时器,每隔100毫秒触发一次,并调用cars.foreach(…)
。当第一(或最后)辆汽车到达终点时,可以取消定时器。(感谢@JoopEggen提供的有效评论)
为了完整性(并且因为这很有趣):一个没有线程但有以下特点的版本:
- 使用javax.swing.Timer,在所有汽车完成后停止。
- 计算每辆车的最终位置。
- 为那些没有汽车GIF图像的人显示文本。
import java.util.Arrays;
import java.util.List;
import javax.swing.Timer;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class CarGame extends JFrame {
int width = 600;
int position = 1;
class Car {
private JLabel label;
private int x, y;
public Car(String fname, int x, int y) {
this.x = x;
this.y = y;
label = new JLabel(fname + ">");
label.setIcon(new ImageIcon(fname + ".gif"));
label.setBounds(x, y, 100, 100);
add(label);
}
public boolean move() {
if (!finished()) {
x += 10 * Math.random();
label.setBounds(x, y, 100, 100);
if (finished())
label.setText(label.getText() + "[" + (position++) + "]");
}
return finished();
}
public boolean finished() {
return x > width;
}
}
public CarGame() {
setTitle("Car Race");
setSize(width + 100, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(null);
List<Car> cars = Arrays.asList(new Car("car1", 100, 0), new Car("car2", 100, 50),
new Car("car3", 100, 100));
setVisible(true);
Timer timer = new Timer(100, null);
timer.addActionListener(e -> {
// 计算未完成的汽车数量
if (cars.stream().map(car -> car.move()).filter(b -> !b).count() == 0)
timer.stop();
});
timer.start();
}
public static void main(String[] args) {
new CarGame();
}
}
英文:
Create an object for every car which holds its state. Put all cars in a list and iterate over it 200 times:
import java.util.Arrays;
import java.util.List;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class CarGame extends JFrame {
class Car {
private JLabel label;
private int x, y;
public Car(String fname, int x, int y) {
this.x = x;
this.y = y;
label = new JLabel();
label.setIcon(new ImageIcon(fname));
label.setBounds(x, y, 100, 100);
add(label);
}
public void move()
{
x += 10 * Math.random();
label.setBounds(x, y, 100, 100);
repaint();
}
}
public CarGame() {
setTitle("Car Race");
setSize(600, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(null);
List<Car> cars=Arrays.asList(new Car("car1.gif", 100, 0),new Car("car2.gif", 100, 50),new Car("car3.gif", 100, 100));
setVisible(true);
for(int i=0;i<200;i++)
{
cars.forEach(car->car.move());
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
CarGame t = new CarGame();
}
}
You will always have one thread.
Remark: using Thread.sleep() for this purpose is not such a good idea as it will block the thread from doing other work. Better would be to use a timer which is triggered every 100ms and calls the cars.foreach(…)
. Off course this would result in a second thread. The timer can be canceled once the first (or last) car reaches the finish. (thanks to @JoopEggen for the valid comment)
For completeness (and because it was fun to do): a version without threads but with :
- javax.swing.Timer which stops after all cars finished.
- counts the final position of each car
- displays a text for those like who don't have a car gif.
import java.util.Arrays;
import java.util.List;
import javax.swing.Timer;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class CarGame extends JFrame {
int width = 600;
int position=1;
class Car {
private JLabel label;
private int x, y;
public Car(String fname, int x, int y) {
this.x = x;
this.y = y;
label = new JLabel(fname+">");
label.setIcon(new ImageIcon(fname+".gif"));
label.setBounds(x, y, 100, 100);
add(label);
}
public boolean move() {
if (!finished()) {
x += 10 * Math.random();
label.setBounds(x, y, 100, 100);
if(finished())
label.setText(label.getText()+"["+(position++)+"]");
}
return finished();
}
public boolean finished() {
return x > width;
}
}
public CarGame() {
setTitle("Car Race");
setSize(width+100, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(null);
List<Car> cars = Arrays.asList(new Car("car1", 100, 0), new Car("car2", 100, 50),
new Car("car3", 100, 100));
setVisible(true);
Timer timer=new Timer(100,null);
timer.addActionListener(e-> {
// count the number of non-finished cars
if(cars.stream().map(car -> car.move()).filter(b->!b).count()==0)
timer.stop();
});
timer.start();
}
public static void main(String[] args) {
new CarGame();
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论