質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.98%

  • Java

    12205questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Swing

    199questions

    SwingはJavaに標準で付属するグラフィック関連のクラスライブラリを指します。

初期化しているにもかかわらずNullPointerExceptionが発生する

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 214

tarutarupop

score 10

お世話になっております。

javaのswingを学ぶため四目並べゲームのプログラムを作っていたのですが、java.lang.NullPointerExceptionのエラーが発生し解消に難航しています。

二つあり一つ目が、GameScreen コンストラクタ内のsetTelllimittext(system.getSecond());
Gamesystemにあるint secを参照するところ。

二つ目が、GameSystem 92行目screen.setTelllimittext(sec);
表示する秒数を更新するため、Gamescreentelllimitのテキストを変更する関数にsecを渡すところ。

どちらもsecを参照しているためこれがnullになっているのはわかるのですが、それがなぜなのかがわかりません。secの宣言時に値を入れてみたり宣言する場所を変えてみたりしたのですが解決できませんでした。初歩的な見落としのような気もしますが、どうかご指摘のほどお願いいたします。

public class GameScreen extends JPanel implements ActionListener{
    private int cn;        //升目の数 cn * cn
    private boolean press = true;
    private JPanel backpane;
    private JLabel telllimit;
    private GameSystem system;
    private JLabel tellcolor;
    private Color player_c;
    static  JLabel timelimit;
    static boolean play_turn;                //現在のターンを保持
    static boolean[] enter ;    //すべての入力を保持
    static ArrayList<ArrayList<JButton>> y_coordinate = new ArrayList<ArrayList<JButton>>();

    public static void main(String args[]){
        JFrame jf = new JFrame();
        GameScreen gs = new GameScreen(15);
        jf.add(gs);
        jf.pack();
        jf.setVisible(true);
        //ゲーム開始
        new GameSystem(15);
    }

    public GameScreen(int n){
        /*
         * 画面生成
         */
            //親パネル
        super();
        this.setPreferredSize(new Dimension(930,700));
        this.setLayout(null);
        play_turn = true;    //初期値(初期ターン)

            //ターン表示のためのパネル
        tellcolor = new JLabel();
        tellcolor.setBackground(getPlayer_c());
        tellcolor.setBounds(0, 0, 200, 200);
        this.add(tellcolor);

            //残り時間表示のためのパネル
        telllimit = new JLabel();
        telllimit.setBorder(new BevelBorder(BevelBorder.RAISED, Color.blue, Color.black));
        telllimit.setBounds(200, 0, 430, 200);
        telllimit.setForeground(Color.RED);
        setTelllimittext(system.getSecond());
        this.add(telllimit);

        cn = n;
        enter = new boolean[cn*cn];

            //升目パネル
        JPanel screen = new JPanel();
        screen.setBounds(100,220,720,450);
        screen.setLayout(new GridLayout(n,n,0,0));
        for(int i = 0;i<cn;i++){
            ArrayList<JButton> x_coordinate = new ArrayList<JButton>();
            for(int t = 0;t<cn;t++){
                JButton cell = CreateCell(i,t);
                cell.addActionListener(this);
                screen.add(cell);
                x_coordinate.add(cell);
            }
            y_coordinate.add(x_coordinate);
        }
        this.add(screen);
    }

    public JButton CreateCell(int x,int y){
        JButton btn = new JButton();
        btn.setSize(10, 10);
        btn.setActionCommand(x+"-"+y);
        return btn;
    }

    public void setTelllimittext(int second){
        String s= "残り時間 "+ second +" 秒";
        telllimit.setText(s);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if(press == true){

            press = false;
        }

        String coordinate = e.getActionCommand();
        for(int k=0;k<cn;k++){
            for(int j = 0;j<cn;j++){
                String number = k+"-"+j;
                if(coordinate.equals(number)){
                    int order = k*20 + j+1;    //入力の番号を作成
                    if(play_turn == true){
                        player_c = Color.RED;
                        system.addA(order);
                    }else{
                        player_c = Color.BLUE;
                        system.addB(order);
                    }
                    changeTurn();
                    if(k == 19){                    //入力が底の時
                        processEnter(order,k,j,player_c);
                    }else{                            //入力が上部の時
                        if(enter[order+20] == false){
                            System.out.println("無効な入力です");
                        }else{
                            processEnter(order,k,j,player_c);
                        }
                    }
                    system.createCombinations();
                }
            }
        }
        return;
    }

    public Color getPlayer_c(){
        return player_c;
    }

