Did commenting

This commit is contained in:
Malte Tammena 2017-10-20 13:24:11 +02:00 committed by Maurizio Bruetsch
parent 2e9347cfb3
commit 1d87754f53

View file

@ -7,18 +7,42 @@ import java.util.Arrays;
import player.Player; import player.Player;
/**
* Maltes artificial intelligence for playing a game of Connect Four
*/
public class MalteAI implements Player{ public class MalteAI implements Player{
/**
* Name of the player.
*/
private String name; private String name;
/**
* Random Object.
*/
private Random ran; private Random ran;
/**
* The players ID.
*/
private int id; private int id;
/**
* The enemy's ID.
*/
private int enemyID; private int enemyID;
/**
* Constructor.
*
* @param name The name for the player.
*/
public MalteAI(String name){ public MalteAI(String name){
this.name = name; this.name = name;
this.ran = new Random(); this.ran = new Random();
} }
@Override
public void setPlayerID(int id) { public void setPlayerID(int id) {
this.id = id; this.id = id;
this.enemyID = id == 1 ? 2: 1; this.enemyID = id == 1 ? 2: 1;
@ -28,29 +52,40 @@ public class MalteAI implements Player{
this.enemyID = enemyID; this.enemyID = enemyID;
} }
@Override
public int move(int[][] board){ public int move(int[][] board){
// Create a set of all possible options.
Set<Integer> options = new HashSet<>(Arrays.asList(0,1,2,3,4,5,6)); Set<Integer> options = new HashSet<>(Arrays.asList(0,1,2,3,4,5,6));
// Remove impossible options.
for (Integer i: copySet(options)) { for (Integer i: copySet(options)) {
if (board[i][0] != 0) { if (board[i][0] != 0) {
options.remove(i); options.remove(i);
} }
} }
// Get options which would lead to instant win.
Set<Integer> winningOptions = getRowCompletionOptions(options, board, id); Set<Integer> winningOptions = getRowCompletionOptions(options, board, id);
for (Integer i: winningOptions) { for (Integer i: winningOptions) {
return i.intValue(); return i.intValue();
} }
// Get options which would prevent an instant win of the enemy.
Set<Integer> preventionsOptions = getRowCompletionOptions(options, board, enemyID); Set<Integer> preventionsOptions = getRowCompletionOptions(options, board, enemyID);
for (Integer i: preventionsOptions) { for (Integer i: preventionsOptions) {
// Only accept options, that would not cause a winning opportunity for the enemy.
int[][] fakeBoard = makeMove(copyBoard(board), i, id); int[][] fakeBoard = makeMove(copyBoard(board), i, id);
if (getRowCompletionOptions(options, fakeBoard, enemyID).size() == 0) { if (getRowCompletionOptions(options, fakeBoard, enemyID).size() == 0) {
return i.intValue(); return i.intValue();
} }
} }
// If nothing applies, take a random valied one.
return takeRandom(options).intValue(); return takeRandom(options).intValue();
} }
/**
* Copies the given board.
*
* @param board The board to be copied.
* @return A deep copy of the board.
*/
private int[][] copyBoard(int[][] board) { private int[][] copyBoard(int[][] board) {
int[][] copy = new int[board.length][board[0].length]; int[][] copy = new int[board.length][board[0].length];
for (int i = 0; i < board.length; i++) { for (int i = 0; i < board.length; i++) {
@ -61,25 +96,56 @@ public class MalteAI implements Player{
return copy; return copy;
} }
/**
* Makes a move on the given board.
* Makes a move on the given board, no winning check or anything,
* just a fake move on the given board. Necessary for confirming that
* a chosen move will not give the enemy an instant win.
*
* @param board The board on which the move is made.
* @param choice The column to play in.
* @param id The player's id.
* @return The modified board.
*/
private int[][] makeMove(int[][] board, int choice, int id) { private int[][] makeMove(int[][] board, int choice, int id) {
int column = 0; int column = 0;
// If the column is full, do nothing.
if (board[choice][column] != 0) { if (board[choice][column] != 0) {
return board; return board;
} }
// Find the last empty row.
while (board[choice][column + 1] == 0) { while (board[choice][column + 1] == 0) {
column++; column++;
} }
// Add the players piece.
board[choice][column] = id; board[choice][column] = id;
return board; return board;
} }
/**
* Instant winning options.
* Returns a set of options for the player to choose from. If any one is choosen and
* played by the player with the given id, a win is certain.
*
* @param options The options, that are valid, a subset is returned.
* @param board The current game's board.
* @param id The players id.
* @return A subset of options which would lead to a win.
*/
private Set<Integer> getRowCompletionOptions(Set<Integer> options, int[][] board, int id) { private Set<Integer> getRowCompletionOptions(Set<Integer> options, int[][] board, int id) {
// Get winning patterns from Generator.
Set<Pattern> pats = PatternGenerator.winningPatterns(id); Set<Pattern> pats = PatternGenerator.winningPatterns(id);
// Get patterns, that match anywhere on the board.
Set<Pattern> matches = Pattern.matchingPatterns(pats, board); Set<Pattern> matches = Pattern.matchingPatterns(pats, board);
// Create set to be returned.
Set<Integer> ret = new HashSet<>(); Set<Integer> ret = new HashSet<>();
// Iterate over all matches.
for (Pattern p: matches) { for (Pattern p: matches) {
// Get all positions, this pattern matches.
Set<Position> positions = p.matches(board); Set<Position> positions = p.matches(board);
// Get empty spaces in the pattern.
for (Item i: p.getZeros()) { for (Item i: p.getZeros()) {
// Add all options to the set.
for(Position pos: positions) { for(Position pos: positions) {
ret.add(new Integer(i.getPosX() + pos.getPosX())); ret.add(new Integer(i.getPosX() + pos.getPosX()));
} }
@ -88,10 +154,19 @@ public class MalteAI implements Player{
return ret; return ret;
} }
/**
* Copies a set of Integer.
*/
private Set<Integer> copySet(Set<Integer> s) { private Set<Integer> copySet(Set<Integer> s) {
return new HashSet<Integer>(s); return new HashSet<Integer>(s);
} }
/**
* Takes a random Integer from a set of Integer.
*
* @param s The set to take from.
* @return A random element of s.
*/
private Integer takeRandom(Set<Integer> s) { private Integer takeRandom(Set<Integer> s) {
int item = ran.nextInt(s.size()); int item = ran.nextInt(s.size());
int i = 0; int i = 0;
@ -105,6 +180,9 @@ public class MalteAI implements Player{
return 0; return 0;
} }
/**
* Get the player's name.
*/
public String getName(){ public String getName(){
return this.name; return this.name;
} }