利用多线程写一个龟兔赛跑游戏

代码地址:src · master · 小肖在路上 / ider · GitCode

直接克隆就好了

我来说一下大致思路:

1.利用swing创建窗口,开始按钮,复原按钮,乌龟图片、兔子图片

2.点击开始进行游戏,再次点击暂停游戏,再次点击继续游戏,点击复原按钮回到起点

2.获取到兔子和乌龟的x坐标,创建两个线程每次加0~5随机,每加完一次休眠0~500毫秒

3.当有其中一个到达终点时,停止游戏,点击复原再点击开始可以再次开始

创建窗口代码如下:

 private void initialize() {
        frame = new JFrame();
        frame.setBounds(200, 100, 500, 500);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(null);
        frame.setTitle("龟兔赛跑");
        //乌龟图片
        wuGui = new JLabel(new ImageIcon("src\\wg1.png"));
        wuGui.setBounds(0, 102, 100, 100);
        frame.getContentPane().add(wuGui);

        //兔子图片
        tuZi = new JLabel(new ImageIcon("src\\tz1.png"));
        tuZi.setBounds(0, 271, 100, 100);
        frame.getContentPane().add(tuZi);
        Thread wg = null;
        initializationWgThread(wg, false);
        Thread tz = null;
        initializationTzThread(tz, false);
        //开始按钮
        JButton kaiShi = new JButton("开始");
        kaiShi.setFont(new Font("宋体", Font.BOLD, 30));
        kaiShi.setBounds(150, 10, 100, 54);
        kaiShi.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (buttons) {
                    buttons = false;
                    isVictory = false;
                    initializationWgThread(wg, true);
                    initializationTzThread(tz, true);
                } else {
                    String t = kaiShi.getText();
                    if (t.equals("开始")) {
                        state = true;
                        kaiShi.setText("暂停");
                    } else {
                        state = false;
                        continues();
                        kaiShi.setText("开始");
                    }
                }

            }
        });
        frame.getContentPane().add(kaiShi);

        //复原按钮
        JButton fuYuan = new JButton("复原");
        fuYuan.setFont(new Font("宋体", Font.BOLD, 30));
        fuYuan.setBounds(260, 10, 100, 54);
        frame.add(fuYuan);
        fuYuan.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                wuGui.setBounds(0, 102, 100, 100);
                tuZi.setBounds(0, 271, 100, 100);
            }
        });
}

代码也很好理解,主要是开始按钮这里:

我给了一个标识量: buttons

作用于表示本次点击是开始游戏还是暂停游戏

        点击时标识量为true:开始游戏,调用初始化乌龟、兔子的线程方法

        点击时标识量为false:

        判断当前按钮的汉字,为“开始”时,改变为“暂停”,调用暂停游戏的方法,原理就是利用Object的 wait()方法,暂停该线程,等待解开。

        按钮名字为“暂停”时,调用继续游戏方法,利用Object的notifyAll()方法解开被暂停的线程,由于时暂停了两个线程,所以要调用notifyAll()方法,而不是notify()方法,因为notify()方法只能一次解开一个线程,所以会导致一个在动,另一个不动的bug。

继续游戏方法:

 private void continues() {
        synchronized (lock) {
            lock.notifyAll();
        }
    }

 暂停游戏方法:

  private void pause() {
        synchronized (lock) {
            try {
                lock.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

复原按钮:

点击复原乌龟、兔子的位置,但是不停止游戏、

 我认为我这个程序最值得注意的一点是:

当游戏结束时,我们点击复原,再点击开始还能继续游戏,本来我原始时直接调用乌龟和兔子的开始线程方法,不过很显然是错的,因为一个线程不允许调用启动两次,所以我就把他们封装为一个初始化方法,每次新游戏是创建两个新的线程,这样就实现的二次游戏的目的。

 private void initializationTzThread(Thread tz, boolean isYes) {
        tz = new Thread() {
            @Override
            public void run() {
                while (!isVictory) {
                    if (state) {
                        pause();
                    }
                    double x = tuZi.getBounds().getX();
                    tuZi.setBounds(((int) x) + r.nextInt(11) + testSpeed, 271, 100, 100);
                    if (tuZi.getBounds().getX() >= 400) {
                        synchronized (r) {
                            if (isVictory == false) {
                                isVictory = true;
                                JOptionPane.showMessageDialog(null, "兔子胜利", "游戏结束", JOptionPane.YES_NO_OPTION);
                                buttons = true;
                            }
                        }
                        break;
                    }
                    try {
                        //距离大于50时,兔子会睡觉5秒
                        int s = (int) (tuZi.getBounds().getX() - wuGui.getBounds().getX());
                        if (s >= 50) {
                            Thread.sleep(5000);
                        }
                        Thread.sleep((r.nextInt(6)) * 100);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        if (isYes) {
            tz.start();
        }
    }

    /**
     * @initializationWgThread 乌龟线程初始化
     */
    private void initializationWgThread(Thread wg, boolean isYes) {
        wg = new Thread() {
            @Override
            public void run() {
                while (!isVictory) {
                    if (state) {
                        pause();
                    }
                    double x = wuGui.getBounds().getX();
                    wuGui.setBounds(((int) x) + r.nextInt(6) + testSpeed, 102, 100, 100);
                    if (wuGui.getBounds().getX() >= 400) {
                        synchronized (r) {
                            if (isVictory == false) {
                                isVictory = true;
                                JOptionPane.showMessageDialog(null, "乌龟胜利", "游戏结束", JOptionPane.YES_NO_OPTION);
                                buttons = true;
                            }
                        }
                        break;
                    }
                    try {
                        Thread.sleep(150);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        };
        if (isYes) {
            wg.start();
        }
    }

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
龟兔赛跑一个经典的多线程问题,它可以用来展示多线程的基本概念和原理。在这个问题中,龟兔两个角色同时在赛道上奔跑,龟速度慢但坚持不懈,兔速度快但容易骄傲自满。我们可以通过多线程技术来实现这个问题,让龟和兔各自成为一个线程,同时在赛道上奔跑。 Java中实现多线程有两种方式: 1. 继承Thread并重run()方法 2. 实现Runnable接口,并实现其run()方法 下面是一个简单的龟兔赛跑多线程程序的Java实现示例: ```java public class TortoiseAndHare implements Runnable { private String winner = null; @Override public void run() { for (int i = 1; i <= 100; i++) { // 判断是否有胜者 if (Thread.currentThread().getName().equals("兔子") && i % 10 == 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + "跑了" + i + "步"); // 判断是否有胜者 if (this.isWinner(i)) { break; } } } private boolean isWinner(int steps) { if (winner != null) { // 已经有胜者了 return true; } if (steps == 100) { // 判断是否已经到终点 winner = Thread.currentThread().getName(); System.out.println("胜利者是:" + winner); return true; } return false; } public static void main(String[] args) { TortoiseAndHare race = new TortoiseAndHare(); Thread tortoise = new Thread(race, "乌龟"); Thread hare = new Thread(race, "兔子"); tortoise.start(); hare.start(); } } ``` 这个程序中,我们实现了Runnable接口,并在run()方法中下了每个角色的跑步逻辑,同时在isWinner()方法中判断是否有胜者出现。在main()方法中,我们创建了两个线程分别代表龟和兔,并调用start()方法启动线程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值