2013-05-01 3 views
1

Я пытаюсь написать игру памяти. Когда мы запускаем приложение, сначала появляется «меню». Выбор состоит из одного игрока и двух игроков. Когда мы нажимаем кнопку выбора уровня «один» игрока. Здесь выбор легкий, средний, жесткий. Затем один из них щелкнут, и игра начнется. Но у меня возникают проблемы при реализации того, как проверять выбранные карты равными или нет. Когда карта создается, ей присваивается идентификатор. И когда нажимают две карты, я проверяю идентификаторы. Если идентификаторы одинаковы, он возвращает «match», если это не значит «закрыть», что означает, что карты поворачиваются лицом вниз. Я использую шаблон 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 (в ​​игре). Когда я запускаю код, я получаю null-указатель exeption. Потому что я не могу взять 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

... Что такое нуль, и где? –

+0

В классе Game, "v2 = b2.getCard(). GetValue();" и в GamePanel "currentState = model.compareCards (b, b2);" – user1422167

+0

Вам нужно разбить это на небольшие, управляемые задачи. –

ответ

1

Переменные b и b2 равны нулю при создании CardButtonActionListener. Итак, в первый раз вызывается actionPerformed(), и вы проваливаете свой условный оператор if(i==0), только одному из b или b2 присваивается возвращаемое значение из e.getSource(). Поэтому, когда вы вызываете currentState = model.compareCards(b, b2);, либо b, либо b2 по-прежнему будут иметь значение null, которое, как вы выяснили, вызовет этот метод для исключения исключения из нулевого указателя.

Похоже, что это не столько ошибка кодирования, сколько в том, что вашему дизайну нужны некоторые дополнения. Основная причина заключается в том, что каждая карта имеет свой собственный экземпляр CardButtonActionListener, и при нажатии этого класса слушателя не знают других карточек, которые уже были нажаты. Для быстрого лекарства к этому можно добавить переменную в public static Card lastClicked; члены вашего класса Game (оговорках: обратите внимание, я сказал: «быстро», не «хорошо», так как это нарушает хороший дизайн объектно-ориентированного программирования и в многопоточном приложении даст у вас много неприятностей ... но для однопоточного приложения, такого как ваш, если вы просто хотите, чтобы он работал, это может быть хорошо для вас - но будьте осторожны, что использование общедоступных статических переменных вроде этого, безусловно, не хорошая привычка к попасть в). Тогда вы могли бы изменить свой 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

Большое спасибо, это лучше, чем мое решение «i» :) – user1422167

Смежные вопросы