I have the codes written in Java. Since Java is similar to C++, perhaps you could convert them to C++. When you are done, please post the C++ codes into this forum.
There are two files - TicTacToeServer.java and TicTacToeClient.java
1) TicTacToeServer.java
Code:
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import javax.swing.*;
public class TicTacToeServer extends JFrame{
private byte board[];
private JTextArea outputArea;
private Player players[];
private ServerSocket server;
private int currentPlayer;
public TicTacToeServer()
{
super("Tic-Tac-Toce Server");
board = new byte[9];
players = new Player[2];
currentPlayer = 0;
try{
server = new ServerSocket(5000, 2);
}
catch(IOException ioException){
ioException.printStackTrace();
System.exit(1);
}
outputArea = new JTextArea();
getContentPane().add(outputArea, BorderLayout.CENTER);
outputArea.setText("Server awaiting connections\n");
setSize(300,300);
setVisible(true);
}
public void execute()
{
for (int i = 0; i < players.length; i++){
try{
players[i] = new Player(server.accept(), i);
players[i].start();
}
catch(IOException ioException){
ioException.printStackTrace();
System.exit(1);
}
}
synchronized(players[0]){
players[0].setSuspended(false);
players[0].notify();
}
}
public void display(String message)
{
outputArea.append(message + "\n");
}
public synchronized boolean validMove(int location, int player)
{
boolean moveDone = false;
while(player != currentPlayer)
{
try
{
wait();
}
catch(InterruptedException interruptedException)
{
interruptedException.printStackTrace();
}
}
if(!isOccupied(location))
{
board[location] = (byte)(currentPlayer == 0 ? 'X' : '0');
currentPlayer = (currentPlayer + 1) % 2;
players[currentPlayer].otherPlayerMoved(location);
notify();
return true;
}
else
return false;
}
public boolean isOccupied(int location)
{
if(board[location] == 'X' || board[location] == 'O')
return true;
else
return false;
}
public boolean gameOver()
{
return false;
}
public static void main(String args[])
{
TicTacToeServer application = new TicTacToeServer();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.execute();
}
private class Player extends Thread{
private Socket connection;
private DataInputStream input;
private DataOutputStream output;
private int playerNumber;
private char mark;
protected boolean suspended = true;
public Player(Socket socket, int number)
{
playerNumber = number;
mark = (playerNumber == 0 ? 'X' : 'O');
connection = socket;
try{
input = new DataInputStream(connection.getInputStream());
output = new DataOutputStream(connection.getOutputStream());
}
catch(IOException ioException){
ioException.printStackTrace();
System.exit(1);
}
}
public void otherPlayerMoved(int location)
{
try{
output.writeUTF("Opponent moved");
output.writeInt(location);
}
catch(IOException ioException){
ioException.printStackTrace();
}
}
public void run()
{
try{
display("Player " + (playerNumber == 0 ? 'X' : 'O') + " connected");
output.writeChar(mark);
output.writeUTF("Player " + (playerNumber == 0 ? "X connected\n" : "O connected, please wait\n"));
if(mark == 'X')
{
output.writeUTF("Waiting for another player");
try
{
synchronized(this)
{
while(suspended)
wait();
}
}
catch(InterruptedException exception)
{
exception.printStackTrace();
}
output.writeUTF("Other player connected. Your move.");
}
while(! gameOver())
{
int location = input.readInt();
if(validMove(location, playerNumber))
{
display("loc: " + location);
output.writeUTF("Valid move.");
}
else
output.writeUTF("Invalid move, try again.");
}
connection.close();
}
catch(IOException ioException)
{
ioException.printStackTrace();
System.exit(1);
}
}
public void setSuspended(boolean status)
{
suspended = status;
}
}
}
2) TicTacToeClient.java
Code:
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import javax.swing.*;
public class TicTacToeClient extends JApplet implements Runnable
{
private JTextField idField;
private JTextArea displayArea;
private JPanel boardPanel, panel2;
private Square board[][], currentSquare;
private Socket connection;
private DataInputStream input;
private DataOutputStream output;
private Thread outputThread;
private char myMark;
private boolean myTurn;
public void init()
{
Container container = getContentPane();
displayArea = new JTextArea(4,30);
displayArea.setEditable(false);
container.add(new JScrollPane(displayArea), BorderLayout.SOUTH);
boardPanel = new JPanel();
boardPanel.setLayout(new GridLayout(3,3,0, 0));
board = new Square[3][3];
for(int row = 0; row < board.length; row++)
{
for(int column = 0; column < board[row].length; column++)
{
board[row][column] = new Square(' ', row * 3 + column);
boardPanel.add(board[row][column]);
}
}
idField = new JTextField();
idField.setEditable(false);
container.add(panel2, BorderLayout.NORTH);
panel2 = new JPanel();
panel2.add(boardPanel, BorderLayout.CENTER);
container.add(panel2, BorderLayout.CENTER);
}
public void start()
{
try
{
connection = new Socket(InetAddress.getByName("127.0.0.1"), 5000);
input = new DataInputStream(connection.getInputStream());
output = new DataOutputStream(connection.getOutputStream());
}
catch(IOException ioException)
{
ioException.printStackTrace();
}
outputThread = new Thread(this);
outputThread.start();
}
public void run()
{
try
{
myMark = input.readChar();
idField.setText("You are player \"" + myMark + "\"");
myTurn = (myMark == 'X' ? true : false);
}
catch(IOException ioException)
{
ioException.printStackTrace();
}
while(true)
{
try
{
String message = input.readUTF();
processMessage(message);
}
catch(IOException ioException)
{
ioException.printStackTrace();
}
}
}
public void processMessage(String message)
{
if(message.equals("Valid move." ))
{
displayArea.append("Valid move, please wait. \n");
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
currentSquare.setMark(myMark);
}
}
);
}
else if(message.equals("Invalid move, try again" ))
{
displayArea.append(message + "\n" );
myTurn = true;
}
else if(message.equals("Opponent moved" ))
{
try
{
final int location = input.readInt();
SwingUtilities.invokeLater(
new Runnable()
{
public void run()
{
int row = location / 3;
int column = location % 3;
board[row][column].setMark((myMark == 'X' ? 'O' : 'X'));
displayArea.append("Opponent moved. Your turn. \n");
}
}
);
myTurn = true;
}
catch(IOException ioException)
{
ioException.printStackTrace();
}
}
else
displayArea.append(message + "\n" );
displayArea.setCaretPosition(displayArea.getText().length());
}
public void sendClickedSquare(int location)
{
if(myTurn)
{
try
{
output.writeInt(location);
myTurn = false;
}
catch(IOException ioException)
{
ioException.printStackTrace();
}
}
}
public void setCurrentSquare(Square square)
{
currentSquare = square;
}
private class Square extends JPanel
{
private char mark;
private int location;
public Square(char squareMark, int squareLocation)
{
mark = squareMark;
location = squareLocation;
addMouseListener
(
new MouseAdapter()
{
public void mouseReleased(MouseEvent e)
{
setCurrentSquare(Square.this);
sendClickedSquare(getSquareLocation());
}
}
);
}
public Dimension getPreferredSize()
{
return new Dimension(30, 30);
}
public Dimension getMinimumSize()
{
return getPreferredSize();
}
public void setMark(char newMark)
{
mark = newMark;
repaint();
}
public int getSquareLocation()
{
return location;
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawRect(0,0, 29,29);
g.drawString(String.valueOf(mark), 11, 20);
}
}
}