最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java編寫(xiě)擲骰子游戲

 更新時(shí)間:2015年11月27日 11:55:56   投稿:mrr  
這篇文章主要介紹了Java編寫(xiě)擲骰子游戲,需要的朋友可以參考下

廢話(huà)不多說(shuō)了,直接奔主題。

**多線程&&觀察者模式

題目要求:《擲骰子》窗體小游戲,在該游戲中,玩家初始擁有1000的金錢(qián),每次輸入押大還是押小,以及下注金額,隨機(jī)3個(gè)骰子的點(diǎn)數(shù),如果3個(gè)骰子的總點(diǎn)數(shù)小于等于9,則開(kāi)小,否則開(kāi)大,然后判斷玩家是否押對(duì),如果未押對(duì)則扣除下注金額,如果押對(duì)則獎(jiǎng)勵(lì)和玩家下注金額相同的金錢(qián)。

分析:這個(gè)題目要求靈活運(yùn)用多線程的相關(guān)知識(shí),達(dá)到點(diǎn)擊開(kāi)始按鈕時(shí),有3個(gè)線程啟動(dòng),分別控制3顆骰子的轉(zhuǎn)動(dòng),在3顆骰子全部轉(zhuǎn)完以后,回到主線程計(jì)算游戲結(jié)果。

 //個(gè)線程控制顆骰子
 Thread t = new Thread();
 Thread t = new Thread();
 Thread t = new Thread();
 //啟動(dòng)個(gè)線程
 t.start();
 t.start();
 t.start();
 //將個(gè)線程加入主線程
 t.join();
 t.join();
 t.join();

But,,,寫(xiě)完代碼以后發(fā)現(xiàn),這樣做雖然能夠保證游戲能夠正確運(yùn)行,但是當(dāng)我點(diǎn)擊開(kāi)始按鈕時(shí),由于3個(gè)骰子線程都是直接開(kāi)在主線程上的,點(diǎn)擊開(kāi)始按鈕時(shí),按鈕出現(xiàn)下沉情況,子線程一直在后臺(tái)運(yùn)行,我窗體中的圖片根本不會(huì)發(fā)生改變,而是直接顯示最后的結(jié)果,意思就是骰子一直在后臺(tái)轉(zhuǎn)動(dòng),不在前臺(tái)的窗體中及時(shí)更新顯示。后來(lái)在網(wǎng)上苦苦找尋,大神們說(shuō)如果想要通過(guò)點(diǎn)擊JButton使窗體中的JLabel/JTextFeild等其他組件及時(shí)更新,直接在JButton的監(jiān)聽(tīng)事件的實(shí)現(xiàn)方法里面直接創(chuàng)建匿名線程,也就是說(shuō)直接在actionPerformed()方法中修改代碼即可,這樣能保證你的組件中內(nèi)容的及時(shí)變換,實(shí)現(xiàn)非常炫酷的效果。

代碼如下:

public void actionPerformed(ActionEvent e) {
 new Thread(new Runnable() {
  @Override
  public void run() {
   //將外部線程類(lèi)轉(zhuǎn)移到窗體內(nèi)部
  }
 }).start();
}

 But,,,But,,,   雖然非常炫酷了,能夠?qū)崿F(xiàn)圖片的及時(shí)更新了,游戲結(jié)果卻錯(cuò)了,每次我的骰子還在轉(zhuǎn)動(dòng)呢,我的游戲結(jié)果卻早早的就出來(lái)了。

原因:3根骰子線程屬于子線程,窗體線程屬于主線程,問(wèn)題就在于:子線程可以通過(guò)變成精靈線程來(lái)保持與主線程的同生死,但是主線程卻無(wú)法控制子線程何時(shí)死亡,只有等待子線程執(zhí)行完所屬的run()方法,結(jié)束線程后才知道。

解決方法:在主線程(main)中開(kāi)3個(gè)子線程(t1,t2,t3),在每個(gè)子線程上再開(kāi)一個(gè)子子線程(t11,t21,t31)。

