diff --git a/src/de/itsblue/ConnectFour/ConnectFour.java b/src/de/itsblue/ConnectFour/ConnectFour.java
index fe67e89..e580b7e 100644
--- a/src/de/itsblue/ConnectFour/ConnectFour.java
+++ b/src/de/itsblue/ConnectFour/ConnectFour.java
@@ -18,7 +18,6 @@
package de.itsblue.ConnectFour;
-
import java.awt.*;
import javax.swing.*;
@@ -29,29 +28,37 @@ public class ConnectFour extends JFrame {
/**
*
*/
- private static final long serialVersionUID = 1L;
-
+ private static final long serialVersionUID = 1L;
+
ConnectFour() {
// Constructor
// initialize window
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setTitle("Connect 4");
-
+
this.setPreferredSize(new Dimension(600, 600));
this.getContentPane().setLayout(new GridBagLayout());
+ // Board initilisieren
GameBoard board = new GameBoard();
- board.setPreferredSize(new Dimension(200,200));
+ board.setPreferredSize(new Dimension(400, 400));
this.add(board);
- for(int i = 0; i < 7; i++) {
- board.insertPlate(new Plate(PlateType.X), i);
+ // plate in das Board einfügen
+ board.insertPlate(new Plate(PlateType.O), 1);
+
+ // ein paar mehr plates einfügen
+ for (int i = 0; i < 7; i++) {
+ String res = board.insertPlate(new Plate(PlateType.X), i);
+ // wen das Rückgabewert weder "ok" noch "err" ist, hat jemand gewonnen
+ if (res != "ok" && res != "err")
+ System.out.println(PlateType.valueOf(res));
}
- board.insertPlate(new Plate(PlateType.O), 1);
-
+ // board kann mit board.clearBoard(); geleert werden.
+
// finish up
this.pack();
this.setVisible(true);
diff --git a/src/de/itsblue/ConnectFour/GameBoard.java b/src/de/itsblue/ConnectFour/GameBoard.java
index d91afe4..c8c9626 100644
--- a/src/de/itsblue/ConnectFour/GameBoard.java
+++ b/src/de/itsblue/ConnectFour/GameBoard.java
@@ -21,6 +21,15 @@ package de.itsblue.ConnectFour;
import javax.swing.*;
import java.awt.*;
+import de.itsblue.ConnectFour.Plate.PlateType;
+
+/**
+ * GameBoard is a fully usable connect4 game board. It can take plates and
+ * insert them into a given column and check if somebody won the game.
+ *
+ * @author Oliver Schappacher
+ * @author Dorian Zedler
+ */
public class GameBoard extends JPanel {
/**
@@ -31,17 +40,23 @@ public class GameBoard extends JPanel {
/**
* The rows of the board
*/
- public int BoardRows = 6;
+ private int BoardRows = 6;
/**
* The columns of the board
*/
- public int BoardColumns = 7;
+ private int BoardColumns = 7;
/**
* Array containing all plate containers
*/
- PlateContainer[][] BoardContainers = new PlateContainer[BoardColumns][BoardRows];
+ private PlateContainer[][] BoardContainers = new PlateContainer[BoardColumns][BoardRows];
+
+ /**
+ * If set to true, the board will not accept any insertions. Will be set to
+ * false by the clear() function.
+ */
+ private boolean boardLocked = false;
/**
* Constructor
@@ -55,13 +70,14 @@ public class GameBoard extends JPanel {
*
* @param plate Plate object to insert
* @param column The column to insert the plate into
- * @return true if the inserton was successfull, false if the column is full
+ * @return "ok" if the inserton was successfull, "err" if the column is full,
+ * PlateType as string if a plate type has won
*/
- public boolean insertPlate(Plate plate, int column) {
+ public String insertPlate(Plate plate, int column) {
// check if the column is out of range
- if (column > BoardColumns - 1)
- return false;
+ if (column > BoardColumns - 1 || this.boardLocked)
+ return "err";
// search for an empty row
for (int i = BoardRows - 1; i >= 0; i--) {
@@ -69,13 +85,16 @@ public class GameBoard extends JPanel {
// if the container is empty -> add the plate
this.BoardContainers[column][i].insertPlate(plate);
- this.checkContainerForWin(column, i);
+ PlateType winCheckResult = this.checkContainerForWin(column, i);
- return true;
+ if (winCheckResult == null)
+ return "ok";
+
+ return winCheckResult.toString();
}
}
- return false;
+ return "err";
}
/**
@@ -89,12 +108,14 @@ public class GameBoard extends JPanel {
this.BoardContainers[c][r].removePlate();
}
}
+
+ this.boardLocked = false;
}
/**
* Function to fill the board with containers
*/
- public void initBoard() {
+ private void initBoard() {
// configure the main layout
this.setLayout(new GridLayout(this.BoardRows, this.BoardColumns));
@@ -110,7 +131,13 @@ public class GameBoard extends JPanel {
}
}
- public int getSuggestedContainerSize(Dimension parentSize) {
+ /**
+ * Function to calculate a size for the containers to fit a given dimension
+ *
+ * @param parentSize dimension for the containers to fit into
+ * @return suggested container size
+ */
+ private int getSuggestedContainerSize(Dimension parentSize) {
int containerSize;
if (parentSize.getWidth() / this.BoardColumns > parentSize.getHeight() / this.BoardRows)
@@ -121,14 +148,139 @@ public class GameBoard extends JPanel {
return containerSize;
}
+ /**
+ * Function to check if a certain container is the beginning of a four plate log
+ * chain of plates of the same type what would indicate the end of the game. If
+ * a matching chain is found, the involved containers are highlited.
+ *
+ * @param c column of the container to check
+ * @param r row of the container to check
+ * @return null
if there was no matching chain or the PlateType of
+ * the chain
+ */
+ public PlateType checkContainerForWin(int c, int r) {
+
+ // if there is no plate in the container to check
+ // -> return false
+ if (this.getPlateContainer(c, r) == null || !this.getPlateContainer(c, r).containsPlate())
+ return null;
+
+ // check all possible winnings clockwise
+ for (int pc = 0; pc < 8; pc++) {
+
+ int sum = 0;
+ PlateContainer[] currentContainers = this.getPlateContainerRow(c, r, pc);
+
+ for (PlateContainer plateContainer : currentContainers) {
+ if (plateContainer != null && plateContainer.containsPlate())
+ sum += plateContainer.getContainedPlate().getValue();
+ }
+
+ if (Math.abs(sum) == 4) {
+ this.boardLocked = true;
+
+ for (PlateContainer plateContainer : currentContainers) {
+ plateContainer.highlight();
+ }
+
+ return this.getPlateContainer(c, r).getContainedPlate().getType();
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Function to get the container at a certain column and row.
+ *
+ * @param c column of the container
+ * @param r row of the container
+ * @return null
if there is no container at the given posistion or
+ * the container at the given position
+ */
+ public PlateContainer getPlateContainer(int c, int r) {
+ if (this.BoardContainers.length > c && c >= 0 && this.BoardContainers[c].length > r && r >= 0)
+ return this.BoardContainers[c][r];
+
+ return null;
+ }
+
+ /**
+ * Function to get a row of four containers starting at a given one
+ *
+ * @param c column of the container to start at
+ * @param r row of the conatiner to start at
+ * @param direction direction of the row (0-7)
+ * @return list of containers starting with the given one
+ */
+ private PlateContainer[] getPlateContainerRow(int c, int r, int direction) {
+
+ PlateContainer[] containers = new PlateContainer[4];
+
+ if (direction < 0 || direction > 7)
+ return containers;
+
+ for (int i = 0; i < 4; i++) {
+
+ int checkC = 0;
+ int checkR = 0;
+
+ switch (direction) {
+ case 0:
+ // check top
+ checkC = c;
+ checkR = r + i;
+ break;
+ case 1:
+ // check top right vert
+ checkC = c + i;
+ checkR = r + i;
+ break;
+ case 2:
+ // check right
+ checkC = c + i;
+ checkR = r;
+ break;
+ case 3:
+ // check bottom right vert
+ checkC = c + i;
+ checkR = r - i;
+ break;
+ case 4:
+ // check bottom
+ checkC = c;
+ checkR = r - i;
+ break;
+ case 5:
+ // check bottom left vert
+ checkC = c - i;
+ checkR = r - i;
+ break;
+ case 6:
+ // check left
+ checkC = c - i;
+ checkR = r;
+ break;
+ case 7:
+ // check top left vert
+ checkC = c - i;
+ checkR = r + i;
+ break;
+ }
+
+ containers[i] = this.getPlateContainer(checkC, checkR);
+ }
+
+ return containers;
+ }
+
/**
* Override paint function to rescale all caontainers on every repaint
*/
@Override
public void paint(Graphics g) {
- System.out.println("updating sizes");
-
+ // update the size of all containers
for (PlateContainer[] plateContainers : BoardContainers) {
for (PlateContainer plateContainer : plateContainers) {
plateContainer.setPreferredSize(new Dimension(this.getSuggestedContainerSize(this.getSize()),
@@ -139,127 +291,13 @@ public class GameBoard extends JPanel {
super.paint(g);
}
+ /**
+ * Override setPrefferedSize function to force aspect ratio
+ */
@Override
public void setPreferredSize(Dimension preferredSize) {
Dimension newSize = new Dimension(this.getSuggestedContainerSize(preferredSize) * this.BoardColumns,
this.getSuggestedContainerSize(preferredSize) * this.BoardRows);
super.setPreferredSize(newSize);
}
-
- public boolean checkContainerForWin(int c, int r) {
-
- System.out.println("checking container c=" + c + " r=" + r + " for win");
-
- // if there is no plate in the container to check
- // -> return false
- if (this.getPlateContainer(c, r) == null || !this.getPlateContainer(c, r).containsPlate())
- return false;
-
- // check all possible winnings clockwise
- int[] sums = new int[8];
- for (int i = 0; i < 4; i++) {
- PlateContainer currentContainer = null;
-
- for (int pc = 0; pc < 8; pc++) {
- currentContainer = null;
-
- int checkC = 0;
- int checkR = 0;
-
- switch (pc) {
- case 0:
- // check top
- checkC = c;
- checkR = r + i;
- break;
- case 1:
- // check top right vert
- checkC = c + i;
- checkR = r + i;
- break;
- case 2:
- // check right
- checkC = c + i;
- checkR = r;
- break;
- case 3:
- // check bottom right vert
- checkC = c + i;
- checkR = r - i;
- break;
- case 4:
- checkC = c;
- checkR = r - i;
- // check bottom
- break;
- case 5:
- // check bottom left vert
- checkC = c - i;
- checkR = r - i;
- break;
- case 6:
- // check left
- checkC = c - i;
- checkR = r;
- break;
- case 7:
- // check top left vert
- checkC = c - i;
- checkR = r + i;
- break;
- default:
- currentContainer = null;
- break;
- }
-
- currentContainer = this.getPlateContainer(checkC, checkR);
-
- if (currentContainer != null && currentContainer.containsPlate())
- sums[pc] += currentContainer.getContainedPlate().getValue();
- }
- }
-
- for (int sum : sums) {
- if (Math.abs(sum) == 4) {
- if (sum > 0)
- System.out.println("negative won");
- else
- System.out.println("positive won");
-
- return true;
- }
- }
-
- return false;
- }
-
- public PlateContainer getPlateContainer(int containerColumn, int containerRow) {
-
- if (this.BoardContainers.length > containerColumn && containerColumn >= 0
- && this.BoardContainers[containerColumn].length > containerRow && containerRow >= 0)
- return this.BoardContainers[containerColumn][containerRow];
-
- return null;
- }
-
- /*
- * void winningCondition() { for (int i = 0; i <= 2; i++) for (int j = 0; j <=
- * 6; j++) { if (GameBoard[i][j] == p && GameBoard[i + 1][j] == p && GameBoard[i
- * + 2][j] == p && GameBoard[i + 3][j] == p) { finish = true; } } for (int i =
- * 0; i <= 5; i++) for (int j = 0; j <= 3; j++) { if (GameBoard[i][j] == p &&
- * GameBoard[i][j + 1] == p && GameBoard[i][j + 2] == p && GameBoard[i][j + 3]
- * == p) finish = true; }
- *
- * for (int i = 0; i <= 2; i++) for (int j = 0; j <= 3; j++) { if
- * (GameBoard[i][j] == p && GameBoard[i + 1][j + 1] == p && GameBoard[i + 2][j +
- * 2] == p && GameBoard[i + 3][j + 3] == p) finish = true; }
- *
- * for (int i = 0; i < 3; i++) for (int j = 6; j > 2; j--) { if (GameBoard[i][j]
- * == p && GameBoard[i + 1][j - 1] == p && GameBoard[i + 2][j - 2] == p &&
- * GameBoard[i + 3][j - 3] == p) finish = true; } }
- */
-
- /*
- * void switchPlayer() { if (p != 1) p = 1; else p = 1; }
- */
}
\ No newline at end of file
diff --git a/src/de/itsblue/ConnectFour/PlateContainer.java b/src/de/itsblue/ConnectFour/PlateContainer.java
index 928f372..5403311 100644
--- a/src/de/itsblue/ConnectFour/PlateContainer.java
+++ b/src/de/itsblue/ConnectFour/PlateContainer.java
@@ -21,6 +21,14 @@ package de.itsblue.ConnectFour;
import javax.swing.JPanel;
import java.awt.*;
+/**
+ * PlateContainer is a visual element intendet to be used in a GameBoard in
+ * order to store a plate and indicate what kind of plate it contains. It can ge
+ * highlighted for examplte to indicate that it was involeved in the end of a
+ * game.
+ *
+ * @author Dorian Zedler
+ */
public class PlateContainer extends JPanel {
/**
@@ -33,6 +41,11 @@ public class PlateContainer extends JPanel {
*/
private Plate containedPlate = null;
+ /**
+ * is the container currently highlighted?
+ */
+ private boolean highlighted = false;
+
/**
* Constructor
*/
@@ -49,8 +62,6 @@ public class PlateContainer extends JPanel {
if (this.containsPlate())
return false;
- System.out.println("adding plate " + plate);
-
this.containedPlate = plate;
return true;
@@ -68,8 +79,7 @@ public class PlateContainer extends JPanel {
/**
* Function to check if the container is occupied
*
- * @return true
if occupied
- * false
if not
+ * @return true
if occupied false
if not
*/
public boolean containsPlate() {
if (this.containedPlate != null)
@@ -79,20 +89,29 @@ public class PlateContainer extends JPanel {
}
/**
- * Function to clear the container
+ * Function to clear the container, also removes the highlighting
*
* @return if it was occupied: contained plate, else: null
*/
public Plate removePlate() {
if (!this.containsPlate())
return null;
-
+
Plate ret = this.containedPlate;
this.containedPlate = null;
+ this.highlighted = false;
+
return ret;
}
+ /**
+ * Function to highlight the container
+ */
+ public void highlight() {
+ this.highlighted = true;
+ }
+
/**
* Override the paint function to draw the shape of the plate
*/
@@ -111,5 +130,14 @@ public class PlateContainer extends JPanel {
// draw plate
g.fillOval((int) (this.getWidth() * 0.1), (int) (this.getHeight() * 0.1), (int) (this.getWidth() * 0.8),
(int) (this.getHeight() * 0.8));
+
+ if (this.highlighted) {
+ g.setColor(Color.green);
+ Graphics2D g2 = (Graphics2D) g;
+ g2.setStroke(new BasicStroke((int) (this.getWidth() * 0.1)));
+
+ g2.drawOval((int) (this.getWidth() * 0.1), (int) (this.getHeight() * 0.1), (int) (this.getWidth() * 0.8),
+ (int) (this.getHeight() * 0.8));
+ }
}
}
\ No newline at end of file