2013-05-01 13 views
1

我想寫一個記憶遊戲。當我們運行應用程序時,首先出現「菜單」。選擇是一個球員和兩個球員。當我們點擊一​​個玩家「級別」選擇部分出現。這裏的選擇很簡單,中等,很難。然後點擊其中一個,遊戲開始。但是在執行如何檢查選定的卡片時,我遇到了麻煩。當一張卡片被創建時,一個ID被分配給它。當點擊兩張牌時,我正在檢查ID。如果id相同,則返回「匹配」,如果不是,那麼「close」返回,這意味着卡片面朝下。我正在使用MVC模式。我有9個班。卡,遊戲,級別(枚舉),菜單,狀態(枚舉);查看CardButton,GamePanel,LevelPanel,MenuPanel。 類的GamePanel:java中的記憶遊戲

package view; 

import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.JFrame; 
import javax.swing.JOptionPane; 
import javax.swing.JPanel; 

import model.Game; 
import model.State; 

public class GamePanel extends JPanel { 
private Game model; 
ActionListener cardButtonActionListener; 
private JFrame frame; 

public GamePanel(Game gameModel, JFrame frame) { 
    int width=gameModel.getRowSize(); 
    int height=gameModel.getColumnSize(); 
    setLayout(new GridLayout(width,height)); 

    this.model = gameModel; 
    this.cardButtonActionListener = new CardButtonActionListener(); 
    this.frame = frame; 
    show(); 
} 

public void show() { 
    for(int row=0; row<model.getRowSize(); row++) { 
     for (int col=0; col<model.getColumnSize(); col++) { 
      CardButton cardBtn = new CardButton(model.getCard(row, col)); 
      cardBtn.addActionListener(cardButtonActionListener); 
      add(cardBtn); 
     } 
    } 

    frame.repaint(); 
} 

public class CardButtonActionListener implements ActionListener { 
    private int i = 0; 
    CardButton b ,b2; 
    State currentState; 

    @Override 
    public void actionPerformed(ActionEvent e) { 

     if(i==0){ 
      b = (CardButton) e.getSource(); 
      b.setFaceUp(); 
      JOptionPane.showInputDialog("id "+b.getCard().getValue()); 
      i++; 
     } 
     else{ 
      b2 = (CardButton) e.getSource(); 
      b2.setFaceUp(); 
      i--; 
     } 


     currentState = model.compareCards(b, b2); 

     if(currentState == State.Match){ 
      b.setVisible(false); 
      b2.setVisible(false);    
     } 

     if(currentState == State.Close){ 
      b.setFaceDown(); 
      b2.setFaceDown();    
     } 

     if(currentState == State.Continue){ 

     } 
    } 

} 
} 

類遊戲:

package model; 

import java.util.ArrayList; 
import java.util.Collections; 

import javax.swing.JPanel; 

import view.CardButton; 


public class Game extends JPanel { 

private Level level; 
private ArrayList<ArrayList<Card>> board; 
private int rowSize; 
private int colSize; 
private ArrayList<Card> cardList; 

public Game() { 

} 

public void setLevel(Level level,int x) { 
    this.level = level; 
    initBoard(x); 
} 

private void initBoard(int x) { 
    // Create board according to level variable 
    int s = x; 
    rowSize = s; 
    colSize = s; 
    int a=rowSize*colSize/2; 
    int b=0; 
    this.board = new ArrayList<ArrayList<Card>>(); 
    for(int row=0; row<s; row++) { 
     this.cardList = new ArrayList<Card>(); 
     for (int col=0; col<s/2; col++) { 
      cardList.add(new Card(b)); 
      cardList.add(new Card(b)); 
      b++; 
     } 
     board.add(getCardList()); 
    } 
    Collections.shuffle(board); 
} 

public ArrayList<Card> getCardList(){ 
    Collections.shuffle(cardList); 
    return cardList; 
} 

public int getRowSize() { 
    return rowSize; 
} 

public int getColumnSize() { 
    return colSize; 
} 

public Card getCard(int row, int col) { 
    return board.get(row).get(col); 
} 




public State compareCards(CardButton b, CardButton b2) { 
    int v1, v2; 
    v1 = b.getCard().getValue(); 
    v2 = b2.getCard().getValue(); 
    if(b.getCard()!= null && b2.getCard()!= null){ 
     return State.Continue;  
    }else{ 
     if(v1 == v2){ 
      return State.Match; 
     } 
     else{ 
      return State.Close; 
      } 
    } 

} 
} 

