Project: Connect Four Problem Description: The applet in the figure below enable
ID: 3547959 • Letter: P
Question
Project: Connect Four
Problem Description:
The applet in the figure below enables two players to play the connect-four game. The applet enables two players to place red and yellow discs in turn. To place a disk, the player needs to click on an available cell. An available cell is unoccupied and whose downward neighbor is occupied. The applet flashes the four winning cells if a player wins and reports no winners if all cells are occupied with no winners.
Your task is to modify the given program to enable a user to play with the computer. Things need to do with projects:
(1) Comprehend the given program. The source code for the program is given below named Exercise18_34.
(2) Modify it to enable a user to play with the computer. Let the computer play as intelligently as you can. The bottom line is to make a legal play.
(3) Let the user start first.
(4) Name your PConnectFour.
Here is the source code for Exercise18_34:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Exercise18_34 extends JApplet {
private Cell[][] cells = new Cell[6][7];
private char nextDisc = 'R';
private Timer timer = new Timer(100, new FlashingCells());
private int[][] result;
private JButton jbtStartOver = new JButton("Start Over");
class FlashingCells implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (cells[result[0][0]][result[0][1]].token == ' ') {
cells[result[0][0]][result[0][1]].token = nextDisc;
cells[result[1][0]][result[1][1]].token = nextDisc;
cells[result[2][0]][result[2][1]].token = nextDisc;
cells[result[3][0]][result[3][1]].token = nextDisc;
}
else {
cells[result[0][0]][result[0][1]].token = ' ';
cells[result[1][0]][result[1][1]].token = ' ';
cells[result[2][0]][result[2][1]].token = ' ';
cells[result[3][0]][result[3][1]].token = ' ';
}
repaint();
}
}
public Exercise18_34() {
JPanel panel1 = new JPanel(new GridLayout(6, 7));
for (int i = 0; i < cells.length; i++)
for (int j = 0; j < cells[i].length; j++)
panel1.add(cells[i][j] = new Cell(i, j));
add(panel1, BorderLayout.CENTER);
JPanel panel2 = new JPanel();
panel2.add(jbtStartOver);
add(panel2, BorderLayout.SOUTH);
jbtStartOver.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.stop();
nextDisc = 'R';
result = null;
for (int i = 0; i < cells.length; i++)
for (int j = 0; j < cells[i].length; j++)
cells[i][j].token = ' ';
repaint();
}
});
}
class Cell extends JPanel {
char token = ' ';
int i, j;
boolean isFlashing;
private boolean available() {
return (token == ' ' && (i == 5 || cells[i + 1][j].token != ' '));
}
public Cell(int i, int j) {
this.i = i; this.j = j;
this.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
if (result != null)
return; // Game is over
if (available()) {
token = nextDisc;
result = isConsecutiveFour(cells);
if (result != null) {
timer.start();
}
else if (nextDisc == 'R')
nextDisc = 'Y';
else
nextDisc = 'R';
repaint();
}
}
});
}
protected void paintComponent(Graphics g) {
int radius = Math.min(getWidth(), getHeight()) * 4 / 10;
g.setColor(Color.BLUE);
g.fillRect(0, 0, getWidth(), getHeight());
if (token == ' ') {
g.setColor(Color.WHITE);
g.fillOval(getWidth() / 2 - radius, getHeight() / 2 - radius,
radius * 2, radius * 2);
}
else if (token == 'R') {
g.setColor(Color.RED);
g.fillOval(getWidth() / 2 - radius, getHeight() / 2 - radius,
radius * 2, radius * 2);
}
else if (token == 'Y') {
g.setColor(Color.YELLOW);
g.fillOval(getWidth() / 2 - radius, getHeight() / 2 - radius,
radius * 2, radius * 2);
}
}
}
public static int[][] isConsecutiveFour(Cell[][] cells) {
char[][] values = new char[cells.length][cells[0].length];
for (int i = 0; i < cells.length; i++)
for (int j = 0; j < cells[i].length; j++)
values[i][j] = cells[i][j].token;
return isConsecutiveFour(values);
}
public static int[][] isConsecutiveFour(char[][] values) {
int numberOfRows = values.length;
int numberOfColumns = values[0].length;
// Check rows
for (int i = 0; i < numberOfRows; i++) {
if (isConsecutiveFour(values[i]) != null) {
int[][] result = new int[4][2];
result[0][0] = result[1][0] = result[2][0] = result[3][0] = i;
int k = isConsecutiveFour(values[i]);
result[0][1] = k; result[1][1] = k + 1;
result[2][1] = k + 2; result[3][1] = k + 3;
return result;
}
}
// Check columns
for (int j = 0; j < numberOfColumns; j++) {
char[] column = new char[numberOfRows];
// Get a column into an array
for (int i = 0; i < numberOfRows; i++)
column[i] = values[i][j];
if (isConsecutiveFour(column) != null) {
int[][] result = new int[4][2];
result[0][1] = result[1][1] = result[2][1] = result[3][1] = j;
int k = isConsecutiveFour(column);
result[0][0] = k; result[1][0] = k + 1;
result[2][0] = k + 2; result[3][0] = k + 3;
return result;
}
}
// Check major diagonal (lower part)
for (int i = 0; i < numberOfRows - 3; i++) {
int numberOfElementsInDiagonal
= Math.min(numberOfRows - i, numberOfColumns);
char[] diagonal = new char[numberOfElementsInDiagonal];
for (int k = 0; k < numberOfElementsInDiagonal; k++)
diagonal[k] = values[k + i][k];
if (isConsecutiveFour(diagonal) != null) {
int[][] result = new int[4][2];
int k = isConsecutiveFour(diagonal);
result[0][0] = k + i;
result[1][0] = k + 1 + i;
result[2][0] = k + 2 + i;
result[3][0] = k + 3 + i;
result[0][1] = k;
result[1][1] = k + 1;
result[2][1] = k + 2;
result[3][1] = k + 3;
return result;
}
}
// Check major diagonal (upper part)
for (int j = 1; j < numberOfColumns - 3; j++) {
int numberOfElementsInDiagonal
= Math.min(numberOfColumns - j, numberOfRows);
char[] diagonal = new char[numberOfElementsInDiagonal];
for (int k = 0; k < numberOfElementsInDiagonal; k++)
diagonal[k] = values[k][k + j];
if (isConsecutiveFour(diagonal) != null) {
int[][] result = new int[4][2];
int k = isConsecutiveFour(diagonal);
result[0][0] = k;
result[1][0] = k + 1;
result[2][0] = k + 2;
result[3][0] = k + 3;
result[0][1] = k + j;
result[1][1] = k + 1 + j;
result[2][1] = k + 2 + j;
result[3][1] = k + 3 + j;
return result;
}
}
// Check sub-diagonal (left part)
for (int j = 3; j < numberOfColumns; j++) {
int numberOfElementsInDiagonal
= Math.min(j + 1, numberOfRows);
char[] diagonal = new char[numberOfElementsInDiagonal];
for (int k = 0; k < numberOfElementsInDiagonal; k++)
diagonal[k] = values[k][j - k];
if (isConsecutiveFour(diagonal) != null) {
int[][] result = new int[4][2];
int k = isConsecutiveFour(diagonal);
result[0][0] = k;
result[1][0] = k + 1;
result[2][0] = k + 2;
result[3][0] = k + 3;
result[0][1] = j - k;
result[1][1] = j - k - 1;
result[2][1] = j - k - 2;
result[3][1] = j - k - 3;
return result;
}
}
// Check sub-diagonal (right part)
for (int i = 1; i < numberOfRows - 3; i++) {
int numberOfElementsInDiagonal
= Math.min(numberOfRows - i, numberOfColumns);
char[] diagonal = new char[numberOfElementsInDiagonal];
for (int k = 0; k < numberOfElementsInDiagonal; k++)
diagonal[k] = values[k + i][numberOfColumns - k - 1];
if (isConsecutiveFour(diagonal) != null) {
int[][] result = new int[4][2];
int k = isConsecutiveFour(diagonal);
result[0][0] = k + i;
result[1][0] = k + i + 1;
result[2][0] = k + i + 2;
result[3][0] = k + i + 3;
result[0][1] = numberOfColumns - k - 1;
result[1][1] = numberOfColumns - (k + 1) - 1;
result[2][1] = numberOfColumns - (k + 2) - 1;
result[3][1] = numberOfColumns - (k + 3) - 1;
return result;
}
}
return null;
}
public static Integer isConsecutiveFour(char[] values) {
for (int i = 0; i < values.length - 3; i++) {
boolean isEqual = true;
for (int j = i; j < i + 3; j++) {
if (values[j] == ' ' || values[j] != values[j + 1]) {
isEqual = false;
break;
}
}
if (isEqual) return new Integer(i);
}
return null;
}
public static void main(String[] args) {
JFrame frame = new JFrame("Exercise18_34");
JApplet applet = new Exercise18_34();
frame.add(applet);
frame.setSize(210, 220);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Explanation / Answer
import java.awt.*;
import java.awt.event.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
public class Exercise18_34 extends JApplet {
private Cell[][] cells = new Cell[6][7];
private char nextDisc = 'R';
private Timer timer = new Timer(100, new FlashingCells());
private int[][] result;
private JButton jbtStartOver = new JButton("Start Over");
private Computer c;
private static boolean enableComputer = true;
class Computer{
private boolean isCompTurn;
private boolean stop;
private static final char OFFENSIVE = 'Y';
private static final char DEFENSIVE = 'R';
//public static enum {LEFT, RIGHT, BOTTOM, DIR45, DIR135, DIR225, DIR315};
public Computer(){
stop = false;
isCompTurn = false;
}
public void setCompTurn(boolean b){
isCompTurn = b;
}
public void Process(){
if( isCompTurn ){
int maxScore=0;
int x=0, y=0;
for( int i=0; i<cells.length; i++)
for( int j=0; j<cells[i].length; j++){
if( cells[i][j].available()){
int score;
score = getScore(i, j, OFFENSIVE);
score+= getScore(i, j, DEFENSIVE);
if( score > maxScore){
x = i;
y = j;
maxScore = score;
}
}
}
if( cells[x][y].available()){
cells[x][y].token = 'Y';
nextDisc='R';
}
repaint();
}
}
public int getScore(int i, int j, char s){
int score;
score = getVal(i, j-1, s) * ( 4+ getVal(i, j-2, s) * (16 + 64* getVal(i, j-3, s) ));
score += getVal(i+1, j, s) * ( 4+ getVal(i+2, j, s) * (16 + 64* getVal(i+3, j, s) ));
score += getVal(i, j+1, s) * ( 4+ getVal(i, j+2, s) * (16 + 64* getVal(i, j+3, s) ));
score += getVal(i-1, j-1, s) * ( 4+ getVal(i-2, j-2, s) * (16 + 64* getVal(i-3, j-3, s) ));
score += getVal(i+1, j+1, s) * ( 4+ getVal(i-2, j+2, s) * (16 + 64* getVal(i-3, j+3, s) ));
score += getVal(i-1, j+1, s) * ( 4+ getVal(i-2, j+2, s) * (16 + 64* getVal(i-3, j+3, s) ));
score += getVal(i+1, j-1, s) * ( 4+ getVal(i+2, j-2, s) * (16 + 64* getVal(i+3, j-3, s) ));
return score;
}
public int getVal(int i, int j, char s ){
if(isExist(i, j) && cells[i][j].token==s)
return 1;
else
return 0;
}
public boolean isExist(int i, int j){
return i>=0 && i< cells.length && j>=0 && j<cells[i].length;
}
public boolean available(int i, int j){
return cells[i][j].token!=' ';
}
}
class FlashingCells implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (cells[result[0][0]][result[0][1]].token == ' ') {
cells[result[0][0]][result[0][1]].token = nextDisc;
cells[result[1][0]][result[1][1]].token = nextDisc;
cells[result[2][0]][result[2][1]].token = nextDisc;
cells[result[3][0]][result[3][1]].token = nextDisc;
} else {
cells[result[0][0]][result[0][1]].token = ' ';
cells[result[1][0]][result[1][1]].token = ' ';
cells[result[2][0]][result[2][1]].token = ' ';
cells[result[3][0]][result[3][1]].token = ' ';
}
repaint();
}
}
public Exercise18_34() {
JPanel panel1 = new JPanel(new GridLayout(6, 7));
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[i].length; j++) {
panel1.add(cells[i][j] = new Cell(i, j));
}
}
add(panel1, BorderLayout.CENTER);
JPanel panel2 = new JPanel();
panel2.add(jbtStartOver);
add(panel2, BorderLayout.SOUTH);
jbtStartOver.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
timer.stop();
nextDisc = 'R';
result = null;
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[i].length; j++) {
cells[i][j].token = ' ';
}
}
repaint();
}
});
c = new Computer();
}
class Cell extends JPanel
{
char token = ' ';
int i, j;
boolean isFlashing;
private boolean available() {
return (token == ' ' && (i == 5 || cells[i + 1][j].token != ' '));
}
public Cell(int i, int j) {
this.i = i;
this.j = j;
this.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
if (result != null) {
return; // Game is over
}
if (available()) {
token = nextDisc;
result = isConsecutiveFour(cells);
if (result != null) {
timer.start();
} else if (nextDisc == 'R') {
nextDisc = 'Y';
c.setCompTurn(true);
}
repaint();
}
}
public void mouseReleased(MouseEvent e){
if (result != null) {
return; // Game is over
}
if( c.isCompTurn )
c.Process();
result = isConsecutiveFour(cells);
if (result != null) {
timer.start();
} else {
nextDisc = 'R';
c.setCompTurn(false);
}
}
});
}
protected void paintComponent(Graphics g) {
int radius = Math.min(getWidth(), getHeight()) * 4 / 10;
g.setColor(Color.BLUE);
g.fillRect(0, 0, getWidth(), getHeight());
if (token == ' ') {
g.setColor(Color.WHITE);
g.fillOval(getWidth() / 2 - radius, getHeight() / 2 - radius,
radius * 2, radius * 2);
} else if (token == 'R') {
g.setColor(Color.RED);
g.fillOval(getWidth() / 2 - radius, getHeight() / 2 - radius,
radius * 2, radius * 2);
} else if (token == 'Y') {
g.setColor(Color.YELLOW);
g.fillOval(getWidth() / 2 - radius, getHeight() / 2 - radius,
radius * 2, radius * 2);
}
}
}
public static int[][] isConsecutiveFour(Cell[][] cells) {
char[][] values = new char[cells.length][cells[0].length];
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[i].length; j++) {
values[i][j] = cells[i][j].token;
}
}
return isConsecutiveFour(values);
}
public static int[][] isConsecutiveFour(char[][] values) {
int numberOfRows = values.length;
int numberOfColumns = values[0].length;
// Check rows
for (int i = 0; i < numberOfRows; i++) {
if (isConsecutiveFour(values[i]) != null) {
int[][] result = new int[4][2];
result[0][0] = result[1][0] = result[2][0] = result[3][0] = i;
int k = isConsecutiveFour(values[i]);
result[0][1] = k;
result[1][1] = k + 1;
result[2][1] = k + 2;
result[3][1] = k + 3;
return result;
}
}
// Check columns
for (int j = 0; j < numberOfColumns; j++) {
char[] column = new char[numberOfRows];
// Get a column into an array
for (int i = 0; i < numberOfRows; i++) {
column[i] = values[i][j];
}
if (isConsecutiveFour(column) != null) {
int[][] result = new int[4][2];
result[0][1] = result[1][1] = result[2][1] = result[3][1] = j;
int k = isConsecutiveFour(column);
result[0][0] = k;
result[1][0] = k + 1;
result[2][0] = k + 2;
result[3][0] = k + 3;
return result;
}
}
// Check major diagonal (lower part)
for (int i = 0; i < numberOfRows - 3; i++) {
int numberOfElementsInDiagonal
= Math.min(numberOfRows - i, numberOfColumns);
char[] diagonal = new char[numberOfElementsInDiagonal];
for (int k = 0; k < numberOfElementsInDiagonal; k++) {
diagonal[k] = values[k + i][k];
}
if (isConsecutiveFour(diagonal) != null) {
int[][] result = new int[4][2];
int k = isConsecutiveFour(diagonal);
result[0][0] = k + i;
result[1][0] = k + 1 + i;
result[2][0] = k + 2 + i;
result[3][0] = k + 3 + i;
result[0][1] = k;
result[1][1] = k + 1;
result[2][1] = k + 2;
result[3][1] = k + 3;
return result;
}
}
// Check major diagonal (upper part)
for (int j = 1; j < numberOfColumns - 3; j++) {
int numberOfElementsInDiagonal
= Math.min(numberOfColumns - j, numberOfRows);
char[] diagonal = new char[numberOfElementsInDiagonal];
for (int k = 0; k < numberOfElementsInDiagonal; k++) {
diagonal[k] = values[k][k + j];
}
if (isConsecutiveFour(diagonal) != null) {
int[][] result = new int[4][2];
int k = isConsecutiveFour(diagonal);
result[0][0] = k;
result[1][0] = k + 1;
result[2][0] = k + 2;
result[3][0] = k + 3;
result[0][1] = k + j;
result[1][1] = k + 1 + j;
result[2][1] = k + 2 + j;
result[3][1] = k + 3 + j;
return result;
}
}
// Check sub-diagonal (left part)
for (int j = 3; j < numberOfColumns; j++) {
int numberOfElementsInDiagonal
= Math.min(j + 1, numberOfRows);
char[] diagonal = new char[numberOfElementsInDiagonal];
for (int k = 0; k < numberOfElementsInDiagonal; k++) {
diagonal[k] = values[k][j - k];
}
if (isConsecutiveFour(diagonal) != null) {
int[][] result = new int[4][2];
int k = isConsecutiveFour(diagonal);
result[0][0] = k;
result[1][0] = k + 1;
result[2][0] = k + 2;
result[3][0] = k + 3;
result[0][1] = j - k;
result[1][1] = j - k - 1;
result[2][1] = j - k - 2;
result[3][1] = j - k - 3;
return result;
}
}
// Check sub-diagonal (right part)
for (int i = 1; i < numberOfRows - 3; i++) {
int numberOfElementsInDiagonal
= Math.min(numberOfRows - i, numberOfColumns);
char[] diagonal = new char[numberOfElementsInDiagonal];
for (int k = 0; k < numberOfElementsInDiagonal; k++) {
diagonal[k] = values[k + i][numberOfColumns - k - 1];
}
if (isConsecutiveFour(diagonal) != null) {
int[][] result = new int[4][2];
int k = isConsecutiveFour(diagonal);
result[0][0] = k + i;
result[1][0] = k + i + 1;
result[2][0] = k + i + 2;
result[3][0] = k + i + 3;
result[0][1] = numberOfColumns - k - 1;
result[1][1] = numberOfColumns - (k + 1) - 1;
result[2][1] = numberOfColumns - (k + 2) - 1;
result[3][1] = numberOfColumns - (k + 3) - 1;
return result;
}
}
return null;
}
public static Integer isConsecutiveFour(char[] values) {
for (int i = 0; i < values.length - 3; i++) {
boolean isEqual = true;
for (int j = i; j < i + 3; j++) {
if (values[j] == ' ' || values[j] != values[j + 1]) {
isEqual = false;
break;
}
}
if (isEqual) {
return new Integer(i);
}
}
return null;
}
public static void main(String[] args) {
JFrame frame = new JFrame("Exercise18_34");
JApplet applet = new Exercise18_34();
frame.add(applet);
frame.setSize(210, 220);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.