Hi,

I'm working on an assignment where we have to have a client and server sending each other an integer that represents a noughts and crosses board. I had it working by simply sending back and forth the entire NoughtsAndCrosses class, but now we need to do it just using the integers in the GameData struct using the individual bits. This is where I've gotten lost, here is my code, I'm not looking for straight up answers since I need to learn for myself, maybe just some hints to nudge me in the right direction?

I think there is a problem with my logic in the Play function of the BitNoughtsAndCrosses class and I think I've messed up the sending and recieving.

Server Code:

#include "stdafx.h"
#include <stdio.h>
#include <winsock2.h>
#include <iostream>
#include <ctime> 
#include <math.h>
#include <ws2tcpip.h>



using namespace std;

		const int bits[9] = {1,2,4,8,16,32,64,128,256};

//#define NORMAL 1
#define BITWISE 1


// Noughts and Crosses (Tic Tack Toe) game
class NoughtsAndCrosses{
protected:
	// 3 by 3 board is represented as a one dimensional array
	char board[9];
	// Players symbols are either X or O
	char playerSymbol;
	char aiSymbol;
	// Game state
	bool playerWin,aiWin,draw;
	// If there is a winner or a draw update the state
	bool CheckWin(char symbol){	
		bool won = false;
		// Is there a winner?
		// Check horizontal 
		if (board[0] == symbol && board[1] == symbol && board[2] == symbol) won = true;
		if (board[3] == symbol && board[4] == symbol && board[5] == symbol) won =  true;
		if (board[6] == symbol && board[7] == symbol && board[8] == symbol) won =  true;
		// Check vertical
		if (board[0] == symbol && board[3] == symbol && board[6] == symbol) won =  true;
		if (board[1] == symbol && board[4] == symbol && board[7] == symbol) won =  true;
		if (board[2] == symbol && board[5] == symbol && board[8] == symbol) won =  true;
		// Check diagonals
		if (board[0] == symbol && board[4] == symbol && board[8] == symbol) won =  true;
		if (board[2] == symbol && board[4] == symbol && board[6] == symbol) won =  true;
		// If there is a winner who won?
		if (won){
			if (symbol == aiSymbol) aiWin = true;
			else playerWin = true;
			return true;
		}
		// If no one has won then check to see if it is a draw
		for(int n=0;n<9;n++)
			if (board[n] == ' ') return false;
		draw = true;
		return true;
	}
public:
	NoughtsAndCrosses(){
		for(int n=0;n<9;n++)
			board[n] = ' ';
		playerSymbol = 'X';
		aiSymbol = 'O';
		playerWin = aiWin  = draw = false;
	}
	bool IsFinished(){
		if (playerWin || aiWin || draw) return true;
		else return false;
	}
	void DisplayWinner(){
		if (playerWin)
			cout << "\n The Player has won \n";
		else if (aiWin)
			cout << "\n The AI has won \n";
		else
			cout << "\n Its a draw \n";
	}
	bool Play(char symbol, int pos){
		// Ensure the position is free
		if(board[pos]== ' '){
			board[pos] = symbol;
			CheckWin(symbol);
			return true;
		}
		else return false;
	}
	void AIPlay(){
		srand((unsigned)time(0));
		int index;
		do{
			index = rand();
			index = index % 9;
		}
		while(! Play('O', index));
	}
	void Dump(){
		cout << board[0] << " | " << board[1] << " | " << board[2] << "\n";
		cout << "--------\n";
		cout << board[3] << " | " << board[4] << " | " << board[5] << "\n";
		cout << "--------\n";
		cout << board[6] << " | " << board[7] << " | " << board[8] << "\n";
	}
	// Transmit the whole object to the opponent
	void Send(SOCKET s){
		
		char buffer[sizeof(NoughtsAndCrosses)];
		memcpy(buffer,this,sizeof(NoughtsAndCrosses));
		send(s,buffer,sizeof(NoughtsAndCrosses), 0);
	}
};




// Contains game data to be transmitted
struct GameData{
	int playerData,aiData;
};

class BitNoughtsAndCrosses: public NoughtsAndCrosses
{

	public:

		GameData boardStat;

		BitNoughtsAndCrosses(){
		for(int n=0;n<9;n++)
			board[n] = ' ';
		playerSymbol = 'X';
		aiSymbol = 'O';
		playerWin = aiWin  = draw = false;
	    }

		void Send(SOCKET s)
		{
			send(s,(char*)boardStat.aiData,sizeof(boardStat.aiData), 0);
		}