的GamePanel需要狀態信息,並決定卡位卡應留其中:面朝上,面朝下。但是我無法正確執行操作執行方法(在GamePanel中)和compareCards方法(在遊戲中)。當我運行代碼時,我得到空指針豁免。因爲我不能拿2個按鈕的信息。其中一個始終保持爲空。我可能需要更改此部分:

if(i==0){ 
     b = (CardButton) e.getSource(); 
     b.setFaceUp(); 
     JOptionPane.showInputDialog("id "+b.getCard().getValue()); 
     i++; 
    } 
    else{ 
     b2 = (CardButton) e.getSource(); 
     b2.setFaceUp(); 
     i--; 
    } 

但我不知道如何糾正。謝謝。 編輯:整個項目在這裏http://cnv.as/21qoh

+0

...什麼是空的,在哪裏呢? – 2013-05-01 18:07:57

+0

在課堂遊戲中,「v2 = b2.getCard()。getValue();」並在GamePanel中,「currentState = model.compareCards(b,b2);」 – user1422167 2013-05-01 18:11:12

+0

你需要把它分解成小的,可管理的任務。 – 2013-05-01 18:11:22

回答

1

當創建CardButtonActionListener時,b和b2變量爲空。因此,第一次調用actionPerformed()時,如果您通過條件語句if(i==0),則只有b或b2中的一個被賦予來自e.getSource()的返回值。所以當你打電話給currentState = model.compareCards(b, b2);時,b或者b2仍然是空的,如你發現的那樣會導致該方法拋出一個空指針異常。

看起來這不是一個編碼錯誤,因爲它是你的設計需要一些補充。主要原因是每張卡都有自己的CardButtonActionListener實例,點擊後,這個監聽者類不知道任何其他已被點擊的卡。對於一個快速補救這一點,你可以一個public static Card lastClicked;成員變量添加到您的遊戲類(免責聲明:注意我說:「快速」,而不是「」因爲這違反了良好的面向對象設計,在多線程應用程序將使你噸麻煩......但對於像你這樣的單線程應用程序,如果你只是希望它的工作,這可能是適合你 - 但要警告的是,使用這樣的公共靜態變量肯定是不是一個好習慣進入)。然後,你可以修改你的CardButtonActionListener.actionPerformed()這樣的(注意,我廢除了「我」變量):

@Override 
public void actionPerformed(ActionEvent e) { 
    CardButton justClickedButton = e.getSource(); 
    justClickedButton.setFaceUp(); 
    CardButton previouslyClickedButton = Game.lastClicked; 
    if(previouslyClickedButton == null){ 
     JOptionPane.showInputDialog("id "+justClickedButton.getCard().getValue()); 
     previouslyClickedButton = justClickedButton; 
    } 
    else{ 
     currentState = model.compareCards(justClickedButton, previouslyClickedButton); 

     if(currentState == State.Match){ 
      justClickedButton.setVisible(false); 
      previouslyClickedButton.setVisible(false);    
     } 

     if(currentState == State.Close){ 
      justClickedButton.setFaceDown(); 
      previouslyClickedButton.setFaceDown();    
     } 

     if(currentState == State.Continue){ 
     } 

     previouslyClickedButton = null; 
    } 
} 
+0

非常感謝,這比我的「我」解決方案更好:) – user1422167 2013-05-01 22:21:29