Basic Connect Four Game 2












0












$begingroup$


so here is an updated version of a basic connect four game I had posted previously. Changes include:




  • an overhauled validator, simplifying the process by knowing where the
    last move was made

  • Utilized an array with elements referncing how full each column is to simplify the logic of making a move and checking for a tie

  • The game is now GUI based utilizing swing to build both the game and main menus, built on top of the previous text based logic and
    functions

  • Added the ability to save, load, and start new games from the GUI menu


Constructive criticism/suggestions related to OOD/OOP as well as how to improve the game GUI are especially welcome, as that is where I think I need the most improvement currently. My next steps should involve adding the ability for players to play over a network, so any tips or advice to get there from where I'm at would be appreciated too.



ConnectFour.Java



import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;

public class ConnectFour implements Serializable {
private int gameBoard;
private int piecesInColumn; // Each index keeps track of how many game pieces are currently in the corresponding column
private static final int ROWS = 6;
private static final int COLUMNS = 7;
private static final int RED = 1;
private static final int YELLOW = 2;
private Player playerOne;
private Player playerTwo;
private int totalNumTurns;

public ConnectFour() {
this.gameBoard = new int[ROWS][COLUMNS];
this.piecesInColumn = new int[COLUMNS];
//Initialize each position in the game board to empty
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLUMNS; j++) {
gameBoard[i][j] = -1;
}
}

this.totalNumTurns = 0;

}

public static void main(String args) {
new ConnectFour().buildMainMenu();

}

public void buildMainMenu(){
// Construct a main menu that welcomes players and takes their names

JFrame mainFrame = new JFrame();
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JLabel title = new JLabel("Welcome to Connect Four!");
Font titleFont = new Font(Font.SERIF, Font.BOLD, 20);
title.setFont(titleFont);
JPanel titlePanel = new JPanel();
titlePanel.add(title);

JTextField nameOne = new JTextField(10);
JLabel nameOneLabel = new JLabel("Player one's name:");
JTextField nameTwo = new JTextField(10);
JLabel nameTwoLabel = new JLabel("Player two's name");
JPanel namesPanel = new JPanel();
namesPanel.setLayout(new BoxLayout(namesPanel, BoxLayout.Y_AXIS));
namesPanel.add(nameOneLabel);
namesPanel.add(nameOne);
namesPanel.add(nameTwoLabel);
namesPanel.add(nameTwo);

JButton startGameButton = new JButton("Start Game!");

startGameButton.addActionListener(new ActionListener(){

@Override
public void actionPerformed(ActionEvent e) {
//Once we press start game, create player objects based on the names, close the window and open a new window with the game GUI
playerOne = new Player(nameOne.getText());
playerTwo = new Player(nameTwo.getText());
System.out.println("Welcome player one: " + playerOne.getName());
System.out.println("Welcome player two: " + playerTwo.getName());
mainFrame.dispose();
buildGameGUI();
}
});

JPanel startGamePanel = new JPanel();
startGamePanel.add(startGameButton);

JPanel centerPanel = new JPanel();
centerPanel.add(namesPanel);

mainFrame.getContentPane().add(BorderLayout.NORTH,titlePanel);
mainFrame.getContentPane().add(BorderLayout.SOUTH, startGamePanel);
mainFrame.getContentPane().add(BorderLayout.CENTER,centerPanel);
mainFrame.setSize(400,200);
mainFrame.setVisible(true);

}

public void buildGameGUI(){

JFrame gameFrame = new JFrame();
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

gameFrame.setSize(500,500);
gameFrame.setVisible(true);

ConnectFourVisualizer gameVisualizer = new ConnectFourVisualizer();

gameFrame.add(BorderLayout.CENTER, gameVisualizer);

JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
JMenuItem exit = new JMenuItem("Exit");

JPanel chooseMovePanel = new JPanel();
JLabel chooseMoveLabel = new JLabel( playerOne.getName() + ", Choose a column from 1 to 7: ");
JTextField moveChoiceField = new JTextField(5);
JButton chooseMoveButton = new JButton("Choose");

exit.addActionListener(new ActionListener() {
//Close the window and stop the program if the user clicks exit
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});

JMenuItem loadGame = new JMenuItem("Load Game");
//Add an action listener here for loading the game
//1.) Restore the state of connect four object from the connect_four.ser file
//2.) Repaint the game board gui to display the previous state's game board and allow the game to continue

JMenuItem saveGame = new JMenuItem("Save Game");
JMenuItem newGame = new JMenuItem("New Game");

newGame.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//Reset the board and redraw the visual representation based on the empty board
clearBoard();
gameVisualizer.repaint();
totalNumTurns = 0;
piecesInColumn = new int[COLUMNS];
chooseMoveLabel.setText(playerOne.getName() + ", Choose a column from 1 to 7: ");
//Re-enable the buttons and text field in case the previous game had a winner
moveChoiceField.setEnabled(true);
chooseMoveButton.setEnabled(true);

}
});

saveGame.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try{
FileOutputStream fileOutputStream = new FileOutputStream("connect_four.ser");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(ConnectFour.this);
objectOutputStream.close();
fileOutputStream.close();
}catch (IOException ex){
ex.printStackTrace();
}
}
});

loadGame.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {

//Set the current Connect four object references and values equal to the previously saved games values
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("connect_four.ser"));
ConnectFour previousGame = (ConnectFour) objectInputStream.readObject();
ConnectFour.this.gameBoard = previousGame.gameBoard;
ConnectFour.this.piecesInColumn = previousGame.piecesInColumn;
ConnectFour.this.playerOne = previousGame.playerOne;
ConnectFour.this.playerTwo = previousGame.playerTwo;
ConnectFour.this.totalNumTurns = previousGame.totalNumTurns;

System.out.println("The number of turns is: " + totalNumTurns);

//Determine whose turn it was when the game was saved, and display the appropriate label
if(totalNumTurns % 2 == 0){
chooseMoveLabel.setText(playerOne.getName() + ", choose a column from 1 to 7:");
}

else{
chooseMoveLabel.setText(playerTwo.getName() + ", choose a column from 1 to 7");
}

}catch(Exception ex){
ex.printStackTrace();
}
//Redraw the game gui no correctly show the loaded game state
gameVisualizer.repaint();
printGameBoard();
}
});

//Add the menu items to the menua bar
fileMenu.add(newGame);
fileMenu.add(saveGame);
fileMenu.add(loadGame);
fileMenu.add(exit);
menuBar.add(fileMenu);

gameFrame.getContentPane().add(BorderLayout.NORTH,menuBar);


chooseMovePanel.add(chooseMoveLabel);
chooseMovePanel.add(moveChoiceField);
chooseMovePanel.add(chooseMoveButton);

gameFrame.getContentPane().add(BorderLayout.SOUTH, chooseMovePanel);


chooseMoveButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {

//Notice here we're displaying whose turn in is after the current player makes their move
int move = Integer.parseInt(moveChoiceField.getText());
if(totalNumTurns % 2 == 0){
//It's player one's turn, so make their move and after change the text to ask for player two
boolean attempt = makeMove(playerOne, move);
if(attempt == false){
chooseMoveLabel.setText("That was an invalid move, please try again " + playerOne.getName()+ ":");
moveChoiceField.setText("");
return;
}
chooseMoveLabel.setText(playerTwo.getName() + ", choose a column from 1 to 7:");
moveChoiceField.setText("");
}

else{
//Otherwise it's player two's turn, so make their move and change the text to ask for player one
boolean attempt = makeMove(playerTwo, move);
if(attempt == false){
chooseMoveLabel.setText("That was an invalid move, please try again " + playerTwo.getName() + ":");
moveChoiceField.setText("");
return;
}
chooseMoveLabel.setText(playerOne.getName() + ", choose a column from 1 to 7:");
moveChoiceField.setText("");
}
printGameBoard();
totalNumTurns++;
gameVisualizer.repaint();
int hasWinner = checkForWinner(move);
if(hasWinner != -1){
moveChoiceField.setEnabled(false);
chooseMoveButton.setEnabled(false);
saveGame.setEnabled(false);
if(hasWinner == RED){
chooseMoveLabel.setText(playerOne.getName() + " wins!");

}
else if(hasWinner == YELLOW){
chooseMoveLabel.setText(playerTwo.getName() + " wins!");
}
}
}
});
}