		bool Play(char symbol, int pos){
		// Ensure the position is free
		if(board[pos]== ' '){
			boardStat.aiData = boardStat.aiData & bits[pos];
			board[pos] = symbol;
			CheckWin(symbol);
			return true;
		}
		else return false;
		}	

		void AIPlay(){
		srand((unsigned)time(0));
		int index;
		do{
			index = rand();
			index = index % 9;
			boardStat.aiData = boardStat.aiData & bits[index];
		}
		while(! Play('O', index));
	}

};


int main(int argc, char* argv[]){
	
	SOCKADDR_STORAGE from;
	int retval,fromlen,socket_type;
	char servstr[NI_MAXSERV], hoststr[NI_MAXHOST];


	SOCKET serverSocket, acceptSocket;
	int port = 55555;
	WSADATA wsaData;
	int wsaerr;

	WORD wVersionRequested = MAKEWORD(2, 2);
	wsaerr = WSAStartup(wVersionRequested, &wsaData);
	if (wsaerr != 0){
		 cout << "The Winsock dll not found!" << endl;
		 return 0;
	}
	else{
		 cout << "The Winsock dll found!" << endl;
		 cout << "The status: " << wsaData.szSystemStatus << endl;
	}

	serverSocket = INVALID_SOCKET;
	serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (serverSocket== INVALID_SOCKET){
		cout << "Error at socket(): " <<  WSAGetLastError() << endl;
		WSACleanup();
		return 0;
	}
	else {
		cout << "socket() is OK!" << endl;
	}


	sockaddr_in service;
	service.sin_family = AF_INET;
	service.sin_addr.s_addr = inet_addr("127.0.0.1");
	service.sin_port = htons(port);
	if (bind(serverSocket, (SOCKADDR*)&service, sizeof(service))== SOCKET_ERROR){
		cout << "bind() failed: " <<  WSAGetLastError() << endl;
		closesocket(serverSocket);
		WSACleanup();
		return 0;
	}
	else{
		cout << "bind() is OK!" << endl;
	}

	if (listen(serverSocket, 1) == SOCKET_ERROR)
		cout << "listen(): Error listening on socket " <<  WSAGetLastError()<< endl;
	else
		cout << "listen() is OK, I'm waiting for connections..." << endl;

	fromlen = sizeof(socket_type);
	retval = getsockopt(serverSocket, SOL_SOCKET, SO_TYPE, (char *)&socket_type, &fromlen);
	fromlen = sizeof(from);
	acceptSocket = accept(serverSocket, (SOCKADDR *)&from, &fromlen);

	//acceptSocket = accept(serverSocket, NULL,NULL);
	if (acceptSocket == INVALID_SOCKET){
        cout <<  "accept failed: " << WSAGetLastError() << endl;
		WSACleanup();
		return -1;
	}
	retval = getnameinfo((SOCKADDR *)&from,
                      fromlen,
                      hoststr,
                      NI_MAXHOST,
                      servstr,
                      NI_MAXSERV,
                      NI_NUMERICHOST | NI_NUMERICSERV);
	if (retval != 0){
             cout <<  "getnameinfo failed: " << retval << endl;
	       	WSACleanup();
             return -1;
	}
	cout << "Accepted connection from host " <<  hoststr << " and port " << servstr << endl;
	cout << "Accepted connection" << endl;

	int byteCount = SOCKET_ERROR;
	char msg[50];
	byteCount = recv(acceptSocket, msg, 50,0);
		if(byteCount == SOCKET_ERROR){
		printf("Client: receive() error %ld.\n", WSAGetLastError());
	}
	else{
		printf("Client: sent %ld bytes \n", byteCount);
	}   

	
	int bytesRecv,bytesSend,index;
	int intbuffer = 0;
	char buffer[sizeof(NoughtsAndCrosses)];

#if NORMAL
	NoughtsAndCrosses *game = new NoughtsAndCrosses();
#endif
#if BITWISE
	BitNoughtsAndCrosses *game = new BitNoughtsAndCrosses();
#endif


	while(!(game->IsFinished())){
			//game->Dump();
			
			game->AIPlay();
								
			game->Dump();
			//system("CLS");
			//bytesSend = send(serverSocket,buffer,sizeof(NoughtsAndCrosses), 0);
			game->Send(acceptSocket);

			#if BITWISE
			bytesRecv = recv(acceptSocket,(char*)intbuffer,sizeof(game->boardStat.playerData), 0);
			game->boardStat.playerData = game->boardStat.playerData & intbuffer;
			game->Play('X',bits[intbuffer]);
			cout << "Recieved: " << intbuffer << endl;
			//cout << "AI has completed its move\n";
			#endif

			#if NORMAL
			bytesRecv = recv(acceptSocket, buffer,sizeof(NoughtsAndCrosses), 0);
			memcpy(game, buffer, sizeof(NoughtsAndCrosses));
			//cout << "AI has completed its move\n";
			#endif
			

	}

	game->DisplayWinner();
	system("pause"); 
	WSACleanup();

	return 0;
	
}

