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[]){

int retval,fromlen,socket_type;
char servstr[NI_MAXSERV], hoststr[NI_MAXHOST];

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

WORD wVersionRequested = MAKEWORD(2, 2);
if (wsaerr != 0){
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;
}

service.sin_family = AF_INET;
service.sin_port = htons(port);
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;
}
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){
}
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[]){
int retval,fromlen,socket_type;

SOCKET clientSocket, acceptSocket;
int port = 55555;
int wsaerr;
WORD wVersionRequested = MAKEWORD(2, 2);
if (wsaerr != 0){
return 0;
}
else{
printf("The Winsock dll found!\n");
}

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");
}

clientService.sin_family = AF_INET;
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

Be a part of the DaniWeb community

We're a friendly, industry-focused community of 1.18 million developers, IT pros, digital marketers, and technology enthusiasts learning and sharing knowledge.