美文网首页Java互联网科技
多人运动!挑战极限!Java模拟3人千米赛跑

多人运动!挑战极限!Java模拟3人千米赛跑

作者: Java码农石头 | 来源:发表于2020-04-26 21:13 被阅读0次

    题目:

    利用多线程技术编写模拟三个同学的一次赛跑比赛的程序,赛道长1000米,甲同学速度为0-20米/秒之间的随机数,乙同学速度为0-18米/秒之间的随机数,丙同学的速度为0-16米/秒之间的随机数。每10秒各个同学的速度更新,并刷新显示每位同学跑过的距离,直到到达终点,给出名次及各自的完成时间。

    用图形方面类似进度条画出赛道,显示三个人的比赛过程。

    效果:

    素材: (真多人运动)

    素材图片太多,全发影响排版,此处直接截图整张

    代码演示:

    暂时没追求很好的逻辑结构。

    RunFrame窗口包含三个面板,和一个开始按钮。

    每个面板绑定一个运动员,并实现Runnable接口,以此来重绘小人。

    单击开始后,?添加?或者叫?启动?线程。

    import java.awt.*;

    import java.awt.event.*;

    import java.util.Random;

    import java.util.concurrent.*;

    import javax.swing.*;

    public class _1千米赛跑 extends JFrame

    {

    public static void main(String[] args)

    {

    RunFrame rf = new RunFrame();

    }

    }

    //窗口:包含三个跑步面板,一个开始按钮:单击开始后?启动线程?

    class RunFrame extends JFrame

    {

    private int width = 1500, height = 900;

    private RunPanel rp1 = new RunPanel(0, 30, 20);

    private RunPanel rp2 = new RunPanel(0, 250, 18);

    private RunPanel rp3 = new RunPanel(0, 500, 16);

    public RunFrame()

    {

    super("千米赛跑");

    setSize(width, height);

    setLocation(50, 50);

    setResizable(false);

    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    setLayout(null);

    JButton start = new JButton("开始");

    start.setBounds(20, 10, 100, 20);

    add(start);

    add(rp2);

    add(rp1);

    add(rp3);

    setVisible(true);

    start.addActionListener(new ActionListener()

    {

    public void actionPerformed(ActionEvent e)

    {

    start.setEnabled(false); //单击后不可再单击

    //?启动线程????:

    ExecutorService exec = Executors.newCachedThreadPool();

    exec.execute(rp1);

    exec.execute(rp2);

    exec.execute(rp3);

    exec.shutdown();

    }

    });

    }

    }

    //运动员类:包含最大速度、当前速度、

    class Runner

    {

    private int maxSpeed; // 最大速度

    public int speed; // 当前速度

    public int time; // 记录每5s,即5000ms更换一次速度

    public int basex, basey;

    public double x, y;

    // 在界面中的初始位置,和当前位置。最开始都站在最左边,从上到下

    // 实际上 直跑道 从左向右跑,y是不变的

    public double distance = 1000; // 剩余距离

    private Random rd = new Random(); // 随机速度

    public static Image[] image = new Image[8];

    public int id = 0; // 第几张图

    public Runner(double x, double y, int maxS)

    {

    this.basex = (int) x;

    this.x = x;

    this.basey = (int) y;

    this.y = y;

    maxSpeed = maxS;

    for(int i = 0; i < 8; ++i) image[i] = new ImageIcon("E:\\run_0" + (i + 1) + ".jpg").getImage();

    }

    public void changeSpeed()

    {

    speed = rd.nextInt(maxSpeed + 1);

    // 左闭右开,[0,maxSpeed+1)

    }

    }

    //RunPanel显示小人和路线,每个RunPanel绑定一个运动员,可以获取Runner类的相关信息

    class RunPanel extends JPanel implements Runnable

    {

    private int width = 1500, height = 200; //面板的长宽

    private int x, y; //面板在窗口中的坐标

    private Runner runner; //绑定运动员

    //凡是xxL:Label,凡是xxT:TextField:

    //速度、已跑、用时:

    private JLabel speedL = new JLabel("当前速度m/s:"), lengthL = new JLabel("已跑距离m:"), timeL = new JLabel("已用时s:");

    private JTextField speedT = new JTextField(10), lengthT = new JTextField(10), timeT = new JTextField(10);

    //加速,可选的

    private JButton accelerate = new JButton("加速");

    //构造函数:

    public RunPanel(int x, int y, int maxS)

    {

    this.x = x;

    this.y = y;

    setSize(width, height);

    setLocation(x, y);

    setBackground(Color.white); //小人图片背景是白色的,所以面板设置为白色背景

    runner = new Runner(100, 50, maxS); //运动员,在该面板的起始坐标和最大速度

    //time 是更换速度的计时,设置为一个较大的数,保证开始时即换速,换速的同时更新speedT:

    //不过重点在更新speedT,因为要保证点开始按钮后,再给runner一个速度,并立即在speedT中显示这个速度

    runner.time = 9900;

    //不可编辑:

    speedT.setEditable(false);

    lengthT.setEditable(false);

    timeT.setEditable(false);

    //添加各组件:

    add(accelerate);

    add(speedL);

    add(speedT);

    add(lengthL);

    add(lengthT);

    add(timeL);

    add(timeT);

    //已跑距离和耗时最开始是0:

    lengthT.setText("0.00");

    timeT.setText("0.00");

    //加速并更新TextField:

    accelerate.addActionListener(new ActionListener()

    {

    public void actionPerformed(ActionEvent e)

    {

    if(!speedT.getText().equals(""))

    {

    runner.speed += 10;

    speedT.setText(Integer.parseInt(speedT.getText()) + 10 + "");

    }

    }

    });

    }

    //根据runner的坐标画路线和小人:

    public void paintComponent(Graphics g)

    {

    super.paintComponent(g);

    g.drawLine(runner.basex, runner.basey, (int) runner.x, (int) runner.y);

    g.drawImage(Runner.image[runner.id++], (int) runner.x, (int) runner.y, this);

    }

    public void run()

    {

    //还没跑完:

    while(runner.distance > 0)

    {

    try

    {

    TimeUnit.MILLISECONDS.sleep(100); //休眠100ms

    //每5s更换速度,time清零,准备下一个5s:

    runner.time += 100;

    if(runner.time >= 5000)

    {

    runner.changeSpeed(); //换速

    runner.time = 0; //清零

    speedT.setText("" + runner.speed); //更新speedT

    }

    runner.distance -= runner.speed * 0.1; //剩余距离更新

    runner.x += runner.speed * 0.1; //当前x坐标更新

    //已跑和耗时更新:

    lengthT.setText(String.format("%.2f", Double.parseDouble(lengthT.getText()) + runner.speed * 0.1));

    timeT.setText(String.format("%.2f", Double.parseDouble(timeT.getText()) + 0.1));

    repaint(); //画小人和路线

    //小人图片共8张,id在paint()中会+1,在这儿也可以,这一行放在paint()里应该也行:

    runner.id = runner.id % 8;

    }

    catch(InterruptedException e)

    {

    e.printStackTrace();

    }

    }

    }

    }

    原文链接:https://blog.csdn.net/weixin_43359009/article/details/105729012

    相关文章

      网友评论

        本文标题:多人运动!挑战极限!Java模拟3人千米赛跑

        本文链接:https://www.haomeiwen.com/subject/rbcswhtx.html