Client Code:

#include "stdafx.h"
#include <stdio.h>
#include <winsock2.h>
#include <iostream>
#include <ctime> 
#include <math.h>
//#include <bitset>


using namespace std;

//#define NORMAL 1
#define BITWISE 1

		const int bits[9] = {1,2,4,8,16,32,64,128,256};



// Noughts and Crosses (Tic Tack Toe) game
class NoughtsAndCrosses{

friend class BitNoughtsAndCrosses;

protected:
	// 3 by 3 board is represented as a one dimensional array
	char board[9];
	// Players symbols are either X or O
	char playerSymbol;
	char aiSymbol;
	// Game state
	bool playerWin,aiWin,draw;
	// If there is a winner or a draw update the state
	virtual bool CheckWin(char symbol){	
		bool won = false;
		// Is there a winner?
		// Check horizontal 
		if (board[0] == symbol && board[1] == symbol && board[2] == symbol) won = true;
		if (board[3] == symbol && board[4] == symbol && board[5] == symbol) won =  true;
		if (board[6] == symbol && board[7] == symbol && board[8] == symbol) won =  true;
		// Check vertical
		if (board[0] == symbol && board[3] == symbol && board[6] == symbol) won =  true;
		if (board[1] == symbol && board[4] == symbol && board[7] == symbol) won =  true;
		if (board[2] == symbol && board[5] == symbol && board[8] == symbol) won =  true;
		// Check diagonals
		if (board[0] == symbol && board[4] == symbol && board[8] == symbol) won =  true;
		if (board[2] == symbol && board[4] == symbol && board[6] == symbol) won =  true;
		// If there is a winner who won?
		if (won){
			if (symbol == aiSymbol) aiWin = true;
			else playerWin = true;
			return true;
		}
		// If no one has won then check to see if it is a draw
		for(int n=0;n<9;n++)
			if (board[n] == ' ') return false;
		draw = true;
		return true;
	}
public:
	NoughtsAndCrosses(){
		for(int n=0;n<9;n++)
			board[n] = ' ';
		playerSymbol = 'X';
		aiSymbol = 'O';
		playerWin = aiWin  = draw = false;
	}
	bool IsFinished(){
		if (playerWin || aiWin || draw) return true;
		else return false;
	}
	void DisplayWinner(){
		if (playerWin)
			cout << "\n The Player has won \n";
		else if (aiWin)
			cout << "\n The AI has won \n";
		else
			cout << "\n Its a draw \n";
	}
	virtual bool Play(char symbol, int pos){
		// Ensure the position is free
		if(board[pos]== ' '){
			board[pos] = symbol;
			CheckWin(symbol);
			return true;
		}
		else return false;
	}
	virtual void AIPlay(){
		srand((unsigned)time(0));
		int index;
		do{
			index = rand();
			index = index % 9;
		}
		while(! Play('O', index));
	}
	void Dump(){
		cout << board[0] << " | " << board[1] << " | " << board[2] << "\n";
		cout << "--------\n";
		cout << board[3] << " | " << board[4] << " | " << board[5] << "\n";
		cout << "--------\n";
		cout << board[6] << " | " << board[7] << " | " << board[8] << "\n";
	}
	// Transmit the whole object to the opponent
    void Send(SOCKET s){
		char buffer[sizeof(NoughtsAndCrosses)];
		memcpy(buffer,this,sizeof(NoughtsAndCrosses));
		send(s,buffer,sizeof(NoughtsAndCrosses), 0);
	}
};




// Contains game data to be transmitted
struct GameData{
	int playerData,aiData;
};

class BitNoughtsAndCrosses: public NoughtsAndCrosses
{

	public:

		BitNoughtsAndCrosses(){
		for(int n=0;n<9;n++)
			board[n] = ' ';
		playerSymbol = 'X';
		aiSymbol = 'O';
		playerWin = aiWin  = draw = false;
		}

		GameData boardStat;