    public void changeTurn(){
        if(play_turn == true){
            player_c = Color.RED;
            play_turn = false;
        }else{
            player_c = Color.BLUE;
            play_turn = true;
        }
        tellcolor.setBackground(getPlayer_c());
    }

    /*    色塗り処理    */
    public void processEnter(int order,int k,int j,Color player_c){
        /* 過去に入力があればtrueなければfalse */
        if( enter[order] == true){
            System.out.println("既に入力されています");
            return;
        }else{
            y_coordinate.get(k).get(j).setBackground(player_c);
            enter[order] = true;
        }
    }
}
public class GameSystem implements ActionListener{
    private int limit;
    private Timer timer;
    private int sec = 0;
    private Combinations<Integer> c ;
    private GameScreen screen ;
    //private Screen sc;
    private ArrayList<Integer> number_a = new ArrayList<Integer>();    //player1の入力
    private ArrayList<Integer> number_b = new ArrayList<Integer>();    //player2の入力
    private boolean finish = false;


    public GameSystem(int l){
        limit = l;
        timer = new Timer(limit*1000,this);
        timer.start();
    }

    public void createCombinations(){
        if(GameScreen.play_turn == !true){
            if(number_a.size() > 3){
                c = new Combinations<Integer>(number_a,4);
                judgeWinner();
            }else{
                return;
            }
        }else{
            if(number_b.size() > 3){
                c = new Combinations<Integer>(number_b,4);
                judgeWinner();
            }else{
                return;
            }
        }

    }
    /*    勝者判定    */
    public void judgeWinner(){
        Iterator<List<Integer>> i = c.iterator();
        while(i.hasNext()){
            List<Integer> t = i.next();
            Collections.sort(t);            //小さい順に並び替え
            Collections.reverse(t);        //大きい順へ
            if(t.get(0)-t.get(3)==3 && t.get(0)-t.get(1)==1    ||
               t.get(0)-t.get(1)==20 && t.get(1)-t.get(2)==20 && t.get(2)-t.get(3)==20 ||
               t.get(0)-t.get(1)==21 && t.get(1)-t.get(2)==21 && t.get(2)-t.get(3)==21 ||
               t.get(0)-t.get(1)==19 && t.get(1)-t.get(2)==19 && t.get(2)-t.get(3)==19 ){
                finish = true;
                System.out.println("ゲーム終了");
            }
        }
    }
    public void addA(int n){
        number_a.add(n);
    }

    public void addB(int n){
        number_b.add(n);
    }

    public int getSecond(){
        return sec;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if(finish == true){
            timer.stop();
            /*後々
            e.setSource(this);
            sc.actionPerformed(e);
            */
        }
        if (sec == limit){
             sec = 0;
            screen.changeTurn();
        }else{
             screen.setTelllimittext(sec);
            sec++;
        }
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

どちらもsecを参照しているためこれがnullになっているのはわかるのですが

残念ながら、この認識自体が違います。

1つ目は、フィールドとしてprivate GameSystem system;となっていますが、コンストラクタ内で代入がまったくないため、setTelllimittext(system.getSecond());のところでもsystem == nullとなっています。

2つ目の方でも同じくprivate GameScreen screen;へのオブジェクト代入がないため、これがnullのままです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/10/10 14:37

    一つ目はGameScreenのコンストラクタでSystemを初期化することで無事解決できました。
    しかし、二つ目の解決法がわかりません。具体的にはscreenをインスタンス化するタイミングがわかりません。GameSystemのほうでGameScreenのインスタンス化を行おうとするとjava.lang.StackOverflowErrorというエラーが発生しました。GameScreenから呼び出されたGameSystemのほうで新たにGameScreenをインスタンス化したため無限ループが発生したのかなと予想しているのですが...これはどのように解決すればよいのでしょう?

    キャンセル

+1

public class GameScreen extends JPanel implements ActionListener{
    private int cn;        //升目の数 cn * cn
    private boolean press = true;
    private JPanel backpane;
    private JLabel telllimit;
    private GameSystem system;
public class GameSystem implements ActionListener{
    private int limit;
    private Timer timer;
    private int sec = 0;
    private Combinations<Integer> c ;
    private GameScreen screen ;

「GameScreen has GameSystem」「GameSystem has GameScreen」の関係で循環参照してしまっているので、まず構造を変えたほうがいいのでは?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/10/10 15:10

    たぶん循環参照による再帰的なコンストラクタ呼び出しがStackOverflowErrorの原因と思われ。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.98%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Java

    12205questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Swing

    199questions

    SwingはJavaに標準で付属するグラフィック関連のクラスライブラリを指します。