2017-10-09 3 views
0

私はGUI TicTacToeゲームを何年も前に作りました。コードを600行から約150行に縮小することができました。Java TicTacToeプログラムは、勝ち組合以外の組み合わせで起動します

私は同じスキームを使用していましたが、私は自分で解決できないいくつかの問題に遭遇しましたので、私を助けてください。

プログラムは、2つのクラス、メインクラスTTTMainで構成されています

public class TTTMain { 

public static void main(String[] args) { 
    TTTFrame tttf = new TTTFrame(0,0); 

    /*Tic Tac Toe Field: 
    * 0 1 2 
    * 3 4 5 
    * 6 7 8 
    */ 

}} 

そしてTTTFrame

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

public class TTTFrame extends JFrame implements ActionListener { 

    private Button[] btnPlayButton; 
    private Button btnRestart; 
    private int buttonCounter; 
    private int xScore; 
    private int oScore; 
    private Label Olabel, Xlabel; 

    TTTFrame(int xScore, int oScore) { 

     this.xScore = xScore; 
     this.oScore = oScore; 

     btnPlayButton = new Button[9]; 
     for (int i = 0; i < 9; i++) { 
      btnPlayButton[i] = new Button("" + i); 
      btnPlayButton[i].setBackground(Color.white); 
      btnPlayButton[i].setForeground(Color.white); 
      btnPlayButton[i].addActionListener(this); 
      this.add(btnPlayButton[i]); 
     } 

     Xlabel = new Label("X: " + this.xScore); 
     Xlabel.setFont(new Font("Arial", Font.BOLD, 24)); 
     Xlabel.setForeground(Color.white); 
     Xlabel.setBackground(Color.black); 
     this.add(Xlabel); 

     btnRestart = new Button("Restart"); 
     btnRestart.setActionCommand("Restart"); 
     btnRestart.setFont(new Font("Arial", Font.PLAIN, 18)); 
     btnRestart.addActionListener(this); 
     this.add(btnRestart); 

     Olabel = new Label("O: " + this.oScore); 
     Olabel.setFont(new Font("Arial", Font.BOLD, 24)); 
     Olabel.setForeground(Color.white); 
     Olabel.setBackground(Color.black); 
     this.add(Olabel); 

     this.setLayout(new GridLayout(4, 3)); 
     this.pack(); 
     this.setResizable(true); 
     this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     this.setTitle("Tic Tac Toe"); 
     this.setSize(300, 400); 
     this.getContentPane().setBackground(Color.black); 
     this.setVisible(true); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 

     if (e.getActionCommand().equals("Restart")) { 
      System.out.println("Restarted"); 
      for (int i = 0; i < 9; i++) { 

       btnPlayButton[i].setLabel("" + i); 
       btnPlayButton[i].setForeground(Color.white); 
       btnPlayButton[i].setBackground(Color.white); 
       btnPlayButton[i].addActionListener(this); 

       this.buttonCounter = 0; 
      } 
     } else { 

      ((Button) e.getSource()).setFont(new Font("Arial", Font.BOLD, 48)); 
      ((Button) e.getSource()).setForeground(Color.black); 
      System.out.println(buttonCounter); 
      if (buttonCounter % 2 == 0) { 
       ((Button) e.getSource()).setLabel("X"); 
       ((Button) e.getSource()).removeActionListener(this); 
      } else { 
       ((Button) e.getSource()).setLabel("O"); 
       ((Button) e.getSource()).removeActionListener(this); 
      } 
      buttonCounter++; 
      CheckField(); 
     } 

    } 

    private void CheckField() { 

     if (ButtonsWithIdenticalLabels(0, 1, 2)) { 

      Deactivatebuttons(); 
     } 
     if (ButtonsWithIdenticalLabels(3, 4, 5)) { 

      Deactivatebuttons(); 
     } 
     if (ButtonsWithIdenticalLabels(6, 7, 8)) { 

      Deactivatebuttons(); 
     } 
     if (ButtonsWithIdenticalLabels(0, 3, 6)) { 

      Deactivatebuttons(); 
     } 
     if (ButtonsWithIdenticalLabels(1, 4, 7)) { 

      Deactivatebuttons(); 
     } 
     if (ButtonsWithIdenticalLabels(2, 5, 8)) { 

      Deactivatebuttons(); 
     } 
     if (ButtonsWithIdenticalLabels(0, 4, 8)) { 

      Deactivatebuttons(); 
     } 
     if (ButtonsWithIdenticalLabels(2, 4, 6)) { 

      Deactivatebuttons(); 
     } 
    } 

    private boolean ButtonsWithIdenticalLabels(int i, int j, int k) { 
     if (btnPlayButton[i].getLabel() == btnPlayButton[j].getLabel() 
       && btnPlayButton[j].getLabel() == btnPlayButton[k].getLabel()) { 

      btnPlayButton[i].setBackground(Color.red); 
      btnPlayButton[j].setBackground(Color.red); 
      btnPlayButton[k].setBackground(Color.red); 

      if (btnPlayButton[i].getLabel().equals("X")) { 
       xScore++; 
       Xlabel.setText("X: " + xScore); 
      } else { 
       oScore++; 
       Olabel.setText("O: " + oScore); 
      } 

      return true; 
     } else { 
      return false; 
     } 
    } 