t1,t2,t3只運(yùn)行一次,負(fù)責(zé)創(chuàng)建子子線程;t11,t21,t31每個(gè)線程運(yùn)行多次,負(fù)責(zé)控制窗體中的圖標(biāo)及時(shí)更新。

這樣主線程就不受子線程的影響,開(kāi)始按鈕也不回出現(xiàn)下沉的情況。

但是同樣在此處使用join方法也是hold不住子線程的,畢竟t1,t2,t3只運(yùn)行了一次,join對(duì)他們來(lái)說(shuō)根本不起作用,想要掌控t11,t21,t31,最容易理解的辦法,就是使用觀察者模式了。

將窗體看做觀察者,子線程看做被觀察者。子線程運(yùn)行完時(shí),通知觀察者我已經(jīng)運(yùn)行完成,當(dāng)觀察者觀察到子線程全都運(yùn)行完時(shí),才開(kāi)始運(yùn)行后續(xù)步驟。

全部代碼:

1.窗體

 package com.sxt.dice;
 import java.awt.Color;
 public class DiceFrame extends JFrame implements ActionListener, Observer {
  /**
  * 《擲骰子》控制臺(tái)小游戲,在該游戲中,玩家初始擁有的金錢(qián),每次輸入押大還是押小,
  * 以及下注金額,隨機(jī)個(gè)骰子的點(diǎn)數(shù),如果個(gè)骰子的總點(diǎn)數(shù)小于等于,則開(kāi)小,否則開(kāi)大,
  * 然后判斷玩家是否押對(duì),如果未押對(duì)則扣除下注金額,如果押對(duì)則獎(jiǎng)勵(lì)和玩家下注金額相同的金錢(qián)。
  * 
  * 運(yùn)用觀察者模式 個(gè)子線程分別控制個(gè)骰子,都已經(jīng)結(jié)束時(shí),通知觀察者窗體,窗體觀察到所有子線程都結(jié)束時(shí),計(jì)算游戲結(jié)果
  * 
  */
  private static final long serialVersionUID = L;
  private JTextField txtPut;
  private JButton btnStart;
  private JLabel labResult;
  private JComboBox<String> comboBox;
  private JLabel labBigOrSmall;
  private JLabel labPut;
  private JLabel labSumMoney;
  private JLabel labDice;
  private JLabel labDice;
  private JLabel labDice;
  private JLabel labSum;
  private JLabel labMes;
  private static List<Icon> imgs = new ArrayList<Icon>();
  public static void main(String[] args) {
   new DiceFrame();
  }
  public DiceFrame() {
   this.setLocationRelativeTo(null);
   this.setBounds(, , , );
   this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
   getContentPane().setLayout(null);
   this.setResizable(false);
   labDice = new JLabel("");
   labDice.setIcon(new ImageIcon("img/dices.jpg"));
   labDice.setBounds(, , , );
   getContentPane().add(labDice);
   labSum = new JLabel("\u\uF\uD\uD\uFFA");
   labSum.setBounds(, , , );
   getContentPane().add(labSum);
   labDice = new JLabel("");
   labDice.setIcon(new ImageIcon("img/dices.jpg"));
   labDice.setBounds(, , , );
   getContentPane().add(labDice);
   labDice = new JLabel("");
   labDice.setIcon(new ImageIcon("img/dices.jpg"));
   labDice.setBounds(, , , );
   getContentPane().add(labDice);
   labSumMoney = new JLabel("");
   labSumMoney.setForeground(Color.red);
   labSumMoney.setBounds(, , , );
   getContentPane().add(labSumMoney);
   labPut = new JLabel("\uC\uB\uEB\uCE\uFFA");
   labPut.setToolTipText(".");
   labPut.setBounds(, , , );
   getContentPane().add(labPut);
   txtPut = new JTextField();
   txtPut.setBounds(, , , );
   getContentPane().add(txtPut);
   txtPut.setColumns();
   labBigOrSmall = new JLabel("\uBC\uFFA");
   labBigOrSmall.setBounds(, , , );
   getContentPane().add(labBigOrSmall);
   comboBox = new JComboBox<String>();
   comboBox.setBounds(, , , );
   getContentPane().add(comboBox);
   comboBox.addItem("大");
   comboBox.addItem("小");
   labResult = new JLabel("");
   labResult.setBounds(, , , );
   getContentPane().add(labResult);
   btnStart = new JButton("START");
   btnStart.setBounds(, , , );
   getContentPane().add(btnStart);
   labMes = new JLabel("<html><font size= color=red>*</font></html>");
   labMes.setBounds(, , , );
   getContentPane().add(labMes);
   this.setVisible(true);
   imgs.add(new ImageIcon("img/.png"));
   imgs.add(new ImageIcon("img/.png"));
   imgs.add(new ImageIcon("img/.png"));
   imgs.add(new ImageIcon("img/.png"));
   imgs.add(new ImageIcon("img/.png"));
   imgs.add(new ImageIcon("img/.png"));
   btnStart.addActionListener(this);
  }
  @Override
  public void actionPerformed(ActionEvent e) {
   if (e.getSource() == btnStart) {
    // 清除上次游戲的結(jié)果
    labResult.setText("");
    // 獲取當(dāng)前下注金額,用戶(hù)余額,用戶(hù)押大還是押小
    String txt = txtPut.getText().trim();
    String remain = labSumMoney.getText().trim();
    // 余額不足,不能開(kāi)始游戲,提示用戶(hù)充值
    if (Integer.parseInt(remain) <= ) {
     JOptionPane.showMessageDialog(null, "當(dāng)前余額不足,請(qǐng)充值!");
     return;
    }
    // 下注金額合法性檢查
    if (txt.length() == ) {
     // 提示用戶(hù)輸入
     labMes.setText("*請(qǐng)輸入下注金額");
     labMes.setForeground(Color.RED);
     return;
    }
    // 檢查用戶(hù)下注金額是否在有效范圍內(nèi)
    if (Integer.parseInt(txt) <= 
      || Integer.parseInt(txt) > Integer.parseInt(remain)) {
     txtPut.setText("");
     labMes.setText("下注金額應(yīng)在~" + remain + "之間");
     return;
    }
    // 游戲開(kāi)始后相關(guān)項(xiàng)不可更改
    txtPut.setEnabled(false);
    labMes.setText("");
    comboBox.setEnabled(false);
    //在主線程上開(kāi)t,t,t 個(gè)子線程
    Thread t = new Thread() {
     @Override
     public void run() {
      //每個(gè)子線程上再開(kāi)子子線程,控制圖標(biāo)變換
      IconThread t = new IconThread(labDice, imgs);
      //給t添加觀察者,即當(dāng)前窗體
      t.addObserver(DiceFrame.this);
      new Thread(t).start();
     }
    };
    Thread t = new Thread() {
     @Override
     public void run() {
      IconThread t = new IconThread(labDice, imgs);
      t.addObserver(DiceFrame.this);
      new Thread(t).start();
     }
    };
    Thread t = new Thread() {
     @Override
     public void run() {
      IconThread t = new IconThread(labDice, imgs);
      t.addObserver(DiceFrame.this);
      new Thread(t).start();
     }
    };
    t.start();
    t.start();
    t.start();
   }
  }
  /**
  * 獲取骰子點(diǎn)數(shù)和
  * 
  * @param lab
  * @return sum
  */
  private int result(JLabel lab) {
   // 獲取當(dāng)前骰子圖片
   Icon icon = lab.getIcon();
   int sum = ;
   for (int i = ; i < imgs.size(); i++) {
    if (icon.equals(imgs.get(i))) {
     sum += (i + );
     break;
    }
   }
   return sum;
  }
  // 構(gòu)建所有被觀察者的集合
  Vector<Observable> allObservables = new Vector<Observable>();
  @Override
  public void update(Observable o, Object arg) {
   System.out.println(o + ".................");
   // 如果集合中不包含當(dāng)前被觀察者,將此被觀察者加入集合
   if (allObservables.contains(o) == false) {
    allObservables.add(o);
   }
   // 如果集合中被觀察者個(gè)數(shù)為,說(shuō)明個(gè)骰子線程已經(jīng)全部結(jié)束
   if (allObservables.size() == ) {
    // 獲取當(dāng)前下注金額,用戶(hù)余額,用戶(hù)押大還是押小
    String txt = txtPut.getText().trim();
    String remain = labSumMoney.getText().trim();
    String bigOrSmall = comboBox.getSelectedItem().toString();
    // 獲取每個(gè)骰子點(diǎn)數(shù)
    int sum = result(labDice);
    int sum = result(labDice);
    int sum = result(labDice);
    System.out.println(sum + "-" + sum + "-" + sum);
    int sum = sum + sum + sum;
    System.out.println(sum);
    if (sum > && "大".equals(bigOrSmall) || sum <= 
      && "小".equals(bigOrSmall)) {
     // 獎(jiǎng)勵(lì)玩家相應(yīng)金額
     remain = String.valueOf(Integer.parseInt(remain)
       + Integer.parseInt(txt));
     labSumMoney.setText(remain);
     // 顯示游戲結(jié)果
     labResult.setText("WIN");
     labResult.setForeground(Color.GREEN);
     labResult.setFont(new Font("宋體", Font.BOLD, ));
    } else {
     // 扣除玩家相應(yīng)金額
     remain = String.valueOf(Integer.parseInt(remain)
       - Integer.parseInt(txt));
     labSumMoney.setText(remain);
     labResult.setText("FAIL");
     labResult.setForeground(Color.red);
     labResult.setFont(new Font("宋體", Font.BOLD, ));
    }
    txtPut.setEnabled(true);
    comboBox.setEnabled(true);
    // 本次游戲結(jié)束后移除集合中所有線程
    allObservables.removeAll(allObservables);
   }
  }
 }

