As part of intelligent systems i wrote a minimax algorithm
Here my implementation
Note* I’ve already submitted this, wouldn’t recommend you pawn it off as your own!
This report explains the implementation
import java.util.ArrayList; import ie.ul.konane.Konane; import ie.ul.konane.KonaneMove; import ie.ul.konane.Player; /** * MiniMax DFS Implementation to play Konane * * @author David O Neill ( 0813001 ) * @version 4.0 */ public class C0813001 extends Player { private Konane currentState; /** * Constructor * * @param pName ( The name Associated with the user ) */ public C0813001( String pName ) { super( pName ); } /* (non-Javadoc) * @see ie.ul.konane.Player#initialize(char) */ @Override public void initialize( char pColour ) { this.name = "0813001"; this.colour = pColour; } /** * Instantiates the tree and gets the best move * * @return KonaneMove ( the next best move ) */ private KonaneMove decideMyMove() { KonaneMove move = null; if( this.currentState.generateMoves( this.colour ).size() == 0 ) { KonaneMove gameOver = new KonaneMove( 0 , 0 ); gameOver.lostGame(); return gameOver; } try { Tree tree = new Tree( this.currentState , this.colour ); move = tree.getNextMove(); } catch ( Exception e ) { move = this.currentState.generateMoves( this.colour ).get( 0 ); System.out.println( e.getMessage() ); e.printStackTrace(); } return move; } /* (non-Javadoc) * @see ie.ul.konane.Player#makeMove(ie.ul.konane.Konane) */ @Override public KonaneMove makeMove( Konane game ) { this.currentState = game; KonaneMove m = this.decideMyMove(); return m; } } /** * MiniMax DFS Implementation to play Konane * * @author David O Neill ( 0813001 ) * @version 4.0 */ class Tree { public static char PLAYER; public static char OPPONENT; public static int MAXDEPTH; public static int MAXVALUE; public static int MINVALUE; public static char heurisitic; private Node head; /** * Java's version of a static constructor */ static { Tree.MAXDEPTH = 4; Tree.MAXVALUE = Integer.MAX_VALUE - ( Tree.MAXDEPTH * 5000 ); Tree.MINVALUE = Integer.MIN_VALUE + ( Tree.MAXDEPTH * 5000 ); Tree.heurisitic = 'b'; } /** * Constructor for the Tree * * @param board ( the current Konane ) * @param me ( the char representing my color ) */ public Tree( Konane board , char me ) { Tree.PLAYER = me; Tree.OPPONENT = ( me == 'w' ) ? 'b' : 'w'; this.head = new Node( board ); } /** * After the tree has completed evaluating itself * This is use to get the move that was pushed to the top * * @return KonaneMove ( the best move ) */ public KonaneMove getNextMove() { return this.head.getBestChild().getLastMove(); } } /** * MiniMax DFS Implementation to play Konane * * @author David O Neill ( 0813001 ) * @version 4.0 */ class Node { private boolean max; private Konane currentBoard; private int currentDepth = 0; private ArrayList< Node > nextNodes = null; private ArrayList< KonaneMove > nextMoves = null; private KonaneMove moveThatCreatedState = null; private Node parentNode = null; private Node bestChildNode = null; private int heuristicValue = 0; /** * Default constructor for the Head * * This is the current state ( not considered a move ) * Begins the recursive generation of the Tree * * @param board ( Konane the current state ) */ public Node( Konane board ) { this.max = false; this.nextNodes = new ArrayList< Node >(); this.currentBoard = board; this.currentDepth = 0; this.generateNextNodes( Tree.PLAYER , this.max ); } /** * Overloaded constructor * Recursively generates next moves until MAXDEPTH is reached * The base case is, if this node's heuristic value is better than its parents * Then push this child Node to its parent's Node * * @param board ( Konane, that was generate for the next possible move ) * @param depth ( The depth of this Node ) * @param isMax ( Indicates whether its a min or max node ) * @param move ( The KonaneMove that generated this state ) * @param parent ( The parent of this state ) * @param whichPlayer ( The player at this depth ) */ public Node( Konane board , int depth , boolean isMax , KonaneMove move , Node parent , char whichPlayer ) { this.parentNode = parent; this.moveThatCreatedState = move; this.max = isMax; this.currentDepth = depth; this.nextNodes = new ArrayList< Node >(); this.currentBoard = board; this.generateNextNodes( whichPlayer , this.max ); if( parent.getBestChild() == null ) { parent.setHeurisiticValue( this.heuristicValue , this ); } else { if( this.max ) { if( this.heuristicValue > parent.getHeurisiticValue() ) { parent.setHeurisiticValue( this.heuristicValue , this ); } } else { if( this.heuristicValue < parent.getHeurisiticValue() ) { parent.setHeurisiticValue( this.heuristicValue , this ); } } } this.nextMoves.clear(); this.nextNodes.clear(); } /** * Gets the list of possible moves * And generates the next Node states for each move * * @param whichPlayer ( The player at this depth ) * @param isMax ( is max or min ) */ private void generateNextNodes( char whichPlayer , boolean isMax ) { Konane newBoard; Node tempNode; KonaneMove possibleMove; this.nextMoves = this.currentBoard.generateMoves( whichPlayer ); this.calculateHeuristicValue(); if( this.currentDepth == Tree.MAXDEPTH ) { return; } else { for ( int counter = 0 ; counter < this.nextMoves.size() ; counter++ ) { newBoard = new Konane( this.currentBoard ); possibleMove = new KonaneMove( this.nextMoves.get( counter ) ); try { newBoard.makeMove( whichPlayer , possibleMove ); } catch ( Exception e ) { e.printStackTrace(); } tempNode = new Node( newBoard , this.currentDepth + 1 , !isMax , possibleMove , this , ( whichPlayer == Tree.PLAYER ) ? Tree.OPPONENT : Tree.PLAYER ); this.nextNodes.add( tempNode ); } } } /** * Calculates the heuristic value of this Node */ private void calculateHeuristicValue() { int mymoves = 1; int opmoves = 1; int heuristic = this.currentDepth; int mypieces = this.currentBoard.countSymbol( Tree.PLAYER ); int oppieces = this.currentBoard.countSymbol( Tree.OPPONENT ); if( this.currentDepth > 0 ) { mymoves = ( this.max ) ? this.parentNode.getParentMoveCount() + 1 : this.nextMoves.size() + 1; opmoves = ( this.max ) ? this.nextMoves.size() + 1 : this.parentNode.getParentMoveCount() + 1; } if( this.currentDepth != Tree.MAXDEPTH && this.nextMoves.size() == 0 ) { heuristic += ( this.max == true ) ? Tree.MAXVALUE : Tree.MINVALUE; } if( Tree.heurisitic == 'a' ) { heuristic += ( int ) Math.round( mymoves - ( opmoves * 3 ) ); } else if( Tree.heurisitic == 'b' ) { heuristic += mymoves - opmoves; } else if( Tree.heurisitic == 'c' ) { heuristic += ( int ) Math.round( mymoves / ( opmoves * 3 ) ); } else if( Tree.heurisitic == 'd' ) { heuristic += ( int ) Math.round( mymoves / opmoves ); } else if( Tree.heurisitic == 'e' ) { heuristic += ( int ) Math.round( mypieces / ( oppieces * 3 ) ); } else if( Tree.heurisitic == 'f' ) { heuristic += ( int ) Math.round( mypieces / oppieces ); } else { heuristic += this.nextMoves.size(); } this.heuristicValue = heuristic; } /** * Gets a count of the moves for this Node * @return ( number of possible moves ) */ public int getParentMoveCount() { return this.nextMoves.size(); } /** * Gets the heuristic of this Node * * @return ( Heuristic Value ) */ public int getHeurisiticValue() { return this.heuristicValue; } /** * Gets the move that created this state * * @return ( The move ) */ public KonaneMove getLastMove() { return this.moveThatCreatedState; } /** * Sets the parent of a Node's, Heuristic value and besctChild * * @param betterHeuristicValue ( the heuristic of the child ) * @param betterChildNode ( the child ) */ public void setHeurisiticValue( int betterHeuristicValue , Node betterChildNode ) { this.heuristicValue = betterHeuristicValue; this.bestChildNode = betterChildNode; } /** * Gets the parent of a Node * * @return ( the parent Node ) */ public Node getParent() { return this.parentNode; } /** * Gets the best child from a Node * Typically used with the Head * * @return ( the best child ) */ public Node getBestChild() { return this.bestChildNode; } }