Finished up board and winning check
This commit is contained in:
parent
bc73ed4829
commit
f4098bf044
3 changed files with 219 additions and 146 deletions
|
@ -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);
|
||||
|
||||
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();
|
||||
|
|
|
@ -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 <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
|
||||
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; }
|
||||
*/
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
Reference in a new issue