    private void Deactivatebuttons() { 
     for (int i = 0; i < 9; i++) { 
      btnPlayButton[i].removeActionListener(this); 
     } 
    } 
} 

今私はプログラムがどのように動作するかを説明しましょう。 3x3の競技場はButtonArray で作られています。ボタンはというラベルで比較されたであるため、ゲームの開始時に一致するラベルを持たないように、ボタンは作成時に1から9のラベルが付いています。ここでは:あなたがbtnPlayButtonをクリックするたびに

for (int i = 0; i < 9; i++) { 
     btnPlayButton[i] = new Button("" + i); // Right here 
     btnPlayButton[i].setBackground(Color.white); 
     btnPlayButton[i].setForeground(Color.white); 
     btnPlayButton[i].addActionListener(this); 
     this.add(btnPlayButton[i]); 
    } 

、プログラムはactionPerformedメソッドにジャンプします。 btnPlayButtonsにはActionCommandがないため、メソッドのelseセクションにジャンプします。ここでは、int buttonCounterは1だけ大きくなります.Wether buttonCounterは偶数または奇数です。クリックされたbtnPlayButtonは、 "X"または "O"でラベル付けされます。 buttonCounterはクリックごとに+1を取得するため、XとOは交互に表示されます。クリックしたボタンの

else { 

    ((Button) e.getSource()).setFont(new Font("Arial", Font.BOLD, 48)); 
    ((Button) e.getSource()).setForeground(Color.black); 
    System.out.println(buttonCounter); 
    if (buttonCounter % 2 == 0) { 
     ((Button) e.getSource()).setLabel("X"); 
     ((Button) e.getSource()).removeActionListener(this); 
    } else { 
     ((Button) e.getSource()).setLabel("O"); 
     ((Button) e.getSource()).removeActionListener(this); 
    } 
    buttonCounter++; 
    CheckField(); 
} 

ActionListener不正行為を防ぐために削除されます。ここでは

は、セクションが言われています。すべてのボタンプレスで、競技場は勝ち組合のためにチェックされます。これはCheckField()で発生します。 CheckField()

、またはより正確に、btnPlayButtons[x]btnPlayButtons[y]btnPlayButtons[z]ButtonsWithIdenticalLabels(x, y, z)ラベルは、それらが同一である場合、それは真を返し、採取し、比較することができます。 btnPlayButton以来

は次のように命じています

0 1 2 
3 4 5 
6 7 8 

勝ちの組み合わせは以下のとおりです。012,345,678,036,147,258,045と

246そう、例えば、btnPlayButton[0]btnPlayButton[1]btnPlayButton[2]全てが同じラベルを持っている場合。 ButtonsWithIdenticalLabelsが真となり、プログラムはDeactivatebuttons()にジャンプし、btnPlayButtonがすべて無効になり、勝ち組が見つかってゲームが終了したことを意味します。 btnPlayButton[1]のラベルが "X"の場合、int xScoreに1が追加されます。また、btnPlayButton[0],btnPlayButton[1]およびbtnPlayButton[2]は、審美的には赤色に塗りつぶされます。

Restartボタンを使用すると、forループにジャンプして、btnPlayButtonを再度ラベル付けし、TTTFrameに実装されているActionListenerを追加します。 buttonCounterも0にリセットされています。再ラベリングは、クラスの初めに1と同じです。

if (e.getActionCommand().equals("Restart")) { 
      System.out.println("Restarted"); 
      for (int i = 0; i < 9; i++) { 

       btnPlayButton[i].setLabel("" + i); 
       btnPlayButton[i].setForeground(Color.white); 
       btnPlayButton[i].setBackground(Color.white); 
       btnPlayButton[i].addActionListener(this); 

       this.buttonCounter = 0; 
      } 

今の問題は、私が持っているということですいくつかの再起動後、XとOの標識はもはや交互にされていないこと、です。時には3行のOと時にはフィールドは次のようにありますが認識し得ている

Picture

に勝つ誰かがこのバグを修正する方法を知っているかのように私は本当に幸せになると思います。事前に

おかげで、

Fihdi

+2

質問でこの多くのコードを使用すると、ここで助けを得ることはあまりありません。すでに自分でデバッグしようとしましたか?それはあなたがバグを見つけ、ここでより具体的な質問に戻ってくるのを助けるはずです。 –

+4

ようこそスタックオーバーフロー! [ツアー](ツアー)を見て回り、[ヘルプセンター](/ help)、特に[どのように良い質問をしますか?](/ help/how-to-質問)と[ここではどのような話題について聞くことができますか?](/ help/on-topic) [Java命名規則](http://www.oracle.com/technetwork/java/codeconventions-135099.html) –

+0

https://ericlippert.com/2014/03/05/howをお読みください-to-debug-small-programs/ – slim

答えて

1

は、ここでの問題は次のとおりです。あなたがゲームを再起動すると、新しいActionListenerは、すべてのボタンに追加されます。ただし、クリックするか、誰かがゲームに勝利したときにのみ削除されます。つまり、勝利する前にゲームを再開すると、クリックされていないボタンはすべてActionListenerとなり、クリックは2回登録され、このバグが表示されます。ボードをリセットする前にDeactivateButtons()に電話してみてください。