So, bassicly i got my program working, but the main problem i have is that when a player makes move in program, it doesn't man X or O on the playborad, but keeps it in mind. I need to mark them, so that user could se where he made his move. I would be very thankful if someone could help me fix this - > code below:
The server
The clientimport java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; public class TicTacToeServer { /** * Runs the application. Pairs up clients that connect. */ public static void main(String[] args) throws Exception { ServerSocket listener = new ServerSocket(8901); System.out.println("Tic Tac Toe Server is Running"); try { while (true) { Game game = new Game(); Game.Player playerX = game.new Player(listener.accept(), 'X'); Game.Player playerO = game.new Player(listener.accept(), 'O'); playerX.setOpponent(playerO); playerO.setOpponent(playerX); game.currentPlayer = playerX; playerX.start(); playerO.start(); } } finally { listener.close(); } } } /** * A two-player game. */ class Game { /** * A board has nine squares. Each square is either unowned or * it is owned by a player. So we use a simple array of player * references. If null, the corresponding square is unowned, * otherwise the array cell stores a reference to the player that * owns it. */ private Player[] board = { null, null, null, null, null, null, null, null, null}; /** * The current player. */ Player currentPlayer; /** * Returns whether the current state of the board is such that one * of the players is a winner. */ public boolean hasWinner() { return (board[0] != null && board[0] == board[1] && board[0] == board[2]) ||(board[3] != null && board[3] == board[4] && board[3] == board[5]) ||(board[6] != null && board[6] == board[7] && board[6] == board[8]) ||(board[0] != null && board[0] == board[3] && board[0] == board[6]) ||(board[1] != null && board[1] == board[4] && board[1] == board[7]) ||(board[2] != null && board[2] == board[5] && board[2] == board[8]) ||(board[0] != null && board[0] == board[4] && board[0] == board[8]) ||(board[2] != null && board[2] == board[4] && board[2] == board[6]); } /** * Returns whether there are no more empty squares. */ public boolean boardFilledUp() { for (int i = 0; i < board.length; i++) { if (board[i] == null) { return false; } } return true; } /** * Called by the player threads when a player tries to make a * move. This method checks to see if the move is legal: that * is, the player requesting the move must be the current player * and the square in which she is trying to move must not already * be occupied. If the move is legal the game state is updated * (the square is set and the next player becomes current) and * the other player is notified of the move so it can update its * client. */ public synchronized boolean legalMove(int location, Player player) { if (player == currentPlayer && board[location] == null) { board[location] = currentPlayer; currentPlayer = currentPlayer.opponent; currentPlayer.otherPlayerMoved(location); return true; } return false; } /** * The class for the helper threads in this multithreaded server * application. A Player is identified by a character mark * which is either 'X' or 'O'. For communication with the * client the player has a socket with its input and output * streams. Since only text is being communicated we use a * reader and a writer. */ class Player extends Thread { char mark; Player opponent; Socket socket; BufferedReader input; PrintWriter output; /** * Constructs a handler thread for a given socket and mark * initializes the stream fields, displays the first two * welcoming messages. */ public Player(Socket socket, char mark) { this.socket = socket; this.mark = mark; try { input = new BufferedReader( new InputStreamReader(socket.getInputStream())); output = new PrintWriter(socket.getOutputStream(), true); output.println("WELCOME " + mark); output.println("MESSAGE Waiting for opponent to connect"); } catch (IOException e) { System.out.println("Player died: " + e); } } /** * Accepts notification of who the opponent is. */ public void setOpponent(Player opponent) { this.opponent = opponent; } /** * Handles the otherPlayerMoved message. */ public void otherPlayerMoved(int location) { output.println("OPPONENT_MOVED " + location); output.println( hasWinner() ? "DEFEAT" : boardFilledUp() ? "TIE" : ""); } /** * The run method of this thread. */ public void run() { try { // The thread is only started after everyone connects. output.println("MESSAGE All players connected"); // Tell the first player that it is her turn. if (mark == 'X') { output.println("MESSAGE Your move"); } // Repeatedly get commands from the client and process them. while (true) { String command = input.readLine(); if (command.startsWith("MOVE")) { int location = Integer.parseInt(command.substring(5)); if (legalMove(location, this)) { output.println("VALID_MOVE"); output.println(hasWinner() ? "VICTORY" : boardFilledUp() ? "TIE" : ""); } else { output.println("MESSAGE ?"); } } else if (command.startsWith("QUIT")) { return; } } } catch (IOException e) { System.out.println("Player died: " + e); } finally { try {socket.close();} catch (IOException e) {} } } } }
import java.awt.Color; import java.awt.GridLayout; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; public class TicTacToeClient { private JFrame frame = new JFrame("Tic Tac Toe"); private JLabel messageLabel = new JLabel(""); private ImageIcon icon; private ImageIcon opponentIcon; private Square[] board = new Square[9]; private Square currentSquare; private static int PORT = 8901; private Socket socket; private BufferedReader in; private PrintWriter out; /** * Constructs the client by connecting to a server, laying out the * GUI and registering GUI listeners. */ public TicTacToeClient(String serverAddress) throws Exception { // Setup networking socket = new Socket(serverAddress, PORT); in = new BufferedReader(new InputStreamReader( socket.getInputStream())); out = new PrintWriter(socket.getOutputStream(), true); // Layout GUI messageLabel.setBackground(Color.lightGray); frame.getContentPane().add(messageLabel, "South"); JPanel boardPanel = new JPanel(); boardPanel.setBackground(Color.black); boardPanel.setLayout(new GridLayout(3, 3, 2, 2)); for (int i = 0; i < board.length; i++) { final int j = i; board[i] = new Square(); board[i].addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { currentSquare = board[j]; out.println("MOVE " + j);}}); boardPanel.add(board[i]); } frame.getContentPane().add(boardPanel, "Center"); } public void play() throws Exception { String response; try { response = in.readLine(); if (response.startsWith("WELCOME")) { char mark = response.charAt(8); icon = new ImageIcon(mark == 'X' ? "x.gif" : "o.gif"); opponentIcon = new ImageIcon(mark == 'X' ? "o.gif" : "x.gif"); frame.setTitle("Tic Tac Toe - Player " + mark); } while (true) { response = in.readLine(); if (response.startsWith("VALID_MOVE")) { messageLabel.setText("Valid move, please wait"); currentSquare.setIcon(icon); currentSquare.repaint(); } else if (response.startsWith("OPPONENT_MOVED")) { int loc = Integer.parseInt(response.substring(15)); board[loc].setIcon(opponentIcon); board[loc].repaint(); messageLabel.setText("Opponent moved, your turn"); } else if (response.startsWith("VICTORY")) { messageLabel.setText("You win"); break; } else if (response.startsWith("DEFEAT")) { messageLabel.setText("You lose"); break; } else if (response.startsWith("TIE")) { messageLabel.setText("You tied"); break; } else if (response.startsWith("MESSAGE")) { messageLabel.setText(response.substring(8)); } } out.println("QUIT"); } finally { socket.close(); } } private boolean wantsToPlayAgain() { int response = JOptionPane.showConfirmDialog(frame, "Want to play again?", "Tic Tac Toe is Fun Fun Fun", JOptionPane.YES_NO_OPTION); frame.dispose(); return response == JOptionPane.YES_OPTION; } /** * Graphical square in the client window. Each square is * a white panel containing. A client calls setIcon() to fill * it with an Icon, presumably an X or O. */ static class Square extends JPanel { JLabel label = new JLabel((Icon)null); public Square() { setBackground(Color.white); add(label); } public void setIcon(Icon icon) { label.setIcon(icon); } } /** * Runs the client as an application. */ public static void main(String[] args) throws Exception { while (true) { String serverAddress = (args.length == 0) ? "localhost" : args[1]; TicTacToeClient client = new TicTacToeClient(serverAddress); client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); client.frame.setSize(240, 160); client.frame.setVisible(true); client.frame.setResizable(false); client.play(); if (!client.wantsToPlayAgain()) { break; } } } }