문제

Java- 안녕하세요, 저는 Minesweeper 프로그램 (First Biggie)을 작성하고 있으며 실제로 붙어 있습니다. 프로그램 자체는 내가 따라야 할 사양에 따라 2 개의 클래스 (논리 용, GUI 용 1 개)로 구성됩니다. 나는 두 수업 모두에서 공정한 일을했지만 끝나지 않았습니다. 그러나 한 클래스에서 다른 클래스로 통화 방법을 구현하는 것을 테스트하려고 노력하고 있으며 그곳에서 갇히는 곳입니다. GUI 클래스에서 사용자가 상자를 클릭 할 때마다 로직 클래스에서 메소드 OpenCell (int x, int y)을 호출하려고합니다. 이 논리 클래스 방법은 정사각형에 광산, 0 또는 숫자가 있는지 확인하고 GUI 클래스에서 적절한 방법을 호출합니다. 오류와 관련된 두 가지 방법은 다음과 같습니다.

GUI CLASS
public void mouseClicked(MouseEvent e) {
    for (int x = 0 ; x < width ; x++) {
       for (int y = 0 ; y < height ; y++) {
           if (e.getSource() == table[x][y]) {    
                if(e.getButton() == e.BUTTON1) {
                   MinesweeperLogic logicClass = new MinesweeperLogic();
                   logicClass.isOpen(x, y); // <--------------------------- ERROR
                 }}}}}

LOGIC CLASS
boolean openCell(int x, int y) {
isClicked[x][y] = true;
    if(mine[x][y] == true && flag[x][y]==false) {
        return false;
    } else if(neighborBombs(x, y) > 0 && flag[x][y]==false) {
        return true;
    }else {
            marked = true;
            return marked;
    }}

다음은 사용자가 게임의 상자를 클릭 한 후에받은 오류 보고서입니다 (코드를 컴파일 할 때 포착하는 데 도움이됩니다).

 Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
 at MinesweeperLogic.isOpen(MinesweeperLogic.java:117)
 at MineSweeperGUI.mouseClicked(MineSweeperGUI.java:126)
 at java.awt.AWTEventMulticaster.mouseClicked(AWTEventMulticaster.java:253)
 at java.awt.Component.processMouseEvent(Component.java:6266)
 at javax.swing.JComponent.processMouseEvent(JComponent.java:3255)
 at java.awt.Component.processEvent(Component.java:6028)
 at java.awt.Container.processEvent(Container.java:2041)
 at java.awt.Component.dispatchEventImpl(Component.java:4630)
 at java.awt.Container.dispatchEventImpl(Container.java:2099)
 at java.awt.Component.dispatchEvent(Component.java:4460)
 at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4574)
 at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4247)
 at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4168)
 at java.awt.Container.dispatchEventImpl(Container.java:2085)
 at java.awt.Window.dispatchEventImpl(Window.java:2475)
 at java.awt.Component.dispatchEvent(Component.java:4460)
 at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
 at  java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
 at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
 at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
 at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
 at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
 at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

마지막으로, 필요한 경우 지금까지 두 클래스에 대한 전체 (이 시점에서 불완전한) 코드. (논리 클래스의 방법은 프로젝트의 지침에 따라 특정 조치를 수행해야하며 논리 클래스에서 사용자 상호 작용이 없어야합니다). 정확히 오류의 원인이 무엇인지 알 수 없습니다. 모든 지침은 대단히 감사 할 것입니다. (바라건대 그것은 정말로 명백한 것이 아닙니다. 나는 지난 몇 시간 동안 독감에 걸렸지 만 이것을 알아 내려고 노력했습니다! lol).

import java.awt.* ;
import java.awt.event.* ;
import java.awt.geom.* ;
import javax.swing.* ;
import javax.swing.event.* ;

