2013-05-01 92 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