1

私は記憶ゲームを書こうとしています。アプリを実行すると、最初に「メニュー」が表示されます。選択肢は 1 人プレイと 2 人プレイです。1 人のプレイヤーをクリックすると、「レベル」選択部分が表示されます。ここでの選択肢は、イージー、ミディアム、ハードです。次に、それらのいずれかをクリックすると、ゲームが開始されます。しかし、選択したカードが等しいかどうかを確認する方法を実装する際に問題があります。カードが作成されると、ID が割り当てられます。2 枚のカードがクリックされると、ID がチェックされます。ID が同じ場合は「match」を返し、そうでない場合はカードが裏向きになることを意味する「close」を返します。MVC パターンを使用しています。私は9つのクラスを持っています。カード、ゲーム、レベル(列挙型)、メニュー、状態(列挙型); CardButton、GamePanel、LevelPanel、MenuPanel を表示します。クラス GamePanel:

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 メソッド (ゲーム内) を正しく実装できませんでした。コードを実行すると、null ポインター例外が発生します。2ボタンの情報が取れないので。そのうちの 1 つは常に null のままです。おそらくこの部分を変更する必要があります:

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

4

1 に答える 1

1

が作成されるとき、b および b2 変数は nullCardButtonActionListenerです。したがって、最初actionPerformed()に呼び出されてif(i==0)条件ステートメントに失敗すると、b または b2 のいずれか 1 つだけが e.getSource() からの戻り値に割り当てられます。したがって、currentState = model.compareCards(b, b2);b または b2 のいずれかを呼び出すと、まだ null のままであり、そのメソッドが null ポインター例外をスローすることがわかりました。

これはコーディング エラーではなく、設計に追加が必要なようです。主な理由は、各カードには独自のインスタンスがCardButtonActionListenerあり、クリックされたときに、このリスナー クラスは既にクリックされた他のカードを認識しないためです。public static Card lastClicked;これを簡単に解決するには、メンバー変数を Game クラスに追加できます (免責事項:これは適切な OOP 設計に違反しており、マルチスレッド アプリでは多くのトラブルが発生するため、「クイック」ではなく「良い」と言ったことに注意してください...ただし、あなたのようなシングルスレッドアプリの場合、それを機能させたいだけであれば、これで問題ないかもしれませんが、このような public static 変数を使用することは絶対にできないことに注意してください入るのに良い習慣です)。次に、 CardButtonActionListener.actionPerformed() を次のように変更できます (「i」変数を削除したことに注意してください)。

@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;
     }
}
于 2013-05-01T18:57:02.427 に答える