public class MineSweeperGUI extends JFrame implements ActionListener, MouseListener {  
int width = 10;
int height = 10;
JPanel p = new JPanel();
JButton[][] table = new JButton[width][height];

public void MineSweeper() {
    MinesweeperLogic logicClass = new MinesweeperLogic();
    logicClass.startNewGame(width, height);
    JButton[] button = new JButton[width*height];
    GridLayout layout = new GridLayout (width, height) ;
    p.setLayout(layout);
    for(int x = 0 ; x < width ; x++) {
        for(int y = 0 ; y < height ; y++) {
            table[x][y] = new JButton();
            table[x][y].setPreferredSize(new Dimension(25,25));
            table[x][y].addMouseListener (this);
            p.add(table [x] [y]);
        }
    }       
    this.add(p);
    this.pack();
    this.setVisible(true);
}


public void mouseClicked(MouseEvent e) {
    for (int x = 0 ; x < width ; x++) {
       for (int y = 0 ; y < height ; y++) {
           if (e.getSource() == table[x][y]) {    
                if(e.getButton() == e.BUTTON1) {
                   MinesweeperLogic logicClass = new MinesweeperLogic();
                   logicClass.isOpen(x, y); //<--------------------------------------
               }
           }
       }
   }
 }
public void gameover(int x, int y) {
   table[x][y].setText("*");
}

public static void main(String[]args) {
    MineSweeperGUI guiClass = new MineSweeperGUI();
    guiClass.MineSweeper();
}}    


public void actionPerformed(ActionEvent e) {
}

public void mouseEntered(MouseEvent e) {
}

public void mousePressed(MouseEvent e) {
}

public void mouseExited(MouseEvent e) {
}

public void mouseReleased(MouseEvent e) {
}




public class MinesweeperLogic {

private int w, h, maxBombs, bombsremaining;
public int width, height;
private boolean mine[][];
private boolean flag[][];
private boolean isClicked[][];
private boolean isZero[][];
private boolean marked;



public void startNewGame(int width, int height) {
    w = width;
    h = height;
    flag = new boolean[w][h];
    isZero = new boolean[w][h];
    isClicked = new boolean[w][h];
    mine = new boolean[w][h];
    maxBombs =(int) Math.floor (width*height*0.15);
    bombsremaining = maxBombs;
    for(int i = 0; i < maxBombs; i++) {
        int x = (int) (Math.random() * (w));
        int y = (int) (Math.random() * (h));
        if (mine[x][y] == false) {
            mine[x][y] = true;
            isClicked[x][y] = false;
            flag[x][y] = false;
        }
    } 
}


int getWidth() {
    return w;
}


int getHeight() {
    return h;
}


boolean openCell(int x, int y) { // <---------------------------------------------
    //MineSweeperGUI guiClass = new MineSweeperGUI();
    isClicked[x][y] = true;
    if(mine[x][y] == true && flag[x][y]==false) {
        //guiClass.gameover(x, y);
        return false;
    } else if(neighborBombs(x, y) > 0 && flag[x][y]==false) {
        return true;
    } else {
            marked = true;
            return marked;
    }}


 boolean markCell(int x, int y) {
     if(flag[x][y] == true) {
            flag[x][y] = false;
            isClicked[x][y] = false;
            bombsremaining++;
            marked = false;
            return marked;
        } else {
            flag[x][y] = true;
            isClicked[x][y] = true;
            bombsremaining--;
                if(mine[x][y]==true) {
                    return true;
                } else {
                    return false;
                }
            }
        }


 boolean isOpen(int x, int y) {
     if(isClicked[x][y] == false) {
         return false;
        } else {
            return true;
        }
}


 boolean isMarked(int x, int y) {
     if(flag[x][y] == true) {
         return true;
        } else {
            return false;
        }
    }


  int getValue(int x, int y) {
      if(mine[x][y] == true) {
          return -1;
        } else {
            return neighborBombs(x, y);
        }
    }


    private int neighborBombs(int x, int y) {  // checks surrounding 8 squares for number of bombs 
        int surBombs = 0;
            for (int q = x - 1 ; q <= x + 1 ; q++) {
                for (int w = y - 1 ; w <= y + 1 ; w++) {
                    while (true) {
                        if (q < 0 || w < 0 || q >= w || w >= h) { 
                            break;
                        }
                        if (mine[q][w] == true) {
                            surBombs++;
                            break;
                        }
                    }   
                }
            }
         return surBombs;
        }
    }
