This commit is contained in:
MaurizioBruetsch 2017-10-19 11:05:33 +02:00
commit 54afd84fe1
9 changed files with 218 additions and 89 deletions

View file

@ -18,6 +18,8 @@ src/game/GameEntry.java \
src/game/PlayerObject.java \
src/player/Player.java \
src/player/malte/MalteAI.java \
src/player/malte/Pattern.java \
src/player/malte/Item.java \
src/player/maurizio/MaurizioAI.java
OBJECTS=$($(subst $(CLASSPATH),$(BUILDS),$(CLASSES)):.java=.class)
@ -26,6 +28,8 @@ BUILDFILES=$(OBJECTS) $(FXMLS_BUILD)
MAIN=game.Main
N=100
all: $(CLASSES) $(FXMLS_BUILD)
$(JAVAC) $(JAVAC_OPTIONS) -cp $(CLASSPATH):$(LIBARIES) $(CLASSES) -d $(BUILDS)
@ -33,6 +37,9 @@ all: $(CLASSES) $(FXMLS_BUILD)
run: $(CLASSES)
$(JAVA) -cp $(BUILDS):$(LIBARIES) $(MAIN)
simulate: $(CLASSES)
$(JAVA) -cp $(BUILDS):$(LIBARIES) $(MAIN) $(N)
doc: $(CLASSES)
$(JAVADOC) $(JAVADOC_OPTIONS) -cp $(CLASSPATH):$(LIBARIES) $(CLASSES) -d $(DOC)

View file

