看板 java 關於我們 聯絡資訊
我的程式是一個可以計時的記憶翻牌遊戲 在程式一些方法中建立一個新的 timer 並呼叫相應的 timertask 我的 timertask 以 inner class 寫在相同的 class 裡面 奇怪的是那方法就只有 timer & timertask 沒有執行,其他都順利執行 我懷疑是我用了 2個 timertask 做不同事情而沒有另外新增執行緒 以下為部分程式碼,請各位大大看看哪邊出問題,若資訊太少會在補充 謝謝 private JFrame mainFrame; ... private List<JButton> Cards = new ArrayList<JButton>(); private List<Integer> numberlist = new ArrayList<Integer>(); private int firstOpenCard = -1; // 記錄第一次翻開的牌 private int openCards = -1; // 記錄翻開幾組 private Timer timer, timer2; // timer2 用來設定翻錯的牌多久蓋回,沒有順利執行 private int i1; public MemoryGame(String title) { playerTable = new JPanel(); playerArea = new JPanel(); playerInformation = new JPanel(); ... mainFrame = new JFrame(title); playerInformation.add(clicks); playerInformation.add(time); clickDetermine clickCards = new clickDetermine(); //替每個按鈕加上事件 startBtn = new JButton("start"); startBtn.addActionListener( new ActionListener () { public void actionPerformed(ActionEvent arg0) { if ( (openCards != CardNumber/2) && (openCards != -1) ) { timer.cancel(); int option = JOptionPane.showConfirmDialog(null, "Do you want to restart the game ?", "Confirm", JOptionPane.YES_NO_CANCEL_OPTION); if (option == 1 || option == 2) { timer = new Timer(); timer.schedule(new timeDisplay(), 0, 1000); return; } } ... timer = new Timer(); timer.schedule(new timeDisplay(), 0, 1000); } }); giveUpBtn = new JButton("give up"); giveUpBtn.addActionListener(...); ... private class clickDetermine implements ActionListener { public void actionPerformed(ActionEvent e) { useSteps++; for (int i = 0 ; i < CardNumber ; i++) { if (e.getSource() == Cards.get(i)) { // 翻的是第一張, 記錄位置 if (firstOpenCard == -1) { Cards.get(i).setText(numberlist.get(i) + ""); firstOpenCard = i; clicks.setText("目前翻動次數 : " + useSteps); } else { if (i == firstOpenCard) { // 翻同一張 useSteps--; return; } Cards.get(i).setText(String.valueOf(numberlist.get(i))); clicks.setText("目前翻動次數 : " + useSteps); // 翻對 if (numberlist.get(i).equals(numberlist.get(firstOpenCard))) { Cards.get(i).setEnabled(false); Cards.get(firstOpenCard).setEnabled(false); openCards++; if (openCards == CardNumber/2) { // 翻完,停止計時 timer.cancel(); } } else { // 翻錯 i1 = i; timer2 = new Timer(); timer2.schedule(new coverback(), 1500); timer2.cancel(); } firstOpenCard = -1; } break; } } } } ... private class timeDisplay extends TimerTask { // 設定時間顯示 public void run() { ... } } private class coverback extends TimerTask { // 設定將牌蓋回 public void run() { Cards.get(firstOpenCard).setText("*"); Cards.get(i1).setText("*"); } } ... -- 肝不好 肝若好 人生是黑白的 考卷是空白的 、 ﹐ ● ●b ▎ ●> ● ▌ ﹍﹍ 囧> 幹... ▲ ■┘ ▎ ■ ▋ ︶■ 〈﹀ ∥ ▁▁∥ ▎ ﹀〉▊ 〈\ ψcockroach727 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 140.112.232.118 ※ 文章網址: https://www.ptt.cc/bbs/java/M.1449844111.A.A57.html
AI3767: 翻錯 那邊, 一schedule完就cancel不會有問題嗎? 12/11 23:11
中間若要插入 sleep ,數值設定太小也不會執行 設大一些要凍結很久,而且也不會有翻開又蓋回的感覺 ※ 編輯: obelisk0114 (140.112.232.118), 12/12/2015 00:34:35
AI3767: 不清楚你的timer2還有做什麼其它的, 如果不cancel可以嗎? 12/12 00:44
AI3767: 另外是,這裡沒看到clickCards變數有被誰用 12/12 00:46
timer2 是設定蓋回去的時間,只有將2張翻開的牌蓋回去 我有試過將 timer2.cancel() 刪掉,執行會報錯誤 clickCards 是設定 16 張牌的 ActionPerformed, 相關程式碼附上如下 for (int i = 0 ; i < CardNumber ; i++) { // CardNumber 是總共有幾張牌 numberlist.add(new Integer(i/2 + 1)); Cards.add(new JButton("*")); playerArea.add(Cards.get(i)); Cards.get(i).addActionListener(clickCards); } ※ 編輯: obelisk0114 (140.112.232.118), 12/12/2015 01:56:24
AI3767: 呃 是報什麼錯?? 12/12 16:37
原本覺得他的報錯很奇怪 後來 print 出來發現翻錯那邊 在跑到 timer2 = new Timer(); 會因為後面的 firstOpenCard = -1; 而將 firstOpenCard 設定成 -1,這樣 coverback 的 Cards.get(firstOpenCard).setText("*"); 就會因為抓到 Cards.get(-1) 而出錯 不知道為何 ? ※ 編輯: obelisk0114 (140.112.232.118), 12/12/2015 18:30:13
jinn: timer2.cancel()刪掉 然後coverback那裡改成 12/12 21:10
jinn: if(firstOpenCard!=-1) { 12/12 21:11
jinn: Cards.get(firstOpenCard).setText("*"); } 12/12 21:12
jinn: 不就好了@@? 12/12 21:13
Cards.get(firstOpenCard).setText("*"); 是翻錯時,把第一張翻開的牌蓋回去 若移到上面會變成翻錯時,先將第一張蓋回,1.5秒後蓋回第二張 感覺很奇怪 ※ 編輯: obelisk0114 (140.112.232.118), 12/12/2015 21:19:58
AI3767: 這個報錯和timer無關, 是程式邏輯要修, 你的寫法,遇到連續 12/12 22:11
AI3767: 開牌, 可能也會有問題 12/12 22:11
程式邏輯要修可以多提一下嗎 ? 資訊太少,不知道怎麼改 timer 和 timertask 的搭配好像是另一個執行緒 是因為主要程式執行完才會交給 timer2 和 coverback ? 雖然只要多定義一個變數,將 firstOpenCard 傳入,再由 coverback 接收就好 ※ 編輯: obelisk0114 (140.112.232.118), 12/13/2015 02:57:46
AI3767: 上面這句, 這樣做是好的, 在new coverback時傳入誰要翻回 12/13 23:46
AI3767: timer new一次就夠了. 然後連續翻牌問題, 可以有兩種方法 12/13 23:47
AI3767: 1:最多翻兩張, 兩張有中,或是兩張都翻回後, 才能翻下一輪 12/13 23:48
AI3767: 2:可連續翻牌,但自己定出方法和資料結構, 能記得哪兩張要 12/13 23:50
AI3767: 互相配對比較 12/13 23:50
只用滑鼠點擊好像不會達成連續翻牌 ? 記得哪2張的方式像是下面嗎 ? 在 public class MemoryGame{ private int i1,i2; // 在 clickDetermine 才傳入第一張,第二張 } ※ 編輯: obelisk0114 (140.112.232.118), 12/14/2015 02:27:47
AI3767: 也可以,原先的firstOpenCard也可以,只要能確保一次最多只 12/14 22:11
AI3767: 會翻開兩張. 然後程式執行的部份再檢查看看吧 12/14 22:15