2.線程

 package com.sxt.dice;
 import java.util.List;
 import java.util.Observable;
 import java.util.Random;
 import javax.swing.Icon;
 import javax.swing.JLabel;
 public class IconThread extends Observable implements Runnable {
  /**
  * 運(yùn)用觀察者模式,將子線程作為被觀察對(duì)象,一旦子線程運(yùn)行完,發(fā)生改變,通知觀察者
  */
  JLabel lab;
  Random random = new Random();
  List<Icon> imgs;
  public IconThread(JLabel lab, List<Icon> imgs) {
   this.lab = lab;
   this.imgs = imgs;
  }
  @Override
  public void run() {
   //設(shè)置每顆骰子轉(zhuǎn)動(dòng)次
   int count = ;
   while (count > ) {
    //獲取一個(gè)隨機(jī)數(shù)[~)
    int index = random.nextInt();
    //從imgs集合中取相應(yīng)圖片放入lab中
    lab.setIcon(imgs.get(index));
    count--;
    try {
     Thread.sleep();
    } catch (InterruptedException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
   this.setChanged();// 子線程運(yùn)行完,發(fā)生改變
   this.notifyObservers();// 通知觀察者
  }
 }

以上所述就是關(guān)于Java編寫(xiě)擲骰子游戲的全部?jī)?nèi)容,希望大家喜歡。

