java 实现多人在在线编辑 开源框架 java多人游戏_模拟java


题目:

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

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

效果:


java 实现多人在在线编辑 开源框架 java多人游戏_Image_02


素材:


java 实现多人在在线编辑 开源框架 java多人游戏_java_03


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

代码演示:

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

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();
            }
        }
    }
}