Finished up board and winning check

This commit is contained in:
Dorian Zedler 2020-02-17 16:55:21 +01:00
parent bc73ed4829
commit f4098bf044
3 changed files with 219 additions and 146 deletions

View file

@ -18,7 +18,6 @@
package de.itsblue.ConnectFour; package de.itsblue.ConnectFour;
import java.awt.*; import java.awt.*;
import javax.swing.*; import javax.swing.*;
@ -42,15 +41,23 @@ public class ConnectFour extends JFrame {
this.getContentPane().setLayout(new GridBagLayout()); this.getContentPane().setLayout(new GridBagLayout());
// Board initilisieren
GameBoard board = new GameBoard(); GameBoard board = new GameBoard();
board.setPreferredSize(new Dimension(200,200)); board.setPreferredSize(new Dimension(400, 400));
this.add(board); this.add(board);
for(int i = 0; i < 7; i++) { // plate in das Board einfügen
board.insertPlate(new Plate(PlateType.X), i); 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 // finish up
this.pack(); this.pack();

View file

@ -21,6 +21,15 @@ package de.itsblue.ConnectFour;
import javax.swing.*; import javax.swing.*;
import java.awt.*; 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 { public class GameBoard extends JPanel {
/** /**
@ -31,17 +40,23 @@ public class GameBoard extends JPanel {
/** /**
* The rows of the board * The rows of the board
*/ */
public int BoardRows = 6; private int BoardRows = 6;
/** /**
* The columns of the board * The columns of the board
*/ */
public int BoardColumns = 7; private int BoardColumns = 7;
/** /**
* Array containing all plate containers * 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 * Constructor
@ -55,13 +70,14 @@ public class GameBoard extends JPanel {
* *
* @param plate Plate object to insert * @param plate Plate object to insert
* @param column The column to insert the plate into * @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 // check if the column is out of range
if (column > BoardColumns - 1) if (column > BoardColumns - 1 || this.boardLocked)
return false; return "err";
// search for an empty row // search for an empty row
for (int i = BoardRows - 1; i >= 0; i--) { 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 // if the container is empty -> add the plate
this.BoardContainers[column][i].insertPlate(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.BoardContainers[c][r].removePlate();
} }
} }
this.boardLocked = false;
} }
/** /**
* Function to fill the board with containers * Function to fill the board with containers
*/ */
public void initBoard() { private void initBoard() {
// configure the main layout // configure the main layout
this.setLayout(new GridLayout(this.BoardRows, this.BoardColumns)); 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; int containerSize;
if (parentSize.getWidth() / this.BoardColumns > parentSize.getHeight() / this.BoardRows) if (parentSize.getWidth() / this.BoardColumns > parentSize.getHeight() / this.BoardRows)
@ -121,14 +148,139 @@ public class GameBoard extends JPanel {
return containerSize; 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 <code>null</code> 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 <code>null</code> 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 paint function to rescale all caontainers on every repaint
*/ */
@Override @Override
public void paint(Graphics g) { public void paint(Graphics g) {
System.out.println("updating sizes"); // update the size of all containers
for (PlateContainer[] plateContainers : BoardContainers) { for (PlateContainer[] plateContainers : BoardContainers) {
for (PlateContainer plateContainer : plateContainers) { for (PlateContainer plateContainer : plateContainers) {
plateContainer.setPreferredSize(new Dimension(this.getSuggestedContainerSize(this.getSize()), plateContainer.setPreferredSize(new Dimension(this.getSuggestedContainerSize(this.getSize()),
@ -139,127 +291,13 @@ public class GameBoard extends JPanel {
super.paint(g); super.paint(g);
} }
/**
* Override setPrefferedSize function to force aspect ratio
*/
@Override @Override
public void setPreferredSize(Dimension preferredSize) { public void setPreferredSize(Dimension preferredSize) {
Dimension newSize = new Dimension(this.getSuggestedContainerSize(preferredSize) * this.BoardColumns, Dimension newSize = new Dimension(this.getSuggestedContainerSize(preferredSize) * this.BoardColumns,
this.getSuggestedContainerSize(preferredSize) * this.BoardRows); this.getSuggestedContainerSize(preferredSize) * this.BoardRows);
super.setPreferredSize(newSize); 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; }
*/
} }

View file

@ -21,6 +21,14 @@ package de.itsblue.ConnectFour;
import javax.swing.JPanel; import javax.swing.JPanel;
import java.awt.*; 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 { public class PlateContainer extends JPanel {
/** /**
@ -33,6 +41,11 @@ public class PlateContainer extends JPanel {
*/ */
private Plate containedPlate = null; private Plate containedPlate = null;
/**
* is the container currently highlighted?
*/
private boolean highlighted = false;
/** /**
* Constructor * Constructor
*/ */
@ -49,8 +62,6 @@ public class PlateContainer extends JPanel {
if (this.containsPlate()) if (this.containsPlate())
return false; return false;
System.out.println("adding plate " + plate);
this.containedPlate = plate; this.containedPlate = plate;
return true; return true;
@ -68,8 +79,7 @@ public class PlateContainer extends JPanel {
/** /**
* Function to check if the container is occupied * Function to check if the container is occupied
* *
* @return <code>true</code> if occupied * @return <code>true</code> if occupied <code>false</code> if not
* <code>false</code> if not
*/ */
public boolean containsPlate() { public boolean containsPlate() {
if (this.containedPlate != null) if (this.containedPlate != null)
@ -79,7 +89,7 @@ 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: <code>null</code> * @return if it was occupied: contained plate, else: <code>null</code>
*/ */
@ -90,9 +100,18 @@ public class PlateContainer extends JPanel {
Plate ret = this.containedPlate; Plate ret = this.containedPlate;
this.containedPlate = null; this.containedPlate = null;
this.highlighted = false;
return ret; return ret;
} }
/**
* Function to highlight the container
*/
public void highlight() {
this.highlighted = true;
}
/** /**
* Override the paint function to draw the shape of the plate * Override the paint function to draw the shape of the plate
*/ */
@ -111,5 +130,14 @@ public class PlateContainer extends JPanel {
// draw plate // draw plate
g.fillOval((int) (this.getWidth() * 0.1), (int) (this.getHeight() * 0.1), (int) (this.getWidth() * 0.8), g.fillOval((int) (this.getWidth() * 0.1), (int) (this.getHeight() * 0.1), (int) (this.getWidth() * 0.8),
(int) (this.getHeight() * 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));
}
} }
} }