相關(guān)文章

  • Window中安裝構(gòu)建神器Jenkins詳解

    Window中安裝構(gòu)建神器Jenkins詳解

    Jenkins是一款開(kāi)源 CI&CD 軟件,用于自動(dòng)化各種任務(wù),包括構(gòu)建、測(cè)試和部署軟件。支持各種運(yùn)行方式,可通過(guò)系統(tǒng)包、Docker 或者通過(guò)一個(gè)獨(dú)立的 Java 程序。是解放人工集成部署的自動(dòng)化構(gòu)建神器
    2021-07-07
  • Java超詳細(xì)講解三大特性之一的多態(tài)

    Java超詳細(xì)講解三大特性之一的多態(tài)

    多態(tài)就是指程序中定義的引用變量所指向的具體類(lèi)型和通過(guò)該引用變量發(fā)出的方法調(diào)用在編程時(shí)并不確定,而是在程序運(yùn)行期間才確定,即一個(gè)引用變量到底會(huì)指向哪個(gè)類(lèi)的實(shí)例對(duì)象,該引用變量發(fā)出的方法調(diào)用到底是哪個(gè)類(lèi)中實(shí)現(xiàn)的方法,必須在由程序運(yùn)行期間才能決定
    2022-05-05
  • Java啟動(dòng)參數(shù)(-,?-X,?-XX參數(shù))的使用

    Java啟動(dòng)參數(shù)(-,?-X,?-XX參數(shù))的使用

    本文主要介紹了Java啟動(dòng)參數(shù)(-,?-X,?-XX參數(shù))的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • Spring中的ContextLoaderListener詳細(xì)解析

    Spring中的ContextLoaderListener詳細(xì)解析

    這篇文章主要介紹了Spring中的ContextLoaderListener詳細(xì)解析,在web容器即Tomact容器啟動(dòng)web應(yīng)用即servlet應(yīng)用時(shí),會(huì)觸發(fā)ServletContextEvent時(shí)間,這個(gè)事件會(huì)被ServletContextListener監(jiān)聽(tīng),需要的朋友可以參考下
    2023-12-12
  • Springboot如何添加server.servlet.context-path相關(guān)使用

    Springboot如何添加server.servlet.context-path相關(guān)使用

    這篇文章主要介紹了Springboot如何添加server.servlet.context-path相關(guān)使用問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • 淺談在Java中JSON的多種使用方式

    淺談在Java中JSON的多種使用方式

    這篇文章主要介紹了淺談在Java中JSON的多種使用方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • SpringBoot解決跨域的5種方式小結(jié)

    SpringBoot解決跨域的5種方式小結(jié)

    在項(xiàng)目開(kāi)發(fā)中,時(shí)常會(huì)遇到跨域問(wèn)題,本文主要介紹了五種解決跨域的方法,使用最多的是第三種,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-06-06
  • Java設(shè)計(jì)模式之工廠方法模式實(shí)例簡(jiǎn)析

    Java設(shè)計(jì)模式之工廠方法模式實(shí)例簡(jiǎn)析

    這篇文章主要介紹了Java設(shè)計(jì)模式之工廠方法模式,較為詳細(xì)的分析了Java工廠模式的功能、定義并給出了實(shí)例代碼加以總結(jié)分析,需要的朋友可以參考下
    2015-11-11
  • Swagger異常定位紀(jì)實(shí)Swagger設(shè)計(jì)問(wèn)題分析

    Swagger異常定位紀(jì)實(shí)Swagger設(shè)計(jì)問(wèn)題分析

    這篇文章主要為大家介紹了Swagger異常定位紀(jì)實(shí)Swagger設(shè)計(jì)的問(wèn)題分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-02-02
  • java8 如何實(shí)現(xiàn)分組計(jì)算數(shù)量和計(jì)算總數(shù)

    java8 如何實(shí)現(xiàn)分組計(jì)算數(shù)量和計(jì)算總數(shù)

    這篇文章主要介紹了java8 如何實(shí)現(xiàn)分組計(jì)算數(shù)量和計(jì)算總數(shù)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07

最新評(píng)論

连平县| 洱源县| 乌拉特中旗| 陈巴尔虎旗| 汤阴县| 曲阳县| 义马市| 尉犁县| 盘锦市| 堆龙德庆县| 阳春市| 福海县| 勃利县| 灵台县| 怀柔区| 府谷县| 旬阳县| 奉新县| 德庆县| 阳泉市| 团风县| 太湖县| 象州县| 耒阳市| 商丘市| 沈丘县| 闸北区| 高尔夫| 厦门市| 阿坝县| 孝感市| 嫩江县| 定陶县| 芷江| 蕉岭县| 嘉义县| 贺州市| 宿松县| 江门市| 大渡口区| 渝中区|