带有GUI bug问题的Java Connect4游戏

时间:2016-06-11 16:31:34

标签: java swing grid

http://imgur.com/a/V7LPP 网格图像位于链接

我目前的connect4代码存在两个主要问题,有时“AI”会在一个回合中放置2张光盘,如果没有“AI”进入无限循环,播放器就无法填满整个电路板。任何帮助表示赞赏。

/**
* Auto Generated Java Class.
*/
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class EmptyFrame1 implements ActionListener
{
 //Array of JButtons
   static JButton [] mnuBtn = new JButton[2];
   static JButton [] btnArray = new JButton[7];
   static JLabel [][] board = new JLabel[6][7];
   static int [][] numBoard = new int[6][7];
   static int choice = 0;
   static int playerColour = 1;
   static int computerColour = 2;
   static int computerTurn = 0;
   static ImageIcon emptyGrid = new ImageIcon("EmptyGrid.png");
   static ImageIcon yellowGrid = new ImageIcon("YellowGrid.png");
   static ImageIcon redGrid = new ImageIcon("RedGrid.png");
   static JPanel pnlBoard;
   static boolean validTurn;
   static int pieceCount = 42;

   public EmptyFrame1() 
   { 

     JFrame game = new JFrame("Connect 4");

     //mainFrame panel to hold all components
     JPanel mainFrame = new JPanel();

     pnlBoard = new JPanel();

     pnlBoard.setLayout(new GridLayout(7,6));

     //Change mainFrame layout to vertical BoxLayout
     mainFrame.setLayout(new BoxLayout(mainFrame, BoxLayout.Y_AXIS));

     //For every single button
     //Set the button text to its index value, add an action listener  and add it to the pnlButtons
     for (int i = 0; i < btnArray.length; i++)
     {
       btnArray[i] = new JButton("place");
       btnArray[i].addActionListener(this);
       pnlBoard.add(btnArray[i]);
     }//end for

     for (int r = 0; r < board.length; r++)
     {
       for (int c = 0; c < board[r].length; c++)
       {
         board[r][c] = new JLabel(emptyGrid);
         board[r][c].setPreferredSize(new Dimension(69, 69));
         pnlBoard.add(board[r][c]);
       }//end for
     }//end for

     //Add all the panels to the mainFrame panel
     mainFrame.add(pnlBoard);

     //add mainFrame to the JFrame
     game.add(mainFrame);
     game.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Added this for security
     game.pack();
     game.setVisible(true);
     game.setResizable(false);
   }

   //*Action listener for all buttons*
   public void actionPerformed(ActionEvent e)
   {
     for (int i = 0; i < btnArray.length; i++)
     {
       //if the current button was triggered, set the choice to the button index
       if (btnArray[i] == e.getSource())
       {
         choice = i;
         colCheck(choice, 1);
         //System.out.println("User turn used");
         pieceCount--;

         for (int j = 0; j < btnArray.length; j++) 
         {
      if (numBoard[0][j] == 0) btnArray[j].setEnabled(true);
    }
    if (pieceCount > 0)
    {
      validTurn = false;
      while(!validTurn)
      {
        computerTurn = (int) (Math.random() * 7);

             System.out.print(computerTurn + " ");
             validTurn = colCheck(computerTurn, 2);
             //System.out.println("CPU tried to move");
           } 
         }
         System.out.println();
         setGrid();
         pieceCount--;
         System.out.println(pieceCount);

         validTurn = false;
       }//end if
     }//end for

     pnlBoard.repaint();

   }//end actionPerformed
   public static boolean colCheck(int choice, int currentTurn)
   {
     int row = -1;
     for (int r = 5; r >= 0; r--)
     {
       if (numBoard[r][choice] == 0)
       {
         row = r;
         break;
       }
     }
     //System.out.println("Row That CPU Chooses: " + row);
     if (row > -1)
     {
       numBoard[row][choice] = currentTurn;
       if (row == 0)
       {
         btnArray[choice].setEnabled(false);
         return false;
       }
       return true;
     }
     return false;
   }

   public static void setGrid()
   {
     for (int r = 0; r < numBoard.length; r++)
     {
       for (int c = 0; c < numBoard[r].length; c++)
       {
         if (numBoard [r][c] == 0)
         {
           board[r][c].setIcon(emptyGrid);
         }
         else if (numBoard [r][c] == 1)
         {
           board[r][c].setIcon(redGrid);
         }
         else if (numBoard [r][c] == 2)
         {
           board[r][c].setIcon(yellowGrid);
         }
       }
     }
   }

   /**
    * Inner helper class that defines the graphics
    */


   public static void main(String[] args) 
   { 
     new EmptyFrame1();
   }
 //end constructor

1 个答案:

答案 0 :(得分:1)

一些问题和建议:

  • 您的colCheck方法和actionPerformed方法中的while (!validTurn) {循环是问题所在的位置。
    • 此方法不应设置numBoard值或禁用按钮。换句话说,它不应该有任何&#34;副作用&#34;。
    • 相反,它应该只检查有效性,然后返回一个布尔值,或多或少
    • 如果游戏有效结束,您应该首先调用另一种方法,即检查有效列是否可用。这应该在上面的while循环之前调用,并且应该阻止while循环进入。这将结束您的无限循环问题,因为它循环,因为无法找到计算机转弯的有效列。
    • 您应该有另一种设置numBoard状态以及启用和禁用JButton的方法。

将colCheck更改为此以查看循环的来源:

public static boolean colCheck(int choice, int currentTurn) {
    int row = -1;
    for (int r = 5; r >= 0; r--) {
        if (numBoard[r][choice] == 0) {
            row = r;
            break;
        }
    }
    // System.out.println("Row That CPU Chooses: " + row);
    if (row > -1) {
        numBoard[row][choice] = currentTurn;
        if (row == 0) {
            btnArray[choice].setEnabled(false);
            System.out.printf("debug 1 row %d %n", row);
            return false;
        }
        System.out.printf("debug 2 row %d %n", row);
        return true;
    }
    System.out.printf("debug 3 row %d %n", row);
    return false;
}

与您手头的问题没有直接关系的其他问题,但应解决哪些问题

  • 您严重过度使用静态修饰符,实际上您的所有字段都不应该是静态的。所有都应该是私有实例字段。
  • 您已经获得了程序逻辑代码,模型,与GUI,视图混合在同一个类中,使得难以调试问题和增强程序。如果你可以让你的模型成为一个完全独立的类,那就更好了,那就是&#34; view-agnostic&#34;这意味着它可以自行测试,可以使用任何视图,无论是命令行还是Swing或Android UI。
  • 您的问题取决于我们无法访问的图片,EmptyGrid.png,YellowGrid.png ....阻止我们对其进行测试。
  • 您正在使用幻数(例如0,1,2)作为位置值,并且需要避免这样做。
  • 而是使用枚举用于空,用户和计算机
  • 这是Java而不是Javascript。您希望明确区别,因为它们是两种完全不同的语言。