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;
import java.awt.*;
import javax.swing.*;
@ -42,15 +41,23 @@ public class ConnectFour extends JFrame {
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);
// 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++) {
board.insertPlate(new Plate(PlateType.X), 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();

View file

@ -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)
@ -122,51 +149,83 @@ public class GameBoard extends JPanel {
}
/**
* Override paint function to rescale all caontainers on every repaint
* 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
*/
@Override
public void paint(Graphics g) {
System.out.println("updating sizes");
for (PlateContainer[] plateContainers : BoardContainers) {
for (PlateContainer plateContainer : plateContainers) {
plateContainer.setPreferredSize(new Dimension(this.getSuggestedContainerSize(this.getSize()),
this.getSuggestedContainerSize(this.getSize())));
}
}
super.paint(g);
}
@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");
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 false;
return null;
// 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 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 (pc) {
switch (direction) {
case 0:
// check top
checkC = c;
@ -188,9 +247,9 @@ public class GameBoard extends JPanel {
checkR = r - i;
break;
case 4:
// check bottom
checkC = c;
checkR = r - i;
// check bottom
break;
case 5:
// check bottom left vert
@ -207,59 +266,38 @@ public class GameBoard extends JPanel {
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();
}
containers[i] = this.getPlateContainer(checkC, checkR);
}
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 containers;
}
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; } }
/**
* Override paint function to rescale all caontainers on every repaint
*/
@Override
public void paint(Graphics g) {
/*
* void switchPlayer() { if (p != 1) p = 1; else p = 1; }
*/
// update the size of all containers
for (PlateContainer[] plateContainers : BoardContainers) {
for (PlateContainer plateContainer : plateContainers) {
plateContainer.setPreferredSize(new Dimension(this.getSuggestedContainerSize(this.getSize()),
this.getSuggestedContainerSize(this.getSize())));
}
}
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);
}
}

View file

@ -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 <code>true</code> if occupied
* <code>false</code> if not
* @return <code>true</code> if occupied <code>false</code> if not
*/
public boolean containsPlate() {
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>
*/
@ -90,9 +100,18 @@ public class PlateContainer extends JPanel {
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));
}
}
}