public class ConnectFourVisualizer extends JPanel{
private int xBackground;
private int yBackground;
private int widthBackground;
private int heightBackGround;
private int xGameSlot;
private int yGameSlot;
private int widthGameSlot;
private int heightGameSlot;

public ConnectFourVisualizer(){
this.widthGameSlot = 20;
this.heightGameSlot = 20;

this.heightBackGround = 300;
this.widthBackground = 350;

this.xBackground = 75;
this.yBackground = 100;
}

public void paintComponent(Graphics g){
g.setColor(Color.YELLOW);
g.fillRect(xBackground, yBackground, widthBackground, heightBackGround);
int currentX = xBackground + 40;
int currentY = yBackground + 40;

for(int i = 0; i < 6; i++) {


for (int j = 0; j < 7; j++) {
if(gameBoard[i][j] == RED){
g.setColor(Color.RED);
}
else if(gameBoard[i][j] == YELLOW){
g.setColor(Color.BLACK);
}
else{
g.setColor(Color.WHITE);
}

g.fillOval(currentX, currentY, widthGameSlot, heightGameSlot);
currentX += 40;

}
currentX = xBackground + 40;
currentY += 40;

}
}
}


public boolean makeMove(Player player, int column) {
/* Since row position is determined by how many pieces are currently in a given column,
we only need to choose a column position and the row position will be determined as a result. */

//Decrement the column value by 1, as our array is zero indexed.
column--;

//Check if the column chosen is valid
if (column < 0 || column >= COLUMNS) {
System.out.println("Column choice must be between 1 and 7 !");
return false;
}

//Check if the column chosen is already full
if (isColumnFull(column)) {
System.out.println("That column is already full!");
return false;
}
/*Otherwise, start from the bottom of the column and change the value in
the first open row to the player's number*/
else {
// for (int i = ROWS - 1; i >= 0; i--) {
// if (gameBoard[i][column] == -1) {
// gameBoard[i][column] = player.getPlayerNumber();
// break;
// }
// }
// return true;
int nextOpenRow = ROWS - 1 - piecesInColumn[column];
gameBoard[nextOpenRow][column] = player.getPlayerNumber();
piecesInColumn[column]++;
return true;
}

}


public int checkForWinner(int latestMove){

//If the gameboard is full, the game is a TIE
if(isBoardFull()){
// 0 indicates a TIE
return 0;
}

int currentCol = latestMove - 1; //Remember, the user sees the columns numbered 1 -> 7 but our array is 0 indexed
int currentRow = ROWS - piecesInColumn[currentCol]; // Determine which row the last piece was placed in

int rows = checkRows(currentRow);
int columns = checkColumns(currentCol);
int diagonals = checkDiagonals(currentRow,currentCol);


if(rows == RED || columns == RED || diagonals == RED){
return RED;
}

if(rows == YELLOW || columns == YELLOW || diagonals == YELLOW){
return YELLOW;
}

//Otherwise we don't have a winner yer

return -1;
}

private int checkRows(int currentRow){
//Obtain the row and column of the latest move

for (int i = 0; i < COLUMNS - 3; i++) {

if (gameBoard[currentRow][i] == RED &&
gameBoard[currentRow][i + 1] == RED &&
gameBoard[currentRow][i + 2] == RED &&
gameBoard[currentRow][i + 3] == RED) {

return RED;
}

if (gameBoard[currentRow][i] == YELLOW &&
gameBoard[currentRow][i + 1] == YELLOW &&
gameBoard[currentRow][i + 2] == YELLOW &&
gameBoard[currentRow][i + 3] == YELLOW) {

return YELLOW;
}
}
//Otherwise, we have no winner yet
return -1;
}

private int checkColumns( int currentCol){
//Check the column

// if(piecesInColumn[currentCol] < 4){
// //If there are less than 4 game pieces in the column, there cannot be a winner here by column
// return -1;
// }

for (int i = ROWS - 1; i >= ROWS - 3; i--) {
if (gameBoard[i][currentCol] == RED &&
gameBoard[i - 1][currentCol] == RED &&
gameBoard[i - 2][currentCol] == RED &&
gameBoard[i - 3][currentCol] == RED) {

return RED;
}

if (gameBoard[i][currentCol] == YELLOW &&
gameBoard[i - 1][currentCol] == YELLOW &&
gameBoard[i - 2][currentCol] == YELLOW &&
gameBoard[i - 3][currentCol] == YELLOW) {

return YELLOW;
}

}

//Otherwise we have no winner
return -1;

}

private int checkDiagonals(int currentRow, int currentCol){
//Check the left-to-right upward diagonal containing the latest move

int startingRow = currentRow + 3;
int startingCol = currentCol - 3;

//get to a starting position that is valid on the board
while (startingRow > ROWS - 1 || startingCol < 0) {
startingRow--;
startingCol++;
}

while (startingRow - 3 >= 0 && startingCol + 3 < COLUMNS ) {
if (gameBoard[startingRow][startingCol] == RED &&
gameBoard[startingRow - 1][startingCol + 1] == RED &&
gameBoard[startingRow - 2][startingCol + 2] == RED &&
gameBoard[startingRow - 3][startingCol + 3] == RED) {

return RED;
}

if (gameBoard[startingRow][startingCol] == YELLOW &&
gameBoard[startingRow - 1][startingCol + 1] == YELLOW &&
gameBoard[startingRow - 2][startingCol + 2] == YELLOW &&
gameBoard[startingRow - 3][startingCol + 3] == YELLOW) {

return YELLOW;
}
startingRow--;
startingCol++;

}

//Check the left to right downward diagonal containing the latest placed game piece

//Reset the starting row and column variables
startingRow = currentRow - 3;
startingCol = currentCol - 3;

while(startingRow < 0 || startingCol < 0 ){
startingCol++;
startingRow++;
}

while(startingRow + 3 < ROWS && startingCol + 3 < COLUMNS ){
if(gameBoard[startingRow][startingCol] == RED &&
gameBoard[startingRow + 1][startingCol + 1] == RED &&
gameBoard[startingRow + 2][startingCol + 2] == RED &&
gameBoard[startingRow + 3][startingCol + 3] == RED){

return RED;
}

if(gameBoard[startingRow][startingCol] == YELLOW &&
gameBoard[startingRow + 1][startingCol + 1] == YELLOW &&
gameBoard[startingRow + 2][startingCol + 2] == YELLOW &&
gameBoard[startingRow + 3][startingCol + 3] == YELLOW){

return YELLOW;
}

startingRow++;
startingCol++;

}

//Otherwise, we have no winner yet
return -1;

}

private boolean isColumnFull(int columnNumber) {
/*Based on the way pieces are placed in a game of connect four, if the very first row of a column has
a piece in it, the column must be full.*/
if (gameBoard[0][columnNumber] == -1) {
return false;
} else {
return true;
}
}

private boolean isBoardFull() {
//If any value in our board is -1, the board is not full
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLUMNS; j++) {
if (gameBoard[i][j] == -1) {
return false;
}
}
}
//Otherwise the board is full
return true;
}

public void printGameBoard() {
System.out.println("==============================");
//Display the number for each column
System.out.println("1 2 3 4 5 6 7");
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLUMNS; j++) {
if (gameBoard[i][j] == RED) {
System.out.print("R ");
} else if (gameBoard[i][j] == YELLOW) {
System.out.print("Y ");
} else {
System.out.print("- ");
}
}
System.out.println();
}
System.out.println("==============================");
}

public void clearBoard() {
//Reset all board positions to -1
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLUMNS; j++) {
gameBoard[i][j] = -1;
}
}
}
}


Player.Java:



import java.io.Serializable;

public class Player implements Serializable {

private final String name;
private static int counter = 0;
private int playerNumber;


public Player(String name) {
this.name = name;
this.counter++;
this.playerNumber = counter;
}

public String getName() {
return name;
}

public int getPlayerNumber() {
return playerNumber;
}

}









share|improve this question