@ -3,7 +3,8 @@ package game;
import java.util.Random;
import player.Player;
import player.MaurizioAI;
import player.maurizio.MaurizioAI;
import player.malte.MalteAI;
/**
* Represents a game of Connect Four.
@ -13,12 +14,12 @@ public class Game {
/**
* Number of columns on the board.
*/
private final static int GAME_COLUMNS = 7;
public final static int GAME_COLUMNS = 7;
/**
* Number of rows on the board.
*/
private final static int GAME_ROWS = 6;
public final static int GAME_ROWS = 6;
/**
* Player One
@ -69,6 +70,39 @@ public class Game {
this.gameOn = false;
}
/**
* Simulates n games.
* Simulates the games and prints statistical output to stdout.
*
* @param runs The number of games to simulate.
*/
public static void simulate(int runs) {
Player p1 = new MaurizioAI("Maurizio");
Player p2 = new MalteAI("Malte");
// 0 - Draw
// 1 - p1 wins
// 2 - p2 wins
int[] statistic = new int[3];
for (int i = 0; i < runs; i++) {
int result = new Game(p1, p2).start(false, true);
// TODO: Improve IDs
statistic[result]++;
}
double[] percents = new double[3];
for (int i = 0; i < statistic.length; i++) {
percents[i] = ((double)statistic[i]) / runs * 100.0;
}
System.out.println("Draws : " + statistic[0]);
System.out.println(p1.getName() + ": " + statistic[1] + " wins");
System.out.println(p2.getName() + ": " + statistic[2] + " wins");
System.out.println("PERCENTAGE:");
System.out.println("Draws : " + percents[0] + "%");
System.out.println(p1.getName() + ": " + percents[1] + "% wins");
System.out.println(p2.getName() + ": " + percents[2] + "% wins");
}
/**
* Start a game.
* @param output determines, whether game info etc. gets printed to the console
@ -168,14 +202,14 @@ public class Game {
* @return the state of the game, -1 = still undecided , 0 = draw, 1 = Player 1 wins, ...
*/
private int checkState(boolean output) {
if(MaurizioAI.checkWin(this.board, p1.getID())){
if(checkWin(this.board, p1.getID())){
this.gameOn = false;
if(output){
System.out.println(p1.getP().getName() + " wins!");
}
return p1.getID(); // player 1 wins
}
if(MaurizioAI.checkWin(this.board, p2.getID())){
if(checkWin(this.board, p2.getID())){
this.gameOn = false;
if(output){
System.out.println(p2.getP().getName() + " wins!");
@ -242,4 +276,83 @@ public class Game {
}
System.out.println();
}
public static boolean checkWin(int[][] board, int player){
int winLength = 4;
boolean win = false;
// check columns for win
for(int i=0;i<board.length;i++){
for(int j=0;j<(board[0].length-winLength+1);j++){
if(board[i][j] == player){
win = true;
for(int k=1;k<winLength;k++){
if(board[i][j+k] != board[i][j]){
win = false;
break;
}
}
if(win){
return true;
}
}
}
}
// check rows for win
for(int i=0;i<board[0].length;i++){
for(int j=0;j<(board.length-winLength+1);j++){
if(board[j][i] == player){
win = true;
for(int k=1;k<winLength;k++){
if(board[j+k][i] != board[j][i]){
win = false;
break;
}
}
if(win){
return true;
}
}
}
}
// check diagonals for win
//bottom-left to top-right diagonals
for(int i=0;i<(board.length-winLength+1);i++){
for(int j=(winLength-1);j<board[0].length;j++){
if(board[i][j] == player){
win = true;
for(int k=1;k<winLength;k++){
if(board[i+k][j-k] != board[i][j]){
win = false;
break;
}
}
if(win){
return true;
}
}
}
}
//top-left to bottom-right diagonals
for(int i=0;i<(board.length-winLength+1);i++){
for(int j=0;j<(board[0].length-winLength+1);j++){
if(board[i][j] == player){
win = true;
for(int k=1;k<winLength;k++){
if(board[i+k][j+k] != board[i][j]){
win = false;
break;
}
}
if(win){
return true;
}
}
}
}
return false;
}
}

View file

@ -1,14 +1,18 @@
package game;
import player.Player;
import player.MaurizioAI;
import player.MalteAI;
import player.maurizio.MaurizioAI;
import player.malte.MalteAI;
public class Main {
public static void main(String[] args) {
if (args.length == 1) {
Game.simulate(Integer.parseInt(args[0]));
} else {
Player p1 = new MalteAI("Malte");
Player p2 = new MaurizioAI("Maurizio");
new Game(p1, p2).start(true, true); //1. param = output mode, 2. param = random beginner
}
}
}

View file

@ -22,6 +22,7 @@ public class PlayerObject {
public PlayerObject(int id, Player p) {
this.p = p;
this.id = id;
this.p.setPlayerID(id);
}
public void setSymbol(String sym) {

View file

@ -4,4 +4,5 @@ public interface Player {
public int move(int[][] game);
public String getName();
public void setPlayerID(int id);
}

View file

@ -0,0 +1,39 @@
package player.malte;
public class Item {
private int posX;
private int posY;
private int[] ids;
public Item(int posX, int posY, int id) {
this(posX, posY, new int[]{id});
}
public Item(int posX, int posY, int[] ids) {
this.posX = posX;
this.posY = posY;
this.ids = ids;
}
public int getPosX() {
return this.posX;
}
public int getPosY() {
return this.posY;
}
public int[] getIDs() {
return this.ids;
}
public boolean hasID(int id) {
for (int i: ids) {
if (i == id) {
return true;
}
}
return false;
}
}

View file

@ -1,20 +1,27 @@
package player;
package player.malte;
import java.util.Random;
import java.util.Set;
import java.util.HashSet;
import java.util.Arrays;
import player.Player;
public class MalteAI implements Player{
private String name;
private Random ran;
private int id;
public MalteAI(String name){
this.name = name;
this.ran = new Random();
}
public void setPlayerID(int id) {
this.id = id;
}
public int move(int[][] board){
Set<Integer> options = new HashSet<>(Arrays.asList(0,1,2,3,4,5,6));
for (Integer i: copySet(options)) {
@ -22,11 +29,28 @@ public class MalteAI implements Player{
options.remove(i);
}
}
Set<Integer> instantWins = getWinningOptions(options, board);
// Set<Integer> preventions = getPreventionOptions(options, board);
return takeRandom(options).intValue();
}
private Set<Integer> getWinningOptions(Set<Integer> options, int[][] board) {
Pattern topOfColumn = new Pattern(new Item(0, 0, 0),
new Item(0, 1, id),
new Item(0, 2, id),
new Item(0, 3, id));
Pattern leftInRow = new Pattern(new Item(0, 0, 0),
new Item(1, 0, id),
new Item(2, 0, id),
new Item(3, 0, id));
Pattern rightInRow = new Pattern(new Item(0, 0, 0),
new Item(-1, 0, id),
new Item(-2, 0, id),
new Item(-3, 0, id));
return null;
}
private Set<Integer> copySet(Set<Integer> s) {
return new HashSet<Integer>(s);
}

View file

@ -0,0 +1,10 @@
package player.malte;
public class Pattern {
private Item[] parts;
public Pattern(Item... parts) {
this.parts = parts;
}
}

View file

@ -1,17 +1,24 @@
package player;
package player.maurizio;
import java.util.Random;
import player.Player;
public class MaurizioAI implements Player {
private String name;
private Random ran;
private int id;
public MaurizioAI(String name){
this.name = name;
this.ran = new Random();
}
public void setPlayerID(int id) {
this.id = id;
}
public int move(int[][] board){
int choice = ran.nextInt(7);
while (board[choice][0] != 0) {
@ -20,83 +27,6 @@ public class MaurizioAI implements Player {
return choice;
}
public static boolean checkWin(int[][] board, int player){
int winLength = 4;
boolean win = false;
// check columns for win
for(int i=0;i<board.length;i++){
for(int j=0;j<(board[0].length-winLength+1);j++){
if(board[i][j] == player){
win = true;
for(int k=1;k<winLength;k++){
if(board[i][j+k] != board[i][j]){
win = false;
break;
}
}
if(win){
return true;
}
}
}
}
// check rows for win
for(int i=0;i<board[0].length;i++){
for(int j=0;j<(board.length-winLength+1);j++){
if(board[j][i] == player){
win = true;
for(int k=1;k<winLength;k++){
if(board[j+k][i] != board[j][i]){
win = false;
break;
}
}
if(win){
return true;
}
}
}
}
// check diagonals for win
//bottom-left to top-right diagonals
for(int i=0;i<(board.length-winLength+1);i++){
for(int j=(winLength-1);j<board[0].length;j++){
if(board[i][j] == player){
win = true;
for(int k=1;k<winLength;k++){
if(board[i+k][j-k] != board[i][j]){
win = false;
break;
}
}
if(win){
return true;
}
}
}
}
//top-left to bottom-right diagonals
for(int i=0;i<(board.length-winLength+1);i++){
for(int j=0;j<(board[0].length-winLength+1);j++){
if(board[i][j] == player){
win = true;
for(int k=1;k<winLength;k++){
if(board[i+k][j+k] != board[i][j]){
win = false;
break;
}
}
if(win){
return true;
}
}
}
}
return false;
}
public String getName(){
return this.name;