package extracredit02;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/**
* A computer game version of 'Connect 4'.
*
* Undocumented code - beware! This code is not the best example of
* programming I have done, I am rushing too much.
*
* @author
*/
public class Connect4 extends JPanel implements ActionListener, MouseListener, MouseMotionListener
{
Connect4AI[] players = new Connect4AI[] {null, new NaiveAI(), new StubbornAI(), new SmartAI()};
String[] playerNames = new String[] {"Human", players[1].getName(), players[2].getName(), players[3].getName()};
int[] playerAI = new int[2]; // Red player is player 0
int[] playerColor = new int[] {Connect4Board.RED, Connect4Board.BLACK};
String[] colorName = new String[] {"red", "", "black"};
JLabel message = new JLabel();
boolean gameInProgress = false;
Connect4Board board = new Board();
JMenuItem menuItem;
int proposedColumn = -1;
int proposedRow = -1;
int playerTurn = 0;
JFrame frame;
int[][] drawState = new int[8][8];
/**
* The application entry point.
*
* @param args Unused.
*/
static public void main (String[] args)
{
Connect4 game = new Connect4();
game.frame = new JFrame ("CP SC 2010 - Connect 4");
game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
game.frame.setBounds(100, 100, 800, 850);
Container contents = game.frame.getContentPane();
contents.setLayout(new BorderLayout());
Container main = new JPanel();
main.setLayout(new BorderLayout());
game.message = new JLabel ("Welcome. Please use the menu to start the game.");
game.message.setFont(new Font("Arial", Font.BOLD, 20));
main.add(game.message, BorderLayout.SOUTH);
main.add(game, BorderLayout.CENTER);
JMenuBar menuBar = new JMenuBar();
JMenu gameMenu = new JMenu("Game");
game.menuItem = new JMenuItem("Start game");
gameMenu.add(game.menuItem);
game.menuItem.addActionListener(game);
game.addMouseListener(game);
game.addMouseMotionListener(game);
menuBar.add(gameMenu);
contents.add(main, BorderLayout.CENTER);
game.frame.setJMenuBar(menuBar);
game.frame.setVisible(true);
}
synchronized public void actionPerformed (ActionEvent e)
{
if (gameInProgress)
{
gameInProgress = false;
menuItem.setText("Start game");
message.setText("Game aborted. Please use the menu to start the game.");
message.repaint();
}
else
{
message.setText ("Select players.");
message.repaint();
try
{
promptForPlayers();
}
catch (Exception ex)
{
message.setText("Please use the menu to start the game.");
message.repaint();
return;
}
gameInProgress = true;
board.clear();
drawState = new int[8][8];
menuItem.setText("Stop game");
playerTurn = 1;
advancePlayer();
}
}
synchronized private void advancePlayer()
{
for (int row = 0; row < 8; row++)
for (int column = 0; column < 8; column++)
drawState[row][column] = board.getSpaceContents(row, column);
proposedColumn = -1;
proposedRow = -1;
if (board.getWinner() != 0)
{
gameInProgress = false;
menuItem.setText("Start game");
message.setText("The game is over. Please use the menu to start the game.");
repaint();
message.repaint();
JOptionPane.showMessageDialog(frame, "The " + colorName[playerColor[playerTurn]+1] + " player wins!\nCongratulations " + playerNames[playerAI[playerTurn]]);
return;
}
if (board.isFull())
{
gameInProgress = false;
menuItem.setText("Start game");
message.setText("The game is over. Please use the menu to start the game.");
repaint();
message.repaint();
JOptionPane.showMessageDialog(frame, "It's a tie.");
return;
}
playerTurn = (playerTurn + 1) % 2;
if (players[playerAI[playerTurn]] != null)
{
message.setText("It is " + playerNames[playerAI[playerTurn]] + " (" + colorName[playerColor[playerTurn]+1] + "s) turn, please wait.");
new Thread(new AITurn()).start();
}
else
message.setText("It is your turn, " + colorName[playerColor[playerTurn]+1] + " player. Click the mouse to drop the piece.");
repaint();
message.repaint();
}
class AITurn implements Runnable
{
public void run ()
{
if (gameInProgress == false)
return;
synchronized (this)
{
long time = System.currentTimeMillis();
int column = players[playerAI[playerTurn]].makeMove(board, playerColor[playerTurn]);
if (playerColor[playerTurn] == Connect4Board.RED)
board.addRedChecker(column);
else
board.addBlackChecker(column);
if (System.currentTimeMillis() - time < 1000)
{ try { Thread.sleep(1000); } catch (Exception e) {}}
repaint();
advancePlayer();
}
}
}
public void promptForPlayers ()
{
playerAI[0] = 0;
playerAI[1] = 0;
String s = (String) JOptionPane.showInputDialog (frame, "Who should play the red pieces?",
"Select a player",
JOptionPane.PLAIN_MESSAGE, null,
playerNames, "Human");
for (int i = 0; i < playerNames.length; i++)
if (s.equals(playerNames[i]))
{
playerAI[0] = i;
}
s = (String) JOptionPane.showInputDialog (frame, "Who should play the black pieces?",
"Select a player",
JOptionPane.PLAIN_MESSAGE, null,
playerNames, "Human");
for (int i = 0; i < playerNames.length; i++)
if (s.equals(playerNames[i]))
{
playerAI[1] = i;
}
}
public void paint (Graphics g)
{
int width = this.getSize().width;
int height = this.getSize().height;
g.setColor(new Color(0.6f, 0.7f, 1.0f));
g.fillRect(0, 0, width, height);
g.setColor(Color.DARK_GRAY);
g.fillRect(50, 20, 704, 704);
for (int row = 0; row < 8; row++)
for (int column = 0; column < 8; column++)
{
int space = drawState[row][column];
if (space == Connect4Board.RED)
g.setColor(Color.RED);
else if (space == Connect4Board.BLACK)
g.setColor(Color.BLACK);
else
g.setColor(Color.WHITE);
g.fillOval (59 + 88*column, 645 - 88*row, 70, 70);
}
if (proposedColumn >= 0 && proposedRow >= 0)
{
g.setColor(new Color(0.7f, 1.0f, 0.7f));
g.fillOval (59 + 88*proposedColumn, 645 - 88*proposedRow, 70, 70);
}
}
public void mouseMoved (MouseEvent e)
{
if (!gameInProgress || players[playerAI[playerTurn]] != null)
return;
int x = e.getX();
int nextColumn = (x - 50) / 88;
int nextRow = 8;
while (nextColumn >= 0 && nextColumn <= 7 && nextRow > 0 && board.getSpaceContents(nextRow-1, nextColumn) == Connect4Board.NONE)
nextRow--;
if (x < 50 || nextColumn < 0 || nextColumn > 7 || nextRow < 0 || nextRow > 7)
{
nextColumn = -1;
nextRow = -1;
}
if (nextColumn != proposedColumn || nextRow != proposedRow)
{
proposedRow = nextRow;
proposedColumn = nextColumn;
repaint();
}
}
public void mouseDragged (MouseEvent e)
{
mouseMoved(e);
}
public void mouseClicked (MouseEvent e)
{
}
public void mousePressed (MouseEvent e)
{
}
public void mouseReleased (MouseEvent e)
{
if (players[playerAI[playerTurn]] != null)
return;
if (proposedRow >= 0 && proposedColumn >= 0)
{
if (playerColor[playerTurn] == Connect4Board.BLACK)
board.addBlackChecker(proposedColumn);
else
board.addRedChecker(proposedColumn);
advancePlayer();
}
}
public void mouseEntered (MouseEvent e)
{
}
public void mouseExited (MouseEvent e)
{
}
}