$endgroup$

















    0












    $begingroup$


    so here is an updated version of a basic connect four game I had posted previously. Changes include:




    • an overhauled validator, simplifying the process by knowing where the
      last move was made

    • Utilized an array with elements referncing how full each column is to simplify the logic of making a move and checking for a tie

    • The game is now GUI based utilizing swing to build both the game and main menus, built on top of the previous text based logic and
      functions

    • Added the ability to save, load, and start new games from the GUI menu


    Constructive criticism/suggestions related to OOD/OOP as well as how to improve the game GUI are especially welcome, as that is where I think I need the most improvement currently. My next steps should involve adding the ability for players to play over a network, so any tips or advice to get there from where I'm at would be appreciated too.



    ConnectFour.Java



    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.io.*;

    public class ConnectFour implements Serializable {
    private int gameBoard;
    private int piecesInColumn; // Each index keeps track of how many game pieces are currently in the corresponding column
    private static final int ROWS = 6;
    private static final int COLUMNS = 7;
    private static final int RED = 1;
    private static final int YELLOW = 2;
    private Player playerOne;
    private Player playerTwo;
    private int totalNumTurns;

    public ConnectFour() {
    this.gameBoard = new int[ROWS][COLUMNS];
    this.piecesInColumn = new int[COLUMNS];
    //Initialize each position in the game board to empty
    for (int i = 0; i < ROWS; i++) {
    for (int j = 0; j < COLUMNS; j++) {
    gameBoard[i][j] = -1;
    }
    }

    this.totalNumTurns = 0;

    }

    public static void main(String args) {
    new ConnectFour().buildMainMenu();

    }

    public void buildMainMenu(){
    // Construct a main menu that welcomes players and takes their names

    JFrame mainFrame = new JFrame();
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JLabel title = new JLabel("Welcome to Connect Four!");
    Font titleFont = new Font(Font.SERIF, Font.BOLD, 20);
    title.setFont(titleFont);
    JPanel titlePanel = new JPanel();
    titlePanel.add(title);

    JTextField nameOne = new JTextField(10);
    JLabel nameOneLabel = new JLabel("Player one's name:");
    JTextField nameTwo = new JTextField(10);
    JLabel nameTwoLabel = new JLabel("Player two's name");
    JPanel namesPanel = new JPanel();
    namesPanel.setLayout(new BoxLayout(namesPanel, BoxLayout.Y_AXIS));
    namesPanel.add(nameOneLabel);
    namesPanel.add(nameOne);
    namesPanel.add(nameTwoLabel);
    namesPanel.add(nameTwo);

    JButton startGameButton = new JButton("Start Game!");

    startGameButton.addActionListener(new ActionListener(){

    @Override
    public void actionPerformed(ActionEvent e) {
    //Once we press start game, create player objects based on the names, close the window and open a new window with the game GUI
    playerOne = new Player(nameOne.getText());
    playerTwo = new Player(nameTwo.getText());
    System.out.println("Welcome player one: " + playerOne.getName());
    System.out.println("Welcome player two: " + playerTwo.getName());
    mainFrame.dispose();
    buildGameGUI();
    }
    });

    JPanel startGamePanel = new JPanel();
    startGamePanel.add(startGameButton);

    JPanel centerPanel = new JPanel();
    centerPanel.add(namesPanel);

    mainFrame.getContentPane().add(BorderLayout.NORTH,titlePanel);
    mainFrame.getContentPane().add(BorderLayout.SOUTH, startGamePanel);
    mainFrame.getContentPane().add(BorderLayout.CENTER,centerPanel);
    mainFrame.setSize(400,200);
    mainFrame.setVisible(true);

    }

    public void buildGameGUI(){

    JFrame gameFrame = new JFrame();
    gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    gameFrame.setSize(500,500);
    gameFrame.setVisible(true);

    ConnectFourVisualizer gameVisualizer = new ConnectFourVisualizer();

    gameFrame.add(BorderLayout.CENTER, gameVisualizer);

    JMenuBar menuBar = new JMenuBar();
    JMenu fileMenu = new JMenu("File");
    JMenuItem exit = new JMenuItem("Exit");

    JPanel chooseMovePanel = new JPanel();
    JLabel chooseMoveLabel = new JLabel( playerOne.getName() + ", Choose a column from 1 to 7: ");
    JTextField moveChoiceField = new JTextField(5);
    JButton chooseMoveButton = new JButton("Choose");

    exit.addActionListener(new ActionListener() {
    //Close the window and stop the program if the user clicks exit
    @Override
    public void actionPerformed(ActionEvent e) {
    System.exit(0);
    }
    });

    JMenuItem loadGame = new JMenuItem("Load Game");
    //Add an action listener here for loading the game
    //1.) Restore the state of connect four object from the connect_four.ser file
    //2.) Repaint the game board gui to display the previous state's game board and allow the game to continue

    JMenuItem saveGame = new JMenuItem("Save Game");
    JMenuItem newGame = new JMenuItem("New Game");

    newGame.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
    //Reset the board and redraw the visual representation based on the empty board
    clearBoard();
    gameVisualizer.repaint();
    totalNumTurns = 0;
    piecesInColumn = new int[COLUMNS];
    chooseMoveLabel.setText(playerOne.getName() + ", Choose a column from 1 to 7: ");
    //Re-enable the buttons and text field in case the previous game had a winner
    moveChoiceField.setEnabled(true);
    chooseMoveButton.setEnabled(true);

    }
    });

    saveGame.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
    try{
    FileOutputStream fileOutputStream = new FileOutputStream("connect_four.ser");
    ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
    objectOutputStream.writeObject(ConnectFour.this);
    objectOutputStream.close();
    fileOutputStream.close();
    }catch (IOException ex){
    ex.printStackTrace();
    }
    }
    });

    loadGame.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
    try {

    //Set the current Connect four object references and values equal to the previously saved games values
    ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("connect_four.ser"));
    ConnectFour previousGame = (ConnectFour) objectInputStream.readObject();
    ConnectFour.this.gameBoard = previousGame.gameBoard;
    ConnectFour.this.piecesInColumn = previousGame.piecesInColumn;
    ConnectFour.this.playerOne = previousGame.playerOne;
    ConnectFour.this.playerTwo = previousGame.playerTwo;
    ConnectFour.this.totalNumTurns = previousGame.totalNumTurns;

    System.out.println("The number of turns is: " + totalNumTurns);

    //Determine whose turn it was when the game was saved, and display the appropriate label
    if(totalNumTurns % 2 == 0){
    chooseMoveLabel.setText(playerOne.getName() + ", choose a column from 1 to 7:");
    }

    else{
    chooseMoveLabel.setText(playerTwo.getName() + ", choose a column from 1 to 7");
    }

    }catch(Exception ex){
    ex.printStackTrace();
    }
    //Redraw the game gui no correctly show the loaded game state
    gameVisualizer.repaint();
    printGameBoard();
    }
    });

    //Add the menu items to the menua bar
    fileMenu.add(newGame);
    fileMenu.add(saveGame);
    fileMenu.add(loadGame);
    fileMenu.add(exit);
    menuBar.add(fileMenu);

    gameFrame.getContentPane().add(BorderLayout.NORTH,menuBar);


    chooseMovePanel.add(chooseMoveLabel);
    chooseMovePanel.add(moveChoiceField);
    chooseMovePanel.add(chooseMoveButton);

    gameFrame.getContentPane().add(BorderLayout.SOUTH, chooseMovePanel);


    chooseMoveButton.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {

    //Notice here we're displaying whose turn in is after the current player makes their move
    int move = Integer.parseInt(moveChoiceField.getText());
    if(totalNumTurns % 2 == 0){
    //It's player one's turn, so make their move and after change the text to ask for player two
    boolean attempt = makeMove(playerOne, move);
    if(attempt == false){
    chooseMoveLabel.setText("That was an invalid move, please try again " + playerOne.getName()+ ":");
    moveChoiceField.setText("");
    return;
    }
    chooseMoveLabel.setText(playerTwo.getName() + ", choose a column from 1 to 7:");
    moveChoiceField.setText("");
    }

    else{
    //Otherwise it's player two's turn, so make their move and change the text to ask for player one
    boolean attempt = makeMove(playerTwo, move);
    if(attempt == false){
    chooseMoveLabel.setText("That was an invalid move, please try again " + playerTwo.getName() + ":");
    moveChoiceField.setText("");
    return;
    }
    chooseMoveLabel.setText(playerOne.getName() + ", choose a column from 1 to 7:");
    moveChoiceField.setText("");
    }
    printGameBoard();
    totalNumTurns++;
    gameVisualizer.repaint();
    int hasWinner = checkForWinner(move);
    if(hasWinner != -1){
    moveChoiceField.setEnabled(false);
    chooseMoveButton.setEnabled(false);
    saveGame.setEnabled(false);
    if(hasWinner == RED){
    chooseMoveLabel.setText(playerOne.getName() + " wins!");

    }
    else if(hasWinner == YELLOW){
    chooseMoveLabel.setText(playerTwo.getName() + " wins!");
    }
    }
    }
    });
    }

    public class ConnectFourVisualizer extends JPanel{
    private int xBackground;
    private int yBackground;
    private int widthBackground;
    private int heightBackGround;
    private int xGameSlot;
    private int yGameSlot;
    private int widthGameSlot;
    private int heightGameSlot;

    public ConnectFourVisualizer(){
    this.widthGameSlot = 20;
    this.heightGameSlot = 20;

    this.heightBackGround = 300;
    this.widthBackground = 350;

    this.xBackground = 75;
    this.yBackground = 100;
    }

    public void paintComponent(Graphics g){
    g.setColor(Color.YELLOW);
    g.fillRect(xBackground, yBackground, widthBackground, heightBackGround);
    int currentX = xBackground + 40;
    int currentY = yBackground + 40;

    for(int i = 0; i < 6; i++) {


    for (int j = 0; j < 7; j++) {
    if(gameBoard[i][j] == RED){
    g.setColor(Color.RED);
    }
    else if(gameBoard[i][j] == YELLOW){
    g.setColor(Color.BLACK);
    }
    else{
    g.setColor(Color.WHITE);
    }

    g.fillOval(currentX, currentY, widthGameSlot, heightGameSlot);
    currentX += 40;

    }
    currentX = xBackground + 40;
    currentY += 40;

    }
    }
    }


    public boolean makeMove(Player player, int column) {
    /* Since row position is determined by how many pieces are currently in a given column,
    we only need to choose a column position and the row position will be determined as a result. */

    //Decrement the column value by 1, as our array is zero indexed.
    column--;

    //Check if the column chosen is valid
    if (column < 0 || column >= COLUMNS) {
    System.out.println("Column choice must be between 1 and 7 !");
    return false;
    }

    //Check if the column chosen is already full
    if (isColumnFull(column)) {
    System.out.println("That column is already full!");
    return false;
    }
    /*Otherwise, start from the bottom of the column and change the value in
    the first open row to the player's number*/
    else {
    // for (int i = ROWS - 1; i >= 0; i--) {
    // if (gameBoard[i][column] == -1) {
    // gameBoard[i][column] = player.getPlayerNumber();
    // break;
    // }
    // }
    // return true;
    int nextOpenRow = ROWS - 1 - piecesInColumn[column];
    gameBoard[nextOpenRow][column] = player.getPlayerNumber();
    piecesInColumn[column]++;
    return true;
    }

    }


    public int checkForWinner(int latestMove){

    //If the gameboard is full, the game is a TIE
    if(isBoardFull()){
    // 0 indicates a TIE
    return 0;
    }

    int currentCol = latestMove - 1; //Remember, the user sees the columns numbered 1 -> 7 but our array is 0 indexed
    int currentRow = ROWS - piecesInColumn[currentCol]; // Determine which row the last piece was placed in

    int rows = checkRows(currentRow);
    int columns = checkColumns(currentCol);
    int diagonals = checkDiagonals(currentRow,currentCol);


    if(rows == RED || columns == RED || diagonals == RED){
    return RED;
    }

    if(rows == YELLOW || columns == YELLOW || diagonals == YELLOW){
    return YELLOW;
    }

    //Otherwise we don't have a winner yer

    return -1;
    }

    private int checkRows(int currentRow){
    //Obtain the row and column of the latest move

    for (int i = 0; i < COLUMNS - 3; i++) {

    if (gameBoard[currentRow][i] == RED &&
    gameBoard[currentRow][i + 1] == RED &&
    gameBoard[currentRow][i + 2] == RED &&
    gameBoard[currentRow][i + 3] == RED) {

    return RED;
    }

    if (gameBoard[currentRow][i] == YELLOW &&
    gameBoard[currentRow][i + 1] == YELLOW &&
    gameBoard[currentRow][i + 2] == YELLOW &&
    gameBoard[currentRow][i + 3] == YELLOW) {

    return YELLOW;
    }
    }
    //Otherwise, we have no winner yet
    return -1;
    }

    private int checkColumns( int currentCol){
    //Check the column

    // if(piecesInColumn[currentCol] < 4){
    // //If there are less than 4 game pieces in the column, there cannot be a winner here by column
    // return -1;
    // }

    for (int i = ROWS - 1; i >= ROWS - 3; i--) {
    if (gameBoard[i][currentCol] == RED &&
    gameBoard[i - 1][currentCol] == RED &&
    gameBoard[i - 2][currentCol] == RED &&
    gameBoard[i - 3][currentCol] == RED) {

    return RED;
    }

    if (gameBoard[i][currentCol] == YELLOW &&
    gameBoard[i - 1][currentCol] == YELLOW &&
    gameBoard[i - 2][currentCol] == YELLOW &&
    gameBoard[i - 3][currentCol] == YELLOW) {

    return YELLOW;
    }

    }

    //Otherwise we have no winner
    return -1;

    }

    private int checkDiagonals(int currentRow, int currentCol){
    //Check the left-to-right upward diagonal containing the latest move

    int startingRow = currentRow + 3;
    int startingCol = currentCol - 3;

    //get to a starting position that is valid on the board
    while (startingRow > ROWS - 1 || startingCol < 0) {
    startingRow--;
    startingCol++;
    }

    while (startingRow - 3 >= 0 && startingCol + 3 < COLUMNS ) {
    if (gameBoard[startingRow][startingCol] == RED &&
    gameBoard[startingRow - 1][startingCol + 1] == RED &&
    gameBoard[startingRow - 2][startingCol + 2] == RED &&
    gameBoard[startingRow - 3][startingCol + 3] == RED) {

    return RED;
    }

    if (gameBoard[startingRow][startingCol] == YELLOW &&
    gameBoard[startingRow - 1][startingCol + 1] == YELLOW &&
    gameBoard[startingRow - 2][startingCol + 2] == YELLOW &&
    gameBoard[startingRow - 3][startingCol + 3] == YELLOW) {

    return YELLOW;
    }
    startingRow--;
    startingCol++;

    }

    //Check the left to right downward diagonal containing the latest placed game piece

    //Reset the starting row and column variables
    startingRow = currentRow - 3;
    startingCol = currentCol - 3;

    while(startingRow < 0 || startingCol < 0 ){
    startingCol++;
    startingRow++;
    }

    while(startingRow + 3 < ROWS && startingCol + 3 < COLUMNS ){
    if(gameBoard[startingRow][startingCol] == RED &&
    gameBoard[startingRow + 1][startingCol + 1] == RED &&
    gameBoard[startingRow + 2][startingCol + 2] == RED &&
    gameBoard[startingRow + 3][startingCol + 3] == RED){

    return RED;
    }

    if(gameBoard[startingRow][startingCol] == YELLOW &&
    gameBoard[startingRow + 1][startingCol + 1] == YELLOW &&
    gameBoard[startingRow + 2][startingCol + 2] == YELLOW &&
    gameBoard[startingRow + 3][startingCol + 3] == YELLOW){

    return YELLOW;
    }

    startingRow++;
    startingCol++;

    }

    //Otherwise, we have no winner yet
    return -1;

    }

    private boolean isColumnFull(int columnNumber) {
    /*Based on the way pieces are placed in a game of connect four, if the very first row of a column has
    a piece in it, the column must be full.*/
    if (gameBoard[0][columnNumber] == -1) {
    return false;
    } else {
    return true;
    }
    }

    private boolean isBoardFull() {
    //If any value in our board is -1, the board is not full
    for (int i = 0; i < ROWS; i++) {
    for (int j = 0; j < COLUMNS; j++) {
    if (gameBoard[i][j] == -1) {
    return false;
    }
    }
    }
    //Otherwise the board is full
    return true;
    }

    public void printGameBoard() {
    System.out.println("==============================");
    //Display the number for each column
    System.out.println("1 2 3 4 5 6 7");
    for (int i = 0; i < ROWS; i++) {
    for (int j = 0; j < COLUMNS; j++) {
    if (gameBoard[i][j] == RED) {
    System.out.print("R ");
    } else if (gameBoard[i][j] == YELLOW) {
    System.out.print("Y ");
    } else {
    System.out.print("- ");
    }
    }
    System.out.println();
    }
    System.out.println("==============================");
    }

    public void clearBoard() {
    //Reset all board positions to -1
    for (int i = 0; i < ROWS; i++) {
    for (int j = 0; j < COLUMNS; j++) {
    gameBoard[i][j] = -1;
    }
    }
    }
    }


    Player.Java:



    import java.io.Serializable;

    public class Player implements Serializable {

    private final String name;
    private static int counter = 0;
    private int playerNumber;


    public Player(String name) {
    this.name = name;
    this.counter++;
    this.playerNumber = counter;
    }

    public String getName() {
    return name;
    }

    public int getPlayerNumber() {
    return playerNumber;
    }

    }









    share|improve this question









    $endgroup$















      0












      0








      0





      $begingroup$


      so here is an updated version of a basic connect four game I had posted previously. Changes include:




      • an overhauled validator, simplifying the process by knowing where the
        last move was made

      • Utilized an array with elements referncing how full each column is to simplify the logic of making a move and checking for a tie

      • The game is now GUI based utilizing swing to build both the game and main menus, built on top of the previous text based logic and
        functions

      • Added the ability to save, load, and start new games from the GUI menu


      Constructive criticism/suggestions related to OOD/OOP as well as how to improve the game GUI are especially welcome, as that is where I think I need the most improvement currently. My next steps should involve adding the ability for players to play over a network, so any tips or advice to get there from where I'm at would be appreciated too.



      ConnectFour.Java



      import javax.swing.*;
      import java.awt.*;
      import java.awt.event.ActionEvent;
      import java.awt.event.ActionListener;
      import java.io.*;

      public class ConnectFour implements Serializable {
      private int gameBoard;
      private int piecesInColumn; // Each index keeps track of how many game pieces are currently in the corresponding column
      private static final int ROWS = 6;
      private static final int COLUMNS = 7;
      private static final int RED = 1;
      private static final int YELLOW = 2;
      private Player playerOne;
      private Player playerTwo;
      private int totalNumTurns;

      public ConnectFour() {
      this.gameBoard = new int[ROWS][COLUMNS];
      this.piecesInColumn = new int[COLUMNS];
      //Initialize each position in the game board to empty
      for (int i = 0; i < ROWS; i++) {
      for (int j = 0; j < COLUMNS; j++) {
      gameBoard[i][j] = -1;
      }
      }

      this.totalNumTurns = 0;

      }

      public static void main(String args) {
      new ConnectFour().buildMainMenu();

      }

      public void buildMainMenu(){
      // Construct a main menu that welcomes players and takes their names

      JFrame mainFrame = new JFrame();
      mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

      JLabel title = new JLabel("Welcome to Connect Four!");
      Font titleFont = new Font(Font.SERIF, Font.BOLD, 20);
      title.setFont(titleFont);
      JPanel titlePanel = new JPanel();
      titlePanel.add(title);

      JTextField nameOne = new JTextField(10);
      JLabel nameOneLabel = new JLabel("Player one's name:");
      JTextField nameTwo = new JTextField(10);
      JLabel nameTwoLabel = new JLabel("Player two's name");
      JPanel namesPanel = new JPanel();
      namesPanel.setLayout(new BoxLayout(namesPanel, BoxLayout.Y_AXIS));
      namesPanel.add(nameOneLabel);
      namesPanel.add(nameOne);
      namesPanel.add(nameTwoLabel);
      namesPanel.add(nameTwo);

      JButton startGameButton = new JButton("Start Game!");

      startGameButton.addActionListener(new ActionListener(){

      @Override
      public void actionPerformed(ActionEvent e) {
      //Once we press start game, create player objects based on the names, close the window and open a new window with the game GUI
      playerOne = new Player(nameOne.getText());
      playerTwo = new Player(nameTwo.getText());
      System.out.println("Welcome player one: " + playerOne.getName());
      System.out.println("Welcome player two: " + playerTwo.getName());
      mainFrame.dispose();
      buildGameGUI();
      }
      });

      JPanel startGamePanel = new JPanel();
      startGamePanel.add(startGameButton);

      JPanel centerPanel = new JPanel();
      centerPanel.add(namesPanel);

      mainFrame.getContentPane().add(BorderLayout.NORTH,titlePanel);
      mainFrame.getContentPane().add(BorderLayout.SOUTH, startGamePanel);
      mainFrame.getContentPane().add(BorderLayout.CENTER,centerPanel);
      mainFrame.setSize(400,200);
      mainFrame.setVisible(true);

      }

      public void buildGameGUI(){

      JFrame gameFrame = new JFrame();
      gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

      gameFrame.setSize(500,500);
      gameFrame.setVisible(true);

      ConnectFourVisualizer gameVisualizer = new ConnectFourVisualizer();

      gameFrame.add(BorderLayout.CENTER, gameVisualizer);

      JMenuBar menuBar = new JMenuBar();
      JMenu fileMenu = new JMenu("File");
      JMenuItem exit = new JMenuItem("Exit");

      JPanel chooseMovePanel = new JPanel();
      JLabel chooseMoveLabel = new JLabel( playerOne.getName() + ", Choose a column from 1 to 7: ");
      JTextField moveChoiceField = new JTextField(5);
      JButton chooseMoveButton = new JButton("Choose");

      exit.addActionListener(new ActionListener() {
      //Close the window and stop the program if the user clicks exit
      @Override
      public void actionPerformed(ActionEvent e) {
      System.exit(0);
      }
      });

      JMenuItem loadGame = new JMenuItem("Load Game");
      //Add an action listener here for loading the game
      //1.) Restore the state of connect four object from the connect_four.ser file
      //2.) Repaint the game board gui to display the previous state's game board and allow the game to continue

      JMenuItem saveGame = new JMenuItem("Save Game");
      JMenuItem newGame = new JMenuItem("New Game");

      newGame.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
      //Reset the board and redraw the visual representation based on the empty board
      clearBoard();
      gameVisualizer.repaint();
      totalNumTurns = 0;
      piecesInColumn = new int[COLUMNS];
      chooseMoveLabel.setText(playerOne.getName() + ", Choose a column from 1 to 7: ");
      //Re-enable the buttons and text field in case the previous game had a winner
      moveChoiceField.setEnabled(true);
      chooseMoveButton.setEnabled(true);

      }
      });

      saveGame.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
      try{
      FileOutputStream fileOutputStream = new FileOutputStream("connect_four.ser");
      ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
      objectOutputStream.writeObject(ConnectFour.this);
      objectOutputStream.close();
      fileOutputStream.close();
      }catch (IOException ex){
      ex.printStackTrace();
      }
      }
      });

      loadGame.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
      try {

      //Set the current Connect four object references and values equal to the previously saved games values
      ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("connect_four.ser"));
      ConnectFour previousGame = (ConnectFour) objectInputStream.readObject();
      ConnectFour.this.gameBoard = previousGame.gameBoard;
      ConnectFour.this.piecesInColumn = previousGame.piecesInColumn;
      ConnectFour.this.playerOne = previousGame.playerOne;
      ConnectFour.this.playerTwo = previousGame.playerTwo;
      ConnectFour.this.totalNumTurns = previousGame.totalNumTurns;

      System.out.println("The number of turns is: " + totalNumTurns);

      //Determine whose turn it was when the game was saved, and display the appropriate label
      if(totalNumTurns % 2 == 0){
      chooseMoveLabel.setText(playerOne.getName() + ", choose a column from 1 to 7:");
      }

      else{
      chooseMoveLabel.setText(playerTwo.getName() + ", choose a column from 1 to 7");
      }

      }catch(Exception ex){
      ex.printStackTrace();
      }
      //Redraw the game gui no correctly show the loaded game state
      gameVisualizer.repaint();
      printGameBoard();
      }
      });

      //Add the menu items to the menua bar
      fileMenu.add(newGame);
      fileMenu.add(saveGame);
      fileMenu.add(loadGame);
      fileMenu.add(exit);
      menuBar.add(fileMenu);

      gameFrame.getContentPane().add(BorderLayout.NORTH,menuBar);


      chooseMovePanel.add(chooseMoveLabel);
      chooseMovePanel.add(moveChoiceField);
      chooseMovePanel.add(chooseMoveButton);

      gameFrame.getContentPane().add(BorderLayout.SOUTH, chooseMovePanel);


      chooseMoveButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {

      //Notice here we're displaying whose turn in is after the current player makes their move
      int move = Integer.parseInt(moveChoiceField.getText());
      if(totalNumTurns % 2 == 0){
      //It's player one's turn, so make their move and after change the text to ask for player two
      boolean attempt = makeMove(playerOne, move);
      if(attempt == false){
      chooseMoveLabel.setText("That was an invalid move, please try again " + playerOne.getName()+ ":");
      moveChoiceField.setText("");
      return;
      }
      chooseMoveLabel.setText(playerTwo.getName() + ", choose a column from 1 to 7:");
      moveChoiceField.setText("");
      }

      else{
      //Otherwise it's player two's turn, so make their move and change the text to ask for player one
      boolean attempt = makeMove(playerTwo, move);
      if(attempt == false){
      chooseMoveLabel.setText("That was an invalid move, please try again " + playerTwo.getName() + ":");
      moveChoiceField.setText("");
      return;
      }
      chooseMoveLabel.setText(playerOne.getName() + ", choose a column from 1 to 7:");
      moveChoiceField.setText("");
      }
      printGameBoard();
      totalNumTurns++;
      gameVisualizer.repaint();
      int hasWinner = checkForWinner(move);
      if(hasWinner != -1){
      moveChoiceField.setEnabled(false);
      chooseMoveButton.setEnabled(false);
      saveGame.setEnabled(false);
      if(hasWinner == RED){
      chooseMoveLabel.setText(playerOne.getName() + " wins!");

      }
      else if(hasWinner == YELLOW){
      chooseMoveLabel.setText(playerTwo.getName() + " wins!");
      }
      }
      }
      });
      }

      public class ConnectFourVisualizer extends JPanel{
      private int xBackground;
      private int yBackground;
      private int widthBackground;
      private int heightBackGround;
      private int xGameSlot;
      private int yGameSlot;
      private int widthGameSlot;
      private int heightGameSlot;

      public ConnectFourVisualizer(){
      this.widthGameSlot = 20;
      this.heightGameSlot = 20;

      this.heightBackGround = 300;
      this.widthBackground = 350;

      this.xBackground = 75;
      this.yBackground = 100;
      }

      public void paintComponent(Graphics g){
      g.setColor(Color.YELLOW);
      g.fillRect(xBackground, yBackground, widthBackground, heightBackGround);
      int currentX = xBackground + 40;
      int currentY = yBackground + 40;

      for(int i = 0; i < 6; i++) {


      for (int j = 0; j < 7; j++) {
      if(gameBoard[i][j] == RED){
      g.setColor(Color.RED);
      }
      else if(gameBoard[i][j] == YELLOW){
      g.setColor(Color.BLACK);
      }
      else{
      g.setColor(Color.WHITE);
      }

      g.fillOval(currentX, currentY, widthGameSlot, heightGameSlot);
      currentX += 40;

      }
      currentX = xBackground + 40;
      currentY += 40;

      }
      }
      }


      public boolean makeMove(Player player, int column) {
      /* Since row position is determined by how many pieces are currently in a given column,
      we only need to choose a column position and the row position will be determined as a result. */

      //Decrement the column value by 1, as our array is zero indexed.
      column--;

      //Check if the column chosen is valid
      if (column < 0 || column >= COLUMNS) {
      System.out.println("Column choice must be between 1 and 7 !");
      return false;
      }

      //Check if the column chosen is already full
      if (isColumnFull(column)) {
      System.out.println("That column is already full!");
      return false;
      }
      /*Otherwise, start from the bottom of the column and change the value in
      the first open row to the player's number*/
      else {
      // for (int i = ROWS - 1; i >= 0; i--) {
      // if (gameBoard[i][column] == -1) {
      // gameBoard[i][column] = player.getPlayerNumber();
      // break;
      // }
      // }
      // return true;
      int nextOpenRow = ROWS - 1 - piecesInColumn[column];
      gameBoard[nextOpenRow][column] = player.getPlayerNumber();
      piecesInColumn[column]++;
      return true;
      }

      }


      public int checkForWinner(int latestMove){

      //If the gameboard is full, the game is a TIE
      if(isBoardFull()){
      // 0 indicates a TIE
      return 0;
      }

      int currentCol = latestMove - 1; //Remember, the user sees the columns numbered 1 -> 7 but our array is 0 indexed
      int currentRow = ROWS - piecesInColumn[currentCol]; // Determine which row the last piece was placed in

      int rows = checkRows(currentRow);
      int columns = checkColumns(currentCol);
      int diagonals = checkDiagonals(currentRow,currentCol);


      if(rows == RED || columns == RED || diagonals == RED){
      return RED;
      }

      if(rows == YELLOW || columns == YELLOW || diagonals == YELLOW){
      return YELLOW;
      }

      //Otherwise we don't have a winner yer

      return -1;
      }

      private int checkRows(int currentRow){
      //Obtain the row and column of the latest move

      for (int i = 0; i < COLUMNS - 3; i++) {

      if (gameBoard[currentRow][i] == RED &&
      gameBoard[currentRow][i + 1] == RED &&
      gameBoard[currentRow][i + 2] == RED &&
      gameBoard[currentRow][i + 3] == RED) {

      return RED;
      }

      if (gameBoard[currentRow][i] == YELLOW &&
      gameBoard[currentRow][i + 1] == YELLOW &&
      gameBoard[currentRow][i + 2] == YELLOW &&
      gameBoard[currentRow][i + 3] == YELLOW) {

      return YELLOW;
      }
      }
      //Otherwise, we have no winner yet
      return -1;
      }

      private int checkColumns( int currentCol){
      //Check the column

      // if(piecesInColumn[currentCol] < 4){
      // //If there are less than 4 game pieces in the column, there cannot be a winner here by column
      // return -1;
      // }

      for (int i = ROWS - 1; i >= ROWS - 3; i--) {
      if (gameBoard[i][currentCol] == RED &&
      gameBoard[i - 1][currentCol] == RED &&
      gameBoard[i - 2][currentCol] == RED &&
      gameBoard[i - 3][currentCol] == RED) {

      return RED;
      }

      if (gameBoard[i][currentCol] == YELLOW &&
      gameBoard[i - 1][currentCol] == YELLOW &&
      gameBoard[i - 2][currentCol] == YELLOW &&
      gameBoard[i - 3][currentCol] == YELLOW) {

      return YELLOW;
      }

      }

      //Otherwise we have no winner
      return -1;

      }

      private int checkDiagonals(int currentRow, int currentCol){
      //Check the left-to-right upward diagonal containing the latest move

      int startingRow = currentRow + 3;
      int startingCol = currentCol - 3;

      //get to a starting position that is valid on the board
      while (startingRow > ROWS - 1 || startingCol < 0) {
      startingRow--;
      startingCol++;
      }

      while (startingRow - 3 >= 0 && startingCol + 3 < COLUMNS ) {
      if (gameBoard[startingRow][startingCol] == RED &&
      gameBoard[startingRow - 1][startingCol + 1] == RED &&
      gameBoard[startingRow - 2][startingCol + 2] == RED &&
      gameBoard[startingRow - 3][startingCol + 3] == RED) {

      return RED;
      }

      if (gameBoard[startingRow][startingCol] == YELLOW &&
      gameBoard[startingRow - 1][startingCol + 1] == YELLOW &&
      gameBoard[startingRow - 2][startingCol + 2] == YELLOW &&
      gameBoard[startingRow - 3][startingCol + 3] == YELLOW) {

      return YELLOW;
      }
      startingRow--;
      startingCol++;

      }

      //Check the left to right downward diagonal containing the latest placed game piece

      //Reset the starting row and column variables
      startingRow = currentRow - 3;
      startingCol = currentCol - 3;

      while(startingRow < 0 || startingCol < 0 ){
      startingCol++;
      startingRow++;
      }

      while(startingRow + 3 < ROWS && startingCol + 3 < COLUMNS ){
      if(gameBoard[startingRow][startingCol] == RED &&
      gameBoard[startingRow + 1][startingCol + 1] == RED &&
      gameBoard[startingRow + 2][startingCol + 2] == RED &&
      gameBoard[startingRow + 3][startingCol + 3] == RED){

      return RED;
      }

      if(gameBoard[startingRow][startingCol] == YELLOW &&
      gameBoard[startingRow + 1][startingCol + 1] == YELLOW &&
      gameBoard[startingRow + 2][startingCol + 2] == YELLOW &&
      gameBoard[startingRow + 3][startingCol + 3] == YELLOW){

      return YELLOW;
      }

      startingRow++;
      startingCol++;

      }

      //Otherwise, we have no winner yet
      return -1;

      }

      private boolean isColumnFull(int columnNumber) {
      /*Based on the way pieces are placed in a game of connect four, if the very first row of a column has
      a piece in it, the column must be full.*/
      if (gameBoard[0][columnNumber] == -1) {
      return false;
      } else {
      return true;
      }
      }

      private boolean isBoardFull() {
      //If any value in our board is -1, the board is not full
      for (int i = 0; i < ROWS; i++) {
      for (int j = 0; j < COLUMNS; j++) {
      if (gameBoard[i][j] == -1) {
      return false;
      }
      }
      }
      //Otherwise the board is full
      return true;
      }

      public void printGameBoard() {
      System.out.println("==============================");
      //Display the number for each column
      System.out.println("1 2 3 4 5 6 7");
      for (int i = 0; i < ROWS; i++) {
      for (int j = 0; j < COLUMNS; j++) {
      if (gameBoard[i][j] == RED) {
      System.out.print("R ");
      } else if (gameBoard[i][j] == YELLOW) {
      System.out.print("Y ");
      } else {
      System.out.print("- ");
      }
      }
      System.out.println();
      }
      System.out.println("==============================");
      }

      public void clearBoard() {
      //Reset all board positions to -1
      for (int i = 0; i < ROWS; i++) {
      for (int j = 0; j < COLUMNS; j++) {
      gameBoard[i][j] = -1;
      }
      }
      }
      }


      Player.Java:



      import java.io.Serializable;

      public class Player implements Serializable {

      private final String name;
      private static int counter = 0;
      private int playerNumber;


      public Player(String name) {
      this.name = name;
      this.counter++;
      this.playerNumber = counter;
      }

      public String getName() {
      return name;
      }

      public int getPlayerNumber() {
      return playerNumber;
      }

      }









      share|improve this question









      $endgroup$




      so here is an updated version of a basic connect four game I had posted previously. Changes include:




      • an overhauled validator, simplifying the process by knowing where the
        last move was made

      • Utilized an array with elements referncing how full each column is to simplify the logic of making a move and checking for a tie

      • The game is now GUI based utilizing swing to build both the game and main menus, built on top of the previous text based logic and
        functions

      • Added the ability to save, load, and start new games from the GUI menu


      Constructive criticism/suggestions related to OOD/OOP as well as how to improve the game GUI are especially welcome, as that is where I think I need the most improvement currently. My next steps should involve adding the ability for players to play over a network, so any tips or advice to get there from where I'm at would be appreciated too.



      ConnectFour.Java



      import javax.swing.*;
      import java.awt.*;
      import java.awt.event.ActionEvent;
      import java.awt.event.ActionListener;
      import java.io.*;

      public class ConnectFour implements Serializable {
      private int gameBoard;
      private int piecesInColumn; // Each index keeps track of how many game pieces are currently in the corresponding column
      private static final int ROWS = 6;
      private static final int COLUMNS = 7;
      private static final int RED = 1;
      private static final int YELLOW = 2;
      private Player playerOne;
      private Player playerTwo;
      private int totalNumTurns;

      public ConnectFour() {
      this.gameBoard = new int[ROWS][COLUMNS];
      this.piecesInColumn = new int[COLUMNS];
      //Initialize each position in the game board to empty
      for (int i = 0; i < ROWS; i++) {
      for (int j = 0; j < COLUMNS; j++) {
      gameBoard[i][j] = -1;
      }
      }

      this.totalNumTurns = 0;

      }

      public static void main(String args) {
      new ConnectFour().buildMainMenu();

      }

      public void buildMainMenu(){
      // Construct a main menu that welcomes players and takes their names

      JFrame mainFrame = new JFrame();
      mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

      JLabel title = new JLabel("Welcome to Connect Four!");
      Font titleFont = new Font(Font.SERIF, Font.BOLD, 20);
      title.setFont(titleFont);
      JPanel titlePanel = new JPanel();
      titlePanel.add(title);

      JTextField nameOne = new JTextField(10);
      JLabel nameOneLabel = new JLabel("Player one's name:");
      JTextField nameTwo = new JTextField(10);
      JLabel nameTwoLabel = new JLabel("Player two's name");
      JPanel namesPanel = new JPanel();
      namesPanel.setLayout(new BoxLayout(namesPanel, BoxLayout.Y_AXIS));
      namesPanel.add(nameOneLabel);
      namesPanel.add(nameOne);
      namesPanel.add(nameTwoLabel);
      namesPanel.add(nameTwo);

      JButton startGameButton = new JButton("Start Game!");

      startGameButton.addActionListener(new ActionListener(){

      @Override
      public void actionPerformed(ActionEvent e) {
      //Once we press start game, create player objects based on the names, close the window and open a new window with the game GUI
      playerOne = new Player(nameOne.getText());
      playerTwo = new Player(nameTwo.getText());
      System.out.println("Welcome player one: " + playerOne.getName());
      System.out.println("Welcome player two: " + playerTwo.getName());
      mainFrame.dispose();
      buildGameGUI();
      }
      });

      JPanel startGamePanel = new JPanel();
      startGamePanel.add(startGameButton);

      JPanel centerPanel = new JPanel();
      centerPanel.add(namesPanel);

      mainFrame.getContentPane().add(BorderLayout.NORTH,titlePanel);
      mainFrame.getContentPane().add(BorderLayout.SOUTH, startGamePanel);
      mainFrame.getContentPane().add(BorderLayout.CENTER,centerPanel);
      mainFrame.setSize(400,200);
      mainFrame.setVisible(true);

      }

      public void buildGameGUI(){

      JFrame gameFrame = new JFrame();
      gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

      gameFrame.setSize(500,500);
      gameFrame.setVisible(true);

      ConnectFourVisualizer gameVisualizer = new ConnectFourVisualizer();

      gameFrame.add(BorderLayout.CENTER, gameVisualizer);

      JMenuBar menuBar = new JMenuBar();
      JMenu fileMenu = new JMenu("File");
      JMenuItem exit = new JMenuItem("Exit");

      JPanel chooseMovePanel = new JPanel();
      JLabel chooseMoveLabel = new JLabel( playerOne.getName() + ", Choose a column from 1 to 7: ");
      JTextField moveChoiceField = new JTextField(5);
      JButton chooseMoveButton = new JButton("Choose");

      exit.addActionListener(new ActionListener() {
      //Close the window and stop the program if the user clicks exit
      @Override
      public void actionPerformed(ActionEvent e) {
      System.exit(0);
      }
      });

      JMenuItem loadGame = new JMenuItem("Load Game");
      //Add an action listener here for loading the game
      //1.) Restore the state of connect four object from the connect_four.ser file
      //2.) Repaint the game board gui to display the previous state's game board and allow the game to continue

      JMenuItem saveGame = new JMenuItem("Save Game");
      JMenuItem newGame = new JMenuItem("New Game");

      newGame.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
      //Reset the board and redraw the visual representation based on the empty board
      clearBoard();
      gameVisualizer.repaint();
      totalNumTurns = 0;
      piecesInColumn = new int[COLUMNS];
      chooseMoveLabel.setText(playerOne.getName() + ", Choose a column from 1 to 7: ");
      //Re-enable the buttons and text field in case the previous game had a winner
      moveChoiceField.setEnabled(true);
      chooseMoveButton.setEnabled(true);

      }
      });

      saveGame.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
      try{
      FileOutputStream fileOutputStream = new FileOutputStream("connect_four.ser");
      ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
      objectOutputStream.writeObject(ConnectFour.this);
      objectOutputStream.close();
      fileOutputStream.close();
      }catch (IOException ex){
      ex.printStackTrace();
      }
      }
      });

      loadGame.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
      try {

      //Set the current Connect four object references and values equal to the previously saved games values
      ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("connect_four.ser"));
      ConnectFour previousGame = (ConnectFour) objectInputStream.readObject();
      ConnectFour.this.gameBoard = previousGame.gameBoard;
      ConnectFour.this.piecesInColumn = previousGame.piecesInColumn;
      ConnectFour.this.playerOne = previousGame.playerOne;
      ConnectFour.this.playerTwo = previousGame.playerTwo;
      ConnectFour.this.totalNumTurns = previousGame.totalNumTurns;

      System.out.println("The number of turns is: " + totalNumTurns);

      //Determine whose turn it was when the game was saved, and display the appropriate label
      if(totalNumTurns % 2 == 0){
      chooseMoveLabel.setText(playerOne.getName() + ", choose a column from 1 to 7:");
      }

      else{
      chooseMoveLabel.setText(playerTwo.getName() + ", choose a column from 1 to 7");
      }

      }catch(Exception ex){
      ex.printStackTrace();
      }
      //Redraw the game gui no correctly show the loaded game state
      gameVisualizer.repaint();
      printGameBoard();
      }
      });

      //Add the menu items to the menua bar
      fileMenu.add(newGame);
      fileMenu.add(saveGame);
      fileMenu.add(loadGame);
      fileMenu.add(exit);
      menuBar.add(fileMenu);

      gameFrame.getContentPane().add(BorderLayout.NORTH,menuBar);


      chooseMovePanel.add(chooseMoveLabel);
      chooseMovePanel.add(moveChoiceField);
      chooseMovePanel.add(chooseMoveButton);

      gameFrame.getContentPane().add(BorderLayout.SOUTH, chooseMovePanel);


      chooseMoveButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {

      //Notice here we're displaying whose turn in is after the current player makes their move
      int move = Integer.parseInt(moveChoiceField.getText());
      if(totalNumTurns % 2 == 0){
      //It's player one's turn, so make their move and after change the text to ask for player two
      boolean attempt = makeMove(playerOne, move);
      if(attempt == false){
      chooseMoveLabel.setText("That was an invalid move, please try again " + playerOne.getName()+ ":");
      moveChoiceField.setText("");
      return;
      }
      chooseMoveLabel.setText(playerTwo.getName() + ", choose a column from 1 to 7:");
      moveChoiceField.setText("");
      }

      else{
      //Otherwise it's player two's turn, so make their move and change the text to ask for player one
      boolean attempt = makeMove(playerTwo, move);
      if(attempt == false){
      chooseMoveLabel.setText("That was an invalid move, please try again " + playerTwo.getName() + ":");
      moveChoiceField.setText("");
      return;
      }
      chooseMoveLabel.setText(playerOne.getName() + ", choose a column from 1 to 7:");
      moveChoiceField.setText("");
      }
      printGameBoard();
      totalNumTurns++;
      gameVisualizer.repaint();
      int hasWinner = checkForWinner(move);
      if(hasWinner != -1){
      moveChoiceField.setEnabled(false);
      chooseMoveButton.setEnabled(false);
      saveGame.setEnabled(false);
      if(hasWinner == RED){
      chooseMoveLabel.setText(playerOne.getName() + " wins!");

      }
      else if(hasWinner == YELLOW){
      chooseMoveLabel.setText(playerTwo.getName() + " wins!");
      }
      }
      }
      });
      }

      public class ConnectFourVisualizer extends JPanel{
      private int xBackground;
      private int yBackground;
      private int widthBackground;
      private int heightBackGround;
      private int xGameSlot;
      private int yGameSlot;
      private int widthGameSlot;
      private int heightGameSlot;

      public ConnectFourVisualizer(){
      this.widthGameSlot = 20;
      this.heightGameSlot = 20;

      this.heightBackGround = 300;
      this.widthBackground = 350;

      this.xBackground = 75;
      this.yBackground = 100;
      }

      public void paintComponent(Graphics g){
      g.setColor(Color.YELLOW);
      g.fillRect(xBackground, yBackground, widthBackground, heightBackGround);
      int currentX = xBackground + 40;
      int currentY = yBackground + 40;

      for(int i = 0; i < 6; i++) {


      for (int j = 0; j < 7; j++) {
      if(gameBoard[i][j] == RED){
      g.setColor(Color.RED);
      }
      else if(gameBoard[i][j] == YELLOW){
      g.setColor(Color.BLACK);
      }
      else{
      g.setColor(Color.WHITE);
      }

      g.fillOval(currentX, currentY, widthGameSlot, heightGameSlot);
      currentX += 40;

      }
      currentX = xBackground + 40;
      currentY += 40;

      }
      }
      }


      public boolean makeMove(Player player, int column) {
      /* Since row position is determined by how many pieces are currently in a given column,
      we only need to choose a column position and the row position will be determined as a result. */

      //Decrement the column value by 1, as our array is zero indexed.
      column--;

      //Check if the column chosen is valid
      if (column < 0 || column >= COLUMNS) {
      System.out.println("Column choice must be between 1 and 7 !");
      return false;
      }

      //Check if the column chosen is already full
      if (isColumnFull(column)) {
      System.out.println("That column is already full!");
      return false;
      }
      /*Otherwise, start from the bottom of the column and change the value in
      the first open row to the player's number*/
      else {
      // for (int i = ROWS - 1; i >= 0; i--) {
      // if (gameBoard[i][column] == -1) {
      // gameBoard[i][column] = player.getPlayerNumber();
      // break;
      // }
      // }
      // return true;
      int nextOpenRow = ROWS - 1 - piecesInColumn[column];
      gameBoard[nextOpenRow][column] = player.getPlayerNumber();
      piecesInColumn[column]++;
      return true;
      }

      }


      public int checkForWinner(int latestMove){

      //If the gameboard is full, the game is a TIE
      if(isBoardFull()){
      // 0 indicates a TIE
      return 0;
      }

      int currentCol = latestMove - 1; //Remember, the user sees the columns numbered 1 -> 7 but our array is 0 indexed
      int currentRow = ROWS - piecesInColumn[currentCol]; // Determine which row the last piece was placed in

      int rows = checkRows(currentRow);
      int columns = checkColumns(currentCol);
      int diagonals = checkDiagonals(currentRow,currentCol);


      if(rows == RED || columns == RED || diagonals == RED){
      return RED;
      }

      if(rows == YELLOW || columns == YELLOW || diagonals == YELLOW){
      return YELLOW;
      }

      //Otherwise we don't have a winner yer

      return -1;
      }

      private int checkRows(int currentRow){
      //Obtain the row and column of the latest move

      for (int i = 0; i < COLUMNS - 3; i++) {

      if (gameBoard[currentRow][i] == RED &&
      gameBoard[currentRow][i + 1] == RED &&
      gameBoard[currentRow][i + 2] == RED &&
      gameBoard[currentRow][i + 3] == RED) {

      return RED;
      }

      if (gameBoard[currentRow][i] == YELLOW &&
      gameBoard[currentRow][i + 1] == YELLOW &&
      gameBoard[currentRow][i + 2] == YELLOW &&
      gameBoard[currentRow][i + 3] == YELLOW) {

      return YELLOW;
      }
      }
      //Otherwise, we have no winner yet
      return -1;
      }

      private int checkColumns( int currentCol){
      //Check the column

      // if(piecesInColumn[currentCol] < 4){
      // //If there are less than 4 game pieces in the column, there cannot be a winner here by column
      // return -1;
      // }

      for (int i = ROWS - 1; i >= ROWS - 3; i--) {
      if (gameBoard[i][currentCol] == RED &&
      gameBoard[i - 1][currentCol] == RED &&
      gameBoard[i - 2][currentCol] == RED &&
      gameBoard[i - 3][currentCol] == RED) {

      return RED;
      }

      if (gameBoard[i][currentCol] == YELLOW &&
      gameBoard[i - 1][currentCol] == YELLOW &&
      gameBoard[i - 2][currentCol] == YELLOW &&
      gameBoard[i - 3][currentCol] == YELLOW) {

      return YELLOW;
      }

      }

      //Otherwise we have no winner
      return -1;

      }

      private int checkDiagonals(int currentRow, int currentCol){
      //Check the left-to-right upward diagonal containing the latest move

      int startingRow = currentRow + 3;
      int startingCol = currentCol - 3;

      //get to a starting position that is valid on the board
      while (startingRow > ROWS - 1 || startingCol < 0) {
      startingRow--;
      startingCol++;
      }

      while (startingRow - 3 >= 0 && startingCol + 3 < COLUMNS ) {
      if (gameBoard[startingRow][startingCol] == RED &&
      gameBoard[startingRow - 1][startingCol + 1] == RED &&
      gameBoard[startingRow - 2][startingCol + 2] == RED &&
      gameBoard[startingRow - 3][startingCol + 3] == RED) {

      return RED;
      }

      if (gameBoard[startingRow][startingCol] == YELLOW &&
      gameBoard[startingRow - 1][startingCol + 1] == YELLOW &&
      gameBoard[startingRow - 2][startingCol + 2] == YELLOW &&
      gameBoard[startingRow - 3][startingCol + 3] == YELLOW) {

      return YELLOW;
      }
      startingRow--;
      startingCol++;

      }

      //Check the left to right downward diagonal containing the latest placed game piece

      //Reset the starting row and column variables
      startingRow = currentRow - 3;
      startingCol = currentCol - 3;

      while(startingRow < 0 || startingCol < 0 ){
      startingCol++;
      startingRow++;
      }

      while(startingRow + 3 < ROWS && startingCol + 3 < COLUMNS ){
      if(gameBoard[startingRow][startingCol] == RED &&
      gameBoard[startingRow + 1][startingCol + 1] == RED &&
      gameBoard[startingRow + 2][startingCol + 2] == RED &&
      gameBoard[startingRow + 3][startingCol + 3] == RED){

      return RED;
      }

      if(gameBoard[startingRow][startingCol] == YELLOW &&
      gameBoard[startingRow + 1][startingCol + 1] == YELLOW &&
      gameBoard[startingRow + 2][startingCol + 2] == YELLOW &&
      gameBoard[startingRow + 3][startingCol + 3] == YELLOW){

      return YELLOW;
      }

      startingRow++;
      startingCol++;

      }

      //Otherwise, we have no winner yet
      return -1;

      }

      private boolean isColumnFull(int columnNumber) {
      /*Based on the way pieces are placed in a game of connect four, if the very first row of a column has
      a piece in it, the column must be full.*/
      if (gameBoard[0][columnNumber] == -1) {
      return false;
      } else {
      return true;
      }
      }

      private boolean isBoardFull() {
      //If any value in our board is -1, the board is not full
      for (int i = 0; i < ROWS; i++) {
      for (int j = 0; j < COLUMNS; j++) {
      if (gameBoard[i][j] == -1) {
      return false;
      }
      }
      }
      //Otherwise the board is full
      return true;
      }

      public void printGameBoard() {
      System.out.println("==============================");
      //Display the number for each column
      System.out.println("1 2 3 4 5 6 7");
      for (int i = 0; i < ROWS; i++) {
      for (int j = 0; j < COLUMNS; j++) {
      if (gameBoard[i][j] == RED) {
      System.out.print("R ");
      } else if (gameBoard[i][j] == YELLOW) {
      System.out.print("Y ");
      } else {
      System.out.print("- ");
      }
      }
      System.out.println();
      }
      System.out.println("==============================");
      }

      public void clearBoard() {
      //Reset all board positions to -1
      for (int i = 0; i < ROWS; i++) {
      for (int j = 0; j < COLUMNS; j++) {
      gameBoard[i][j] = -1;
      }
      }
      }
      }


      Player.Java:



      import java.io.Serializable;

      public class Player implements Serializable {

      private final String name;
      private static int counter = 0;
      private int playerNumber;


      public Player(String name) {
      this.name = name;
      this.counter++;
      this.playerNumber = counter;
      }

      public String getName() {
      return name;
      }

      public int getPlayerNumber() {
      return playerNumber;
      }

      }






      java object-oriented swing serialization connect-four






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked 1 hour ago









      dgr27dgr27

      364




      364






















          0






          active

          oldest

          votes











          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f215062%2fbasic-connect-four-game-2%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          0






          active

          oldest

          votes








          0






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes
















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f215062%2fbasic-connect-four-game-2%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          How to make a Squid Proxy server?

          第一次世界大戦

          Touch on Surface Book