Chris Pollett > Old Classes >
CS174

( Print View )

Grades: [Sec1]  [Sec2]

Submit: [Sec1]  [Sec2]

Course Info:
  [Texts & Links]
  [Topics]
  [Grading]
  [HW Info]
  [Exam Info]
  [Regrades]
  [Honesty]
  [Announcements]

HW Assignments:
  [Hw1]  [Hw2]  [Hw3]
  [Hw4]  [Hw5]

Practice Exams:
  [Mid1]  [Mid2]  [Final]

                            












HW3 Solutions Page

Return to homework 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?   
}