//////////////////////////////////////////////////////////////////////////////// // Author: Julie Petrusa (991339). // // Due date: June 18, 2001. // // This program implements the game 'Duper Tac Toe' (written in Java). // // In this game, 1 point is awarded for each 3 in a row, 2 points for each 4 // // in a row and 3 points for each 5 in a row. // // The person with the most points wins the game. // // Rule: the first move cannot occupy the center square. // // Known bugs: error - always puts computer's move in 0, 0. // // ***please tell me how to fix this*** // //////////////////////////////////////////////////////////////////////////////// import java.io.*; // needed in order to do I/O class Board { //--------------------------------------------------------------------------- // fields // -Representation of Game Board: 2D char array (5 X 5) // -Representation of Playing Pieces: '#' = empty square // 'X' = user // 'O' = computer private char[][] boardArray; // board is represented by 2D char array final int size = 5; // size of board is (5 X 5) //--------------------------------------------------------------------------- // constructors public Board(char[][] PorMboard) { boardArray = new char[size][size]; // create the board for (int i=0; i 4 || row < 0 || col > 4 || col < 0) { System.out.println(""); System.out.print("That is not a legal move because "); System.out.println("the row and column indexes are from 0 to 4"); System.out.println("so please try again!"); System.out.println(""); return false; } if (row == 2 && col == 2 && counterPB == 0) { System.out.println(""); System.out.print("That is not a legal move because "); System.out.print("the first move cannot occupy the Center "); System.out.println("Square so please try again!"); System.out.println(""); return false; } if (boardArrayP[row][col] == '#') return true; else { System.out.println(""); System.out.print("That is not a legal move because "); System.out.println("that square is already occupied"); System.out.println("so please try again!"); System.out.println(""); return false; } } //--------------------------------------------------------------------------- // method move // -adds an 'X' or 'O' to the board public void move(char XorO, int row, int col) { boardArrayP[row][col] = XorO; // add 'X' or 'O' counterPB++; // increment counter } //--------------------------------------------------------------------------- // method win // -determines if the game is over // -returns true if the board is full, false otherwise // -displays a message if the game is over public boolean win() { if (counterPB >= 25) { System.out.println(""); System.out.println(""); System.out.println("GAME OVER!!!"); return true; } else return false; } //--------------------------------------------------------------------------- // method winner // -displays the user's and the computer's total points // -displays the winner public void winner() { Board newBoard = new Board(boardArrayP); int Upoints = newBoard.totalPoints('X'); // total points for user System.out.println("You have " + Upoints + " points"); int Cpoints = newBoard.totalPoints('O'); // total points for comp System.out.println("I have " + Cpoints + " points"); if (Upoints - Cpoints > 0) // find winner System.out.println("You Win!"); else System.out.println("You Lose!"); } //--------------------------------------------------------------------------- // method toString // -displays the board public String toString() { String display = ""; display = " 01234" + "\n"; for (int i=0; i scoreArray[ply+2]) // opponent's turn { this.ab1120(PBoard); return true; } this.ab1130(PBoard); // bad move return true; } public boolean ab1110(PlayBoard PBoard) { if (scoreArray[ply+3] < scoreArray[ply+2]) // computer's turn { this.ab1120(PBoard); return true; } this.ab1130(PBoard); // bad move return true; } public void ab1120(PlayBoard PBoard) { scoreArray[ply+2] = scoreArray[ply+3]; // good move, back up score this.princ(); // put good move on princ continuation this.ab1130(PBoard); } public void ab1130(PlayBoard PBoard) { ply--; // return up tree this.restore(); this.ab1131(PBoard); } public boolean ab1131(PlayBoard PBoard) { if (moveArray[0][movePArray[ply+1]+1] != -1) { this.ab1132(PBoard); // are there move moves? return true; } if (ply == 0) // no - if at root, return { int i = princArray[0][0]; int j = princArray[1][0]; PBoard.move('O', i, j); return true; } this.ab1100(PBoard); // otherwise repeat minimax return true; } public boolean ab1132(PlayBoard PBoard) // alpha-beta section { if (ply%2 == 0) // check whose turn it is { this.ab1134(PBoard); return true; } if (scoreArray[ply+3] <= scoreArray[ply+2]) // opponent's turn { this.ab1135(PBoard); return true; } this.ab1140(PBoard); // no cut-off return true; } public boolean ab1134(PlayBoard PBoard) { if (scoreArray[ply+3] >= scoreArray[ply+2]) // opponent's turn { this.ab1135(PBoard); return true; } this.ab1140(PBoard); // no cut-off return true; } public boolean ab1135(PlayBoard PBoard) { ply--; // cut-off occurs, stop this.restore(); // examining moves at this node if (moveArray[0][movePArray[ply+1]+1] == -1) { this.ab1131(PBoard); // are there any moves at one return true; } this.ab1140(PBoard); return true; } public void ab1140(PlayBoard PBoard) { movePArray[ply+1] = movePArray[ply+1]+1; this.ab200(PBoard); // level up tree? } public void ab(PlayBoard PBoard) { ply = 0; // initialize ply movePArray[ply] = 0; // the first ply starts at 0 index = 0; // initialize index this.ab100(PBoard); } //--------------------------------------------------------------------------- // method generate // -implements the move generator // -determines what all the legal moves are at the given state // -puts all the moves at the given ply on the move array // -records the index number from the move array where the next ply starts in // the move pointer array public void generate() { for (int i=0; i -1 && j > -1) // if valid move, { if (ply%2 == 0) // check whose turn it is boardArrayM[i][j] = 'O'; // make computer move else boardArrayM[i][j] = 'X'; // make user move } counterMB++; // increment counter } //--------------------------------------------------------------------------- // method qFunction // -implements the quiescence function // -determines if it is a good time to stop and score // -returns true if ply is at maximum depth, false otherwise public boolean qFunction() { if (ply == MAX_D) return true; else return false; } //--------------------------------------------------------------------------- // method sFunction // -implements the score function // -returns a numerical value representing how good a given state is // // S (x) = 3inRow(1) + 4inRow(2) + 5inRow(3) // + Board Position // + Squares Left // // Reasons why this is a good score function: // 3inRow(1) + 4inRow(2) + 5inRow(3) // -Getting 3, 4 or 5 in a row is very important because it is the only // way to get points and therefore it is the only way to win the game. // The constants that I have multiplied by each term are directly // proportional to the distribution of points in the game. I.E. - One // point is awarded for each 3 in a row, 2 points for each 4 in a row // and 3 points for any 5 in a row. // Board Position // -Some squares on the board are better than others. The values that I // have assigned to each square is directly proportional to the // number of ways of getting 5 in a row from that square. For example, // the middle square is the best because there are four possible ways // of getting 5 in a row. // 3 2 2 2 3 // 2 3 2 3 2 // 2 2 4 2 2 // 2 3 2 3 2 // 3 2 2 2 3 // Squares Left // -The possibility of getting 5 in a row decreases as the amount of // unoccupied squares decreases. // public int sFunction() { int score = 0; // 3inRow(1) + 4inRow(2) + 5inRow(3) Board newBoard = new Board(boardArrayM); // pass array to Board score = score + newBoard.totalPoints('O'); // add total points // Board Position for (int i=0; i -1 && j > -1) // if valid move, boardArrayM[i][j] = '#'; // delete move counterMB--; // decrement counter } //--------------------------------------------------------------------------- // method princ // -updates the information on the principle continuation array // -if the score at ply is good, then store that move and copy all the lower // moves up to the ply row public void princ() { int i = moveArray[0][movePArray[ply]]; // get move from int j = moveArray[1][movePArray[ply]]; // move array if (i > -1 && j > -1) // if valid move, { princArray[ply][ply] = i; // store move in principle princArray[ply+1][ply] = j; // continuation array } princArray[ply][ply+1] = princArray[ply+1][ply+1]; // copy lower princArray[ply+1][ply+1] = princArray[ply+2][ply+1]; // moves } //--------------------------------------------------------------------------- } // end class MemoryBoard class DuperTacToe1 { //--------------------------------------------------------------------------- // main method // -the computer plays 'Duper Tac Toe' with the user public static void main(String[] args) throws IOException { try { System.out.println(""); // display banner System.out.println(""); System.out.println("Author: Julie Petrusa (991339)."); System.out.println("Due date: June 18, 2001."); System.out.print("This program implements the game "); System.out.println("'Duper Tac Toe'."); System.out.print("In this game, 1 point is awarded for "); System.out.println("each 3 in a row, 2 points for"); System.out.print(" each 4 in a row and 3 points "); System.out.println("for each 5 in a row."); System.out.print("The person with the most points wins the "); System.out.println("game."); System.out.print("Rule: the first move cannot occupy the "); System.out.println("center square."); boolean value = true; do { System.out.println(""); // display options for the user System.out.println(""); System.out.println("Choose one of the following options:"); System.out.println(" 1 --> Play Duper Tac Toe"); System.out.println(" 2 --> Quit"); System.out.print("Answer: "); // prompt user for answer System.out.flush(); int answer = getInt(); // read in the user's answer switch (answer) // do what the user wants { case 1: PlayBoard PBoard = new PlayBoard(); // initialize while (!PBoard.win()) // while game not over, { System.out.println(""); System.out.println(""); System.out.println("You --> 'X'"); System.out.println(" Me --> 'O'"); System.out.println(""); System.out.println(""); System.out.println(PBoard.toString()); // display System.out.println(""); int row = 0; int col = 0; do { System.out.println("Your move:"); System.out.print("Row: "); // prompt user System.out.flush(); row = getInt(); // read in user's move System.out.print("Col: "); // prompt user System.out.flush(); col = getInt(); // read in user's move } while (!PBoard.legalMove(row, col)); PBoard.move('X', row, col); // update MemoryBoard MBoard = new MemoryBoard(PBoard); // init MBoard.ab(PBoard); // computer move } System.out.println(""); System.out.println(""); System.out.println(PBoard.toString()); // display System.out.println(""); PBoard.winner(); // display total points and winner break; case 2: value = false; // to end do-while loop break; default: // invalid answer, display error message System.out.println(""); System.out.println("Invalid answer!"); break; } // end switch } while (value != false); System.in.read(); // to view console } // end try catch (IOException e) { System.out.println("IOException"); } // end catch } //--------------------------------------------------------------------------- /* method getString -reads in a string -precondition: -the user has typed in a valid string -postcondition: -if valid string, string is read in -if not valid string, throws IOException -return: -static */ public static String getString() throws IOException { InputStreamReader isr = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(isr); String s = br.readLine(); return s; } //--------------------------------------------------------------------------- /* method getInt -reads in an integer -precondition: -the user has typed in a valid integer -postcondition: -if valid integer, integer is read in -if not valid integer, throws IOException -return: -static */ public static int getInt() throws IOException { String s = getString(); return Integer.parseInt(s); } //--------------------------------------------------------------------------- } // end class DuperTacToe1