Chris Pollett >
Old Classes
> |
HW3 Solutions Page//TicTacToe.java -- a servlet to play TicTacToe import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; /** TicTacToe is a simple servlet that allows browser users to play a game of tictactoe against this servlet. @author Chris Pollett */ public class TicTacToe extends HttpServlet { /** This method is called whenever a request of our servlet is made. It spits out the header and footer HTML, Javascript and calls the appropriate subfunction to handle the request. @param request - data on this request @param response - data on where to reply to @throws IOException, ServletException */ public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setContentType("text/html"); out = response.getWriter(); String board = request.getParameter("board"); String again = request.getParameter("again"); String goFirst = request.getParameter("goFirst"); String moveX = request.getParameter("moveX"); String moveY = request.getParameter("moveY"); winO = false; winX = false; if(moveX != null && moveY != null) { int move = boardSize*Integer.parseInt(moveX) + Integer.parseInt(moveY); board = applyMove("O", move, board); winO = gameOver(board, move); } out.println("<html>"); out.println("<head><title>"+gameTitle+"</title>"); out.println("<script language=\"javascript1.1\" " + "type=\"text/javascript\" >"); out.println("<!--"); outputYNFunction(); outputCheckMoveFunction(); out.println("//-->"); out.println("</script></head>"); outputBody(board, goFirst, again); } /* Outputs the body of the HTML document the server sends back. @param board - current game board. @param goFirst - form data of who should go first @param again - if game ended says whether user wanted to play again */ protected void outputBody(String board, String goFirst, String again) { out.println("<body style=\"background:white\" >"); setAlign("center"); outputTag("h1", "TicTacToe"); if((board == null && goFirst == null) || (again !=null && again.toLowerCase().startsWith("y"))) contactPage(); else if(again !=null && again.toLowerCase().startsWith("n")) { blankLine(); outputTag("h3", "Come play again soon!"); } else { if(goFirst != null && goFirst.toLowerCase().startsWith("n")) board = emptyBoard; gamePage(board); } out.println("</body></html>"); } /* Called by the service() method above to output the Javascript function used that checks if yes or no correctly typed by a user in an input field of a given form */ protected void outputYNFunction() { out.println("function checkYN(response)"); out.println("{"); out.println(" var ans = response.toLowerCase()"); out.print(" if(ans =='y' || ans == 'yes' ||"); out.println(" ans=='n' || ans == 'no') return true;"); out.println("alert('Must enter y, yes, n, or no.')"); out.println(" return false;"); out.println("}"); } /* Called by the service() method above to output the Javascript function used that checks if the user entered a legal move */ protected void outputCheckMoveFunction() { out.println("function checkMove(moveX, moveY, board)"); out.println("{"); out.print(" if(moveX < '0' || moveX > '2' ||"); out.println(" moveY <'0' || moveY > '2') "); out.println(" {"); out.println(" alert('Values must be between 0 and 2.')"); out.println(" return false;"); out.println(" }"); out.println(" var loc = (moveX*"+boardSize+"+1*moveY)"); out.println(" if(board.charAt(loc) == '-')"); out.println(" return true;"); out.println(" alert('Must choose an empty square')"); out.println(" return false;"); out.println("}"); } /* If no data was sent to the servlet then we output the HTML below. */ protected void contactPage() { setAlign("center"); outputTag("h4", "Welcome to the Tic-tac-toe game!"); out.println("<form method=\"POST\" action=\"TicTacToe\""+ " onsubmit=\"return checkYN(goFirst.value);\" >"); blankLine(); inputTag("Would you like to go first?","text", "goFirst", null, "3", "3"); inputTag(null,"submit", null, null, null, null); out.println("</form>"); } /* This function computes the computer's move, gets the resulting board which it draws using HTML. It also check to see if anyone has won the game and outputs the appropriate page if so. @param board - current game board before computer's move */ protected void gamePage(String board) { if(!winO) board = makeMove(board); if(winO || winX || board.indexOf("-") == -1) { endGamePage(); return; } outputTag("h4", "You are playing O."); outputBoard(board); out.println("<form method=\"POST\" action=\"TicTacToe\""+ " onsubmit=\"return checkMove(moveX.value,"+ " moveY.value, '"+board+"');\" >"); blankLine(); inputTag("Enter row value for move: ","text", "moveX", null, "1", "1"); inputTag("Enter column value for move: ","text", "moveY", null, "1", "1"); inputTag(null,"hidden", "board", board, null, null); inputTag(null,"submit", null, null, null, null); out.println("</form>"); } /* Outputs the HTML to draw the game board passed to it. @param board - game board to be drawn */ protected void outputBoard(String board) { out.println("<table border=\"2\" align=\""+align+"\">"); int column = 0; for(int i=0; i < board.length(); i++) { if(column == 0) out.println("<tr>"); out.println("<td>"+board.charAt(i)+"</td>"); column++; if(column == boardSize) { column = 0; out.println("</tr>"); } } out.println("</table>"); } /* Apply the given players move to the board and return the result @param player - whose turn it is @param move - to be applied to the board @param board - current game board @return result of applying move to board */ protected String applyMove(String player, int move, String board) { if(move < 0 || move >= board.length()) return board; String start = board.substring(0, move); String end = board.substring(move + 1); return start+player+end; } /* Calculates a next move for the computer (looks for first open square). @param board - the board to look for a move in @return - resulting board after move */ protected String makeMove(String board) { if(board == null) return emptyBoard; int move = board.indexOf("-"); board = applyMove("X", move, board); winX = gameOver(board, move); return board; } /* Return true if move is a winning move in the board. @param board - board to check win in @param move - move to check to see if caused win @return - whether someone won */ protected boolean gameOver(String board, int move) { if(board == null) return false; if(checkHorizontal(board,move)) return true; if(checkVertical(board,move)) return true; if(checkDiagonal(board,move)) return true; return false; } /* Used to check horizontal wins @param board - board to check win in @param move - move to check to see if caused win @return - if win */ protected boolean checkHorizontal(String board, int move) { char movePlayer = board.charAt(move); int leftBorder = move - (move%boardSize); int rightBorder = leftBorder+ boardSize; int cnt = 0; for(int i= leftBorder; i < rightBorder; i++) { if(board.charAt(i) == movePlayer) cnt++; else cnt = 0; if(cnt == toWin) return true; } return false; } /* Used to check vertical wins @param board - board to check win in @param move - move to check to see if caused win @return - if win */ protected boolean checkVertical(String board, int move) { char movePlayer = board.charAt(move); int topBorder = move%boardSize; int bottomBorder = topBorder -boardSize +boardSize*boardSize; int cnt = 0; for(int i= topBorder; i <= bottomBorder; i+=boardSize) { if(board.charAt(i) == movePlayer) cnt++; else cnt =0; if(cnt == toWin) return true; } return false; } /* Used to check diagonal wins @param board - board to check win in @param move - move to check to see if caused win @return - if win */ protected boolean checkDiagonal(String board, int move) { char movePlayer = board.charAt(move); int col = move%boardSize; int row = move/boardSize; int topLeft; if(row <= col) topLeft = col - row; else topLeft = boardSize*(row - col); int rightCol = boardSize - col -1; int topRight; if(row <= rightCol) topRight = rightCol - row; else topRight = boardSize*(row - rightCol)-1; int cnt=0; for(int i= topLeft; i <= boardSize*boardSize-1; i+=boardSize+1) { if(board.charAt(i) == movePlayer) cnt++; else cnt =0; if(cnt == toWin) return true; } cnt=0; for(int i= topRight; i <= boardSize*boardSize-1; i+=boardSize-1) { if(board.charAt(i) == movePlayer) cnt++; else cnt =0; if(cnt == toWin) return true; } return false; } /* Used to output the HTML page for when the game ends */ protected void endGamePage() { if(winO) outputTag("h4", "You won!"); else if(winX) outputTag("h4", "I won!"); else outputTag("h4", "We tied!"); out.println("<form method=\"POST\" action=\"TicTacToe\""+ " onsubmit=\"return checkYN(again.value);\" >"); blankLine(); inputTag("Would you like to play again?","text", "again", null, "3", "3"); out.println("</form>"); } /* Outputs HTML that simulates skipping a line */ protected void blankLine() { out.println("<p> </p>"); } /* Sets whether HTML output should be aligned to the left, right, or center @param a - is the direction */ protected void setAlign(String a) { align=a; } /* Used to output content between tags of the given type For instance, if type is h2 and content is hi might get <h2 style="text-align: left>hi</h2> output @param type - type of the enclosing tag @param content - content between tags */ protected void outputTag(String type, String content) { out.println("<"+type+" style=\"text-align:"+align+"\" >"); out.println(content); out.println("</"+type+">"); } /* Used to output a form input tag together with a comment @param comment - text of comment output with input tag @param type - type attribute of input tag For example, text @param name - name of input tag @param value - value of input tag @param size - size in chars of tag @param maxLength - maximum number of chars in tag. */ protected void inputTag(String comment, String type, String name, String value, String size, String maxLength) { out.println("<table align=\""+align+"\">"); if(comment !=null) out.println("<tr><td>"+comment+"</td>"); out.print("<td><input"); if(type != null) out.print(" type=\""+type+"\""); if(name != null) out.print(" name=\""+name+"\""); if(value != null) out.print(" value=\""+value+"\""); if(size != null) out.print(" size=\""+size+"\""); if(maxLength != null) out.println(" maxlength=\""+maxLength+"\" />"); out.println("</td></tr></table></div>"); } public String gameTitle = "TicTacToe"; //title of each page output public String emptyBoard = "---------"; // how empty board represented public static final int boardSize =3; // size of game board public static final int toWin = 3; // number in a row to win protected PrintWriter out; //writes to browser protected String align; // determines left, right, center align of text protected boolean winO; // has Y won? protected boolean winX; // has X won? } |