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