// // Othecko 1.1 // // Steve Matuszek // Jack Freelander // University of North Carolina at Chapel Hill // // // OtheckoApplet.java // Steve Matuszek 1.0 // // // This is our applet class, which will present the actual // game interface to the user. In our proof-of-concept tic-tac-toe // game, it is a very simple applet: it displays messages, displays // the tic-tac-toe board as an array of buttons, and has a button // for submitting a move. // // It is not threaded, so it will not receive any game updates unless // it is waiting for them, which it only does at startup and after the // user has submitted a move! Be careful of this. // // Like GameState, this class is an EXAMPLE, not an extensible // interface. It has to know a fair amount about sending MessageObjects // and so forth. Ideally, you would wrap all that up in another class, // but we did not do that for our proof-of-concept. // // The parameters given in the tag will tell this applet // where to connect to. Therefore, it doesn't have to worry about // whether it's connecting to a MiddleMan or directly to the server; // the protocol is the same. // import java.util.*; import java.io.*; import java.net.*; import java.awt.*; import java.awt.event.*; import java.applet.*; public class OtheckoApplet extends Applet implements ActionListener { // ------- Sockets and I/O Socket mySocket; InetAddress myAddress, hostAddress; InputStream myInputStream; ObjectInputStream myOIS; OutputStream myOutputStream; ObjectOutputStream myOOS; String myHostName; int hostPort; ServerSocket inSocket; int inPort; RemoteSystem inRemoteSystem; // ------- Game stuff boolean waitingForState; boolean startedUp; GameState gamestate; MessageObject gamemessage; Vote myVote; // ------- AWT components String currentStatus, currentStatus2; Graphics g; TextArea statuswindow; Button box[][]; Button submitButton; Panel playingsurface; Label statusline; int previ, prevj, curri, currj; Color lightGreen; // ----------------- public void init() { lightGreen = new Color(128,192,128); int i, j; //Graphics gtemp = getGraphics(); //g = gtemp.create(); statuswindow = new TextArea("STATUS\n", 50, 50); playingsurface = new Panel(new GridLayout(3,3,3,3)); statusline = new Label("Welcome to Othecko!"); submitButton = new Button("START"); submitButton.setBackground(Color.magenta); submitButton.setForeground(Color.white); submitButton.addActionListener(this); this.setLayout(new BorderLayout(8,8)); this.add(playingsurface, "Center"); this.add(statuswindow, "West"); this.add(statusline, "North"); this.add(submitButton, "South"); box = new Button[3][3]; for (i=0; i<3; i++) { for (j=0; j<3; j++) { //box[i][j] = new Button(" " + (3*i + j)); box[i][j] = new Button(); playingsurface.add(box[i][j]); box[i][j].addActionListener(this); } } showandlogStatus("Getting local address..."); try { myAddress = InetAddress.getLocalHost(); myHostName = myAddress.getHostName(); showandlogStatus("My address is " + myAddress); } catch (UnknownHostException e) { showandlogStatus("Could not find an IP address."); } hostPort = Integer.parseInt(getParameter("Port")); try { // System.out.println("HostAddress = " + // getParameter("HostAddress")); hostAddress = InetAddress.getByName(getParameter("HostAddress")); showandlogStatus("Got host address " + hostAddress + ":" + hostPort); } catch (UnknownHostException e) { showandlogStatus("Couldn't get host address: " + e.getMessage()); } } public void start() { waitingForState = true; startedUp = false; previ = -1; prevj = -1; showandlogStatus("Press the purple Start button to start."); } public void actionPerformed(ActionEvent e) { if (waitingForState && startedUp) { showandlogStatus( "You can't do anything until we get the next GameState."); return; } //logStatus("Got action event: " + e); if (e.getSource() == submitButton) { if (startedUp) { sendVote(); } else { submitButton.setBackground(Color.pink); submitButton.setForeground(Color.black); submitButton.setLabel("Waiting for connection..."); startGameSocket(); } } else for (int i=0; i<3; i++) { for (int j=0; j<3; j++) { if (e.getSource() == box[i][j]) { handleButton(i,j); i = 10; j = 10; } } } //logStatus(e.getSource().toString()); //startGameSocket(); } private void handleButton(int i, int j) { try { if (previ != -1) { gamestate.setValue('.', previ, prevj); } previ = i; prevj = j; gamestate.setValue('c', i, j); displayGameState(); } catch (GameException ge) { showandlogStatus("Game error!: " + ge); } } private void startListeningSocket() throws IOException { inSocket = new ServerSocket(0, 10); inPort = inSocket.getLocalPort(); inRemoteSystem = new RemoteSystem(myAddress, inPort); showandlogStatus("My RemoteSystem object looks like " + inRemoteSystem); } private void startGameSocket() { try { showandlogStatus("Opening socket to listen on..."); startListeningSocket(); showandlogStatus("Opened listening socket on port " + inPort + "."); // mySocket = new Socket(hostAddress, hostPort); // showandlogStatus("Socket opened. Subscribing..."); showandlogStatus("Subscribing..."); sendSubscription(); receiveGameState(); showandlogStatus("Done trying to receive GameState."); startedUp = true; submitButton.setLabel("Submit this move"); submitButton.setBackground(Color.lightGray); } catch (Exception e) { showandlogStatus("Couldn't connect: " + e.getMessage()); } try { mySocket.close(); logStatus("Closed socket."); } catch (Exception e) { showandlogStatus("Error closing socket: " + e.getMessage()); } } public void sendSubscription() throws Exception { showandlogStatus("Building subscription request..."); MessageObject subscribeMessage = new MessageObject(null, MessageObject.SUBSCRIBE, inRemoteSystem); sendMessage(subscribeMessage); waitingForState = true; showandlogStatus("Waiting for a new state..."); } public void sendVote() { if (previ != -1) { try { myVote = new Vote(previ, prevj); previ = -1; prevj = -1; MessageObject voteMessage = new MessageObject(myVote, MessageObject.VOTE, inRemoteSystem); sendMessage(voteMessage); hangUp(); waitingForState = true; showandlogStatus("Waiting for a new state..."); receiveGameState(); } catch (Exception e) { showandlogStatus("Problem sending vote: " + e); } } else { showandlogStatus("You must pick a move first!"); } } private void sendMessage(MessageObject mo) throws Exception { showandlogStatus("Trying to reach host..."); mySocket = new Socket(hostAddress, hostPort); showandlogStatus("Host reached, trying to send message [" + mo + "]"); myOutputStream = mySocket.getOutputStream(); myOOS = new ObjectOutputStream(myOutputStream); showandlogStatus("Opened ObjectOutputStream..."); myOOS.writeObject(mo); showandlogStatus("Wrote message..."); myOOS.flush(); //myOOS.close(); //showandlogStatus("Flushed and closed stream..."); //myOutputStream.close(); //showandlogStatus("Flushed and closed the other stream..."); //mySocket.close(); //showandlogStatus("Closed connection."); /* catch (IOException ioe) { showandlogStatus("I/O error: " + ioe.getMessage()); } */ } private void hangUp() throws Exception { myOOS.flush(); myOOS.close(); showandlogStatus("Flushed and closed stream..."); myOutputStream.close(); showandlogStatus("Flushed and closed the other stream..."); mySocket.close(); showandlogStatus("Closed connection."); } public void receiveGameState() { //connection = mySocket.accept(); //numConnections++; //System.out.print("Return connection opened. "); try { Socket thisSocket = inSocket.accept(); showandlogStatus("Trying to receive object..."); myInputStream = thisSocket.getInputStream(); myOIS = new ObjectInputStream(myInputStream); gamemessage = (MessageObject) myOIS.readObject(); //gamestate = (GameState) myOIS.readObject(); if (gamemessage.getType() != MessageObject.GAME_STATE) { showandlogStatus("Got a weird message: " + gamemessage); return; } else { showandlogStatus("Got a GameState!"); gamestate = (GameState) gamemessage.getObject(); } showandlogStatus("GameState is: " + gamestate); logStatus ("=========== Game Message ==========="); showandlogStatus(gamestate.getMessage()); logStatus ("==================================="); displayGameState(); waitingForState = false; myOIS.close(); myInputStream.close(); thisSocket.close(); } catch (Exception e) { showandlogStatus("Problem: " + e); } } private void displayGameState() { int i,j; for (i=0; i<3; i++) { for (j=0; j<3; j++) { char val = gamestate.getValueAt(i,j); if (val == 'x') { box[i][j].setLabel("X"); box[i][j].setBackground(Color.red); box[i][j].setEnabled(false); } else if (val == 'o') { box[i][j].setLabel("O"); box[i][j].setBackground(Color.green); box[i][j].setEnabled(false); } else if (val == 'c') { box[i][j].setLabel("O"); box[i][j].setBackground(lightGreen); box[i][j].setEnabled(true); } else if (val == '.') { box[i][j].setLabel(" "); box[i][j].setBackground(Color.lightGray); box[i][j].setEnabled(true); } else { box[i][j].setLabel("????"); box[i][j].setBackground(Color.magenta); box[i][j].setEnabled(true); } } } paint(this.getGraphics()); } private void logStatus(String s) { statuswindow.append(s + "\n"); statuswindow.repaint(); } private void showLineStatus(String s) { statusline.setText(s); statusline.repaint(); } private void showandlogStatus(String s) { showStatus(s); statuswindow.append(s + "\n"); statusline.setText(s); repaint(); } private void writeStatus() { statusline.setText(currentStatus); statuswindow.append(currentStatus + "\n"); // statuswindow.append(currentStatus2 + "\n"); } }