/* Java Tic-Tac-Toe Michael W. Olson Jr. CS 476 */ import java.awt.*; import java.net.*; import java.io.*; import corejava.*; // Main Class for Tic Tac Toe Game public class TicTacToe extends Frame { // Constructor for Server Mode public TicTacToe(int port) { Server = new StartServer(port); System.out.println("Server running on " + Server.Address()); System.out.flush(); S = Server.getClientSocket(); turn = 0; StartGame(); } // Constructor for Client Mode public TicTacToe(String host, int port) { try { S = new Socket(host, port); } catch (Exception e) { System.err.println(e); System.exit(1); } turn = 1; StartGame(); } public void StartGame() { int x, y; // Init Variables Yes[0] = 0; Yes[1] = 0; // Fire up the Network Code Net = new NetGame(this, S); Net.start(); // Build the Game Interface markfont = new Font("Helvetica", Font.PLAIN, 100); Board = new Panel(); Board.setLayout(new GridLayout(3, 3)); for(x=0;x<3;x++) for(y=0;y<3;y++) { Square[x][y] = new Button(); Square[x][y].setFont(markfont); Board.add(Square[x][y]); } // Build the Play Again Interface textfont = new Font("Helvetica", Font.PLAIN, 18); PlayAgain = new Panel(); PlayAgain.setLayout(new BorderLayout()); ButtonArea = new Panel(); YesButton = new Button("Yes"); YesButton.setFont(textfont); ButtonArea.add(YesButton); NoButton = new Button("No"); NoButton.setFont(textfont); ButtonArea.add(NoButton); TextLine1 = new Label(); TextLine1.setAlignment(Label.CENTER); TextLine2 = new Label(); TextLine2.setAlignment(Label.CENTER); PlayAgain.add("North", TextLine1); PlayAgain.add("Center", TextLine2); PlayAgain.add("South", ButtonArea); // Set the game in motion add("Center", Board); setCursor(CROSSHAIR_CURSOR); InitBoard(); if (turn == 1) { SetBoardState(1); setTitle("Tic-Tac-Toe Your Turn"); } else { SetBoardState(0); setTitle("Tic-Tac-Toe Other Players Turn"); } resize(400, 400); show(); } // Do Something with System Events public boolean handleEvent(Event evt) { if (evt.id == Event.WINDOW_DESTROY) System.exit(0); return super.handleEvent(evt); } // Handle Button Presses public boolean action(Event evt, Object args) { int i, j, x, y; if ( ((Button) evt.target).getLabel() == " ") { ((Button) evt.target).setLabel("X"); x = -1; y = -1; for (i=0;i<3;i++) for (j=0;j<3;j++) if (Square[i][j] == ((Button) evt.target)) { x = i; y = j; } moves++; Net.Mark(x,y); SetBoardState(0); setTitle("Tic-Tac-Toe Other Players Turn"); winner = 1; CheckWinner(); return true; } if (args.equals("Yes")) { Net.Yes(); if (Yes[1] == 1) { NewGame(); } else { Yes[0] = 1; TextLine1.setText(""); TextLine2.setText("Waiting for other player to respond"); YesButton.disable(); } } if (args.equals("No")) { Net.No(); System.exit(0); } return false; } public void NewGame() { if (turn ==0) turn = 1; else turn = 0; Yes[0] = 0; Yes[1] = 0; InitBoard(); if (turn == 1) { SetBoardState(1); setTitle("Tic-Tac-Toe Your Turn"); } else { SetBoardState(0); setTitle("Tic-Tac-Toe Other Players Turn"); } setCursor(CROSSHAIR_CURSOR); remove(PlayAgain); add("Center", Board); resize(400, 400); // Certain implimentations of Java will not look right if you // don't call show after resizing it. show(); } // Used by Net Code public void MarkSquare(int x, int y, String mark) { Square[x][y].setLabel(mark); } // Turn the appropriate squares either on or off public void SetBoardState(int state) { int x, y; for(x=0;x<3;x++) for(y=0;y<3;y++) if (state == 1) if (Square[x][y].getLabel() == " ") Square[x][y].enable(); else Square[x][y].disable(); else Square[x][y].disable(); } // Clean everything up public void InitBoard() { int x, y; for(x=0;x<3;x++) for(y=0;y<3;y++) Square[x][y].setLabel(" "); moves = 0; } // Figure out if the game is over public void CheckWinner() { int i, j; for(i=0;i<3;i++) { // Check Horizontal Wins if (Square[i][0].getLabel().equals(Square[i][1].getLabel()) && Square[i][1].getLabel().equals(Square[i][2].getLabel()) && !Square[i][2].getLabel().equals(" ")) { GameOver(); return; } // Check Vertical Wins if (Square[0][i].getLabel().equals(Square[1][i].getLabel()) && Square[1][i].getLabel().equals(Square[2][i].getLabel()) && !Square[2][i].getLabel().equals(" ")) { GameOver(); return; } } // Check Top Left to Bottom Right Win if (Square[0][2].getLabel().equals(Square[1][1].getLabel()) && Square[1][1].getLabel().equals(Square[2][0].getLabel()) && !Square[2][0].getLabel().equals(" ")) { GameOver(); return; } // Check Bottom Left to Top Right Win if (Square[0][0].getLabel().equals(Square[1][1].getLabel()) && Square[1][1].getLabel().equals(Square[2][2].getLabel()) && !Square[2][2].getLabel().equals(" ")) { GameOver(); return; } if (moves == 9) { winner = -1; GameOver(); } } // Handle Game Over Stuff public void GameOver() { remove(Board); if (winner == -1) TextLine1.setText("Game is a tie"); if (winner == 0) TextLine1.setText("You Lose!"); if (winner == 1) TextLine1.setText("You Win!"); TextLine2.setText("Would you like to play again?"); YesButton.enable(); setCursor(DEFAULT_CURSOR); add("Center", PlayAgain); setTitle("Tic-Tac-Toe"); resize(250, 150); show(); } // Main Program Logic public static void main(String[] args) { Frame f; if (args.length == 2) { f = new TicTacToe(args[0], Format.atoi(args[1])); } else { if (args.length == 1) { f = new TicTacToe(Format.atoi(args[0])); } else { if (args.length == 0) { f = new TicTacToe(0); } else { System.err.println("Useage:"); System.err.println(""); System.err.println("Server Mode: java TicTacToe"); System.err.println(" or"); System.err.println(" java TicTacToe "); System.err.println(); System.err.println("Client Mode: java TicTacToe "); System.err.println(""); System.exit(1); } } } } private StartServer Server; private Socket S; private NetGame Net; private Font markfont; private Font textfont; private Panel Board; private Panel PlayAgain; private Panel ButtonArea; private Label TextLine1; private Label TextLine2; private Button[][] Square = new Button[3][3]; private Button YesButton, NoButton; public int turn, moves, winner; public int[] Yes = new int[2]; } /* Common Interface for playing over the network */ class NetGame extends Thread { public NetGame(TicTacToe mstr, Socket skt) { s = skt; parent = mstr; try { in = new DataInputStream(s.getInputStream()); out = new DataOutputStream(s.getOutputStream()); } catch (IOException e) { System.err.println(e); System.exit(1); } } // Recieves and acts on net game data public void run() { String Buffer; int x, y; try { Buffer = in.readLine(); while (Buffer != null) { if (Buffer.equals("MARK")) { x = in.readInt(); y = in.readInt(); parent.MarkSquare(x, y, "O"); parent.SetBoardState(1); parent.setTitle("Tic-Tac-Toe Your Turn"); parent.moves++; parent.winner = 0; parent.CheckWinner(); } if (Buffer.equals("YES")) { if (parent.Yes[0] == 1) { parent.NewGame(); } else { parent.Yes[1] = 1; } } if (Buffer.equals("NO")) { System.exit(0); } Buffer = in.readLine(); } // If the other side terminates Pause to allow // NoButton Events to Terminate System, then Exit sleep(100); System.exit(0); } catch (IOException e) { System.err.println(e); System.exit(1); } catch (InterruptedException e) { System.err.println(e); System.exit(1); } } // Sends Board Marking Data public void Mark(int x, int y) { try { out.writeBytes("MARK\n"); out.writeInt(x); out.writeInt(y); } catch (IOException e) { System.err.println(e); System.exit(1); } } // Send Yes Messsage public void Yes() { try { out.writeBytes("YES\n"); } catch (IOException e) { System.err.println(e); System.exit(1); } } // Send No Messsage public void No() { try { out.writeBytes("NO\n"); } catch (IOException e) { System.err.println(e); System.exit(1); } } private Socket s; private TicTacToe parent; private DataInputStream in; private DataOutputStream out; } // Server specific startup code class StartServer { // Constructor public StartServer(int port) { try { S = new ServerSocket(port); } catch (IOException e) { System.err.println(e); System.exit(1); } } public Socket getClientSocket() { try { Client = S.accept(); } catch (IOException e) { System.err.println(e); System.exit(1); } return Client; } public String Address() { String Result = new String(""); try { Result = InetAddress.getLocalHost() + " " + S.getLocalPort(); } catch (UnknownHostException e) { System.err.println(e); System.exit(1); } return Result; } private ServerSocket S; private Socket Client; }