도움이 되었습니까?

해결책

어떻게에 대한:

  1. 예외 스택 트레이스의 첫 번째 줄을보고, 어떤 클래스와 어떤 클래스가 발생하는지 확인하십시오.
  2. 그 줄로 가서이 위치에서 어떤 개체가 "널"될 수 있는지 확인하십시오.
  3. null 인 객체에 가치가없는 이유를 알아보십시오.
  4. 널이 될 수있는 객체가 두 개 이상 있으면 System.out.println() 그들, whchi 하나를 보려면.

다른 팁

당신의 스택 트레이스는 당신에게 이것을 알려줍니다.

스레드의 예외 "awt-eventqueue-0"java.lang.nullpointerexception at minesweeperlogic.isopen (minesweeperlogic.java:117)

따라서 117 행으로 가서 어떤 참조가 널이 될 수 있는지 결정할 수 있습니다. (StackTrace가 취한 후 117에 라인을 추가 한 다음 새로운 라인을 댓글을 달았으므로 여기서 사지로 나가서 StackTrace가 실제로 118 행이라고하는 것을 참조한다고 말할 것입니다. : isClicked[x][y] = true;)이 경우 null 일 수있는 유일한 것은 isClicked[][].

조금 더 깊이 파고 들어, 우리는 당신이 startNewGame ()에서 iSclicked를 초기화한다는 것을 알 수 있지만 분명히 인스턴스가 손실되고 있습니다. 이것은 두 가지 이유로 발생합니다. 첫째, 생성자의 논리는 클래스의 구성원이 아니기 때문에 경찰을 벗어납니다. 두 번째 (그리고 이것은 아마도 첫 번째 문제를 해결하는 데 실패한 시도 일 것입니다) mouseClicked, 당신은 새로운 것을 만듭니다 MinesweeperLogic (새로 만들어진 Null Isclicked와 함께 이전에 만든 것을 사용하는 대신 MineSweeper() 건설자.

코드를 정리하기 위해 만들어야 할 몇 가지 다른 리팩토링이 있지만 로직 클래스를 멤버로 만들고 중복 인스턴스화를 제거하면 즉각적인 문제를 해결해야합니다.

디버거를 사용하고 문제를 해결하여 무슨 일이 일어나고 있는지 정확하게 이해하는 것이 도움이 될 수 있습니다.

배열 (플래그, Iszero, Isclicked)은 초기화되지 않으며 사용하려고 할 때 무효입니다. 로직 클래스의 인스턴스를 포함하려면 GUI 클래스가 필요하며 항상 동일한 인스턴스를 사용하십시오. 그렇지 않으면 각 GUI 액션은 다른 게임에서 진행됩니다!

로직 클래스의 줄 번호 117이 어떤 줄 번호 117인지 아는 것이 도움이 될 것입니다. 내 추측도있을 것입니다 mine, mine[x], flagged 또는 flagged[x] NULL입니다.

즉, "테이블 전체를 클릭 한 것을 확인하기 위해 전체 테이블을 통한 루프"기술은 특히 영감을받은 것처럼 나를 때리지 않습니다.

편집 : 실제로 문제는 isOpen 배열은 수업을 인스턴스화했기 때문에 배열은 null입니다.

edit2 : 좋아, 그래서 처음에 나열된 것 중 하나입니다. 내 추측이 될 것입니다 그들 모두, 당신은 단지 클래스를 인스턴스화했으며 기본 do nothing 생성자를 사용하고 있기 때문입니다.

오류는 MouseClicked () 메소드에서 발생한다고 말하지만 스택 트레이스는 다르게 표시됩니다.

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
 at MinesweeperLogic.isOpen(MinesweeperLogic.java:117)
 at MineSweeperGUI.mouseClicked(MineSweeperGUI.java:126)

이것은 NPE가 Minesweeperlogic의 117 행에서 발생했다고 말합니다. 해당 라인에 디버거를 사용하거나 인쇄문을 삽입하여 NULL이 무엇인지 알아 내면 이유를 해결할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top