		void Send(SOCKET s)
		{
			send(s,(char*)boardStat.playerData,sizeof(boardStat.playerData), 0);
		}

		bool Play(char symbol, int pos){
		// Ensure the position is free
		if(board[pos]== ' '){
			boardStat.playerData = boardStat.playerData & bits[pos];
			cout << boardStat.playerData << endl;
			board[pos] = symbol;
			CheckWin(symbol);
			return true;
		}
		else return false;
		}	

		void AIPlay(){
		srand((unsigned)time(0));
		int index;
		do{
			index = rand();
			index = index % 9;
		}
		while(! Play('O', index));
		boardStat.aiData = boardStat.aiData & bits[index];
	}

};




int main(int argc, char* argv[]){
	SOCKADDR_STORAGE from;
	int retval,fromlen,socket_type;

	SOCKET clientSocket, acceptSocket;
	int port = 55555;
	WSADATA wsaData;
	int wsaerr;
	WORD wVersionRequested = MAKEWORD(2, 2);
	wsaerr = WSAStartup(wVersionRequested, &wsaData);
	if (wsaerr != 0){
		 printf("The Winsock dll not found!\n");
		return 0;
	}
	else{
		 printf("The Winsock dll found!\n");
		 printf("The status: %s.\n", wsaData.szSystemStatus);
	}

	clientSocket = INVALID_SOCKET;
	clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);



	if (clientSocket== INVALID_SOCKET){
		printf("Error at socket(): %ld\n", WSAGetLastError());
		WSACleanup();
		return 0;
	}
	else {
		printf("socket() is OK!\n");
	}

	sockaddr_in clientService;
    clientService.sin_family = AF_INET;
    clientService.sin_addr.s_addr = inet_addr("127.0.0.1");
    clientService.sin_port = htons(port);
    if (connect(clientSocket, (SOCKADDR*)&clientService, sizeof(clientService)) == SOCKET_ERROR){
        printf("Client: connect() - Failed to connect.\n");
        WSACleanup();
        return 0;
    }
    else   {
       printf("Client: connect() is OK.\n");
       printf("Client: Can start sending and receiving data...\n");
    }
	//===============================

	fromlen = sizeof(from);
	acceptSocket = accept(clientSocket, (SOCKADDR *)&from, &fromlen);

	
	//==============================
    int byteCount = SOCKET_ERROR;
	char msg[50] = "Play noughts and crosses";

	byteCount = send(clientSocket, msg, 50, 0);
	if(byteCount == SOCKET_ERROR){
		printf("Client: send() error %ld.\n", WSAGetLastError());
	}
	else{
		printf("Client: sent %ld bytes \n", byteCount);
	}   
		
	//======================================================
		int bytesRecv,bytesSend, index;

	int intbuffer = 0;
	char buffer[sizeof(NoughtsAndCrosses)];

#if NORMAL
	NoughtsAndCrosses *game = new NoughtsAndCrosses();
#endif

#if BITWISE
		BitNoughtsAndCrosses *game = new BitNoughtsAndCrosses();
		while(!(game->IsFinished())){	
		bytesRecv = recv(clientSocket,(char *)intbuffer,sizeof(game->boardStat.aiData), 0);
		game->boardStat.aiData = game->boardStat.aiData & intbuffer;
		cout << "Recieved: " << intbuffer << endl;
		game->Play('O', intbuffer);
		cout << "AI has completed its move\n";
#endif

#if NORMAL
		while(!(game->IsFinished())){	
		bytesRecv = recv(clientSocket,buffer,sizeof(NoughtsAndCrosses), 0);
		memcpy( game, buffer, sizeof(NoughtsAndCrosses));
		cout << "AI has completed its move\n";
#endif

	//while(!(game->IsFinished())){	
		game->Dump();
		
		if (!(game->IsFinished()))
		{
			do{
				cout << "Enter the index ";
				cin >> index;
			}
			while(!game->Play('X',index));
			
			game->Dump();
			system("CLS");
			game->Send(clientSocket);

			
		}
	}
	game->DisplayWinner();
    system("pause");
	WSACleanup();
    return 0;

}

Thanks for any ideas you can offer.

James

Should probably clarify what state the program is in with that code.

Both the client and server compile and run, but the server just plays out the game by itself, and the client doesn't update its board with the data coming through from the server. I put an output to check what data was being sent and recieved, and it always seems to read 0. I tried changing the & operator when in the Play function, which is supposed to turn on one of the bits in boardStat.playerData, to an | but this causes an unhandled exception :S

This article has been dead for over six months. Start a new discussion instead.