我有以下C ++程序,它使用套接字编程进行战舰游戏,它写在窗口上。但我需要它在ubuntu上运行。请协助建议。我如何继续实现代码,我知道对于ubuntu,套接字编程部分将与窗口不同。
编码:服务器
//Battleship Server
#include <iostream> //For basic I/O operations
#include <conio.h> //For _getch(); to pause the program
#include <winsock2.h> //For network operations
#include <windows.h> //Needed by winsock
#include <ws2tcpip.h> //Used for and addrinfo related functions
#include <time.h> //For rand()
#define BUFLEN 64 //Default buffer length
#define PORT "3490" //Port to be used
#pragma warning(push)
#pragma warning(disable:4996)
using namespace std;
//Global ship names and corresponding letters
char *Shipnames[5] = {
"Aircraft Carrier",
"BattleShip",
"Destroyer",
"Submarine",
"patrol Boat",
};
char Letter[5] = { 'A', 'B', 'D', 'S', 'P' };
struct Ship
{
//To keep track of hits
char Hitbox[5];
//X & Y positions
int X;
int Y;
//Length of ship
int len;
//Direction
//true = vertical (Y)
//false = horizontal (X)
bool Direction;
};
//Translates letter cords to numbers
//eg: A5 = 15, B7 = 27, E3 = 53
int TransLettoNumb(char *Cord)
{
char Letters[8] = {
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
};
char Lowercase[8] = {
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
};
//Check through upper case
for (int x = 0; x < 8; x++)
{
if (Cord[0] == Letters[x])
return x + 1;
}
//check through lower case
for (int x = 0; x < 8; x++)
{
if (Cord[0] == Lowercase[x])
return x + 1;
}
return 0;
}
bool sendl(int sockfd, bool hit)
{
char *Line = new char[BUFLEN];
if (hit)
{
Line = "Hit!";
}
else
{
Line = "Miss!";
cout << "Miss!" << endl;
}
bool var = true;
if (send(sockfd, Line, strlen(Line), 0) == SOCKET_ERROR)
var = false;
return var;
}
//For checking if the client hit a boat
bool Checkhit(Ship ships[], char Cord[], int sockfd)
{
//Translate cords to ints
int Ycord = (Cord[1] - 48);
int Xcord = TransLettoNumb(Cord);
//Length of ship
int Len;
//For each ship
for (int n = 0; n < 4; n++)
{
//Set length
if (n == 0)
Len = 5;
else if (n == 1)
Len = 4;
else if (n == 2)
Len = 3;
else if (n == 3)
Len = 3;
else if (n == 4)
Len = 2;
//loop through the hitbox
for (int i = 0; i < Len; i++)
{
//If the x cord equals the ships cords plus hitbox (i), test y cords
if (Xcord == (ships[n].X + i))
{
//loop through the hitbox
for (int i = 0; i < Len; i++)
{
//If the y cord equals the ships cords plus hitbox (i)
if (Ycord == (ships[n].X + i))
{
//the ship was hit, update the hitbox
ships[n].Hitbox[i] = 'X';
{
cout << Shipnames[n] << " was hit!"<< endl;
//send hit
sendl(sockfd, true);
//Send which ship was hit
send(sockfd, Shipnames[n], strlen(Shipnames[n]), 0);
return true;
}
}
}
}
}
}
//The ship was not hit
return false;
}
void PlaceShips(Ship ships[])
{
int randnumb;
//For each ship
for (int n = 0; n < 5; n++)
{
//Randomize direction
randnumb = rand() % 2;
if (randnumb == 1)
ships[n].Direction = true;
else
ships[n].Direction = false;
do
{
randnumb = 0;
//randomize x
ships[n].X = rand() % 8 + 1;
//randomize y
ships[n].Y = rand() % 8 + 1;
//If direction is true, check y
if (ships[n].Direction)
{
//If the ship hit the wall
if ((ships[n].Y + ships[n].len) > 8)
randnumb = 1;
}
else //else check x
{
//If the ship hit the wall
if ((ships[n].X + ships[n].len) > 8)
randnumb = 1;
}
} while (randnumb > 0);
}
}
int main()
{
//Quit flag
bool quit = false;
//Initialize random seed
srand(time(NULL));
//Declare ships
Ship ships[5];
//Initialize ship lengths
ships[1].len = 5;
ships[2].len = 4;
ships[3].len = 3;
ships[4].len = 3;
ships[5].len = 2;
//Hit counter
int HitCounter = 0;
//Declare some winsock variables
int status; //To keep track of errors
WSADATA wsaData; //For winsock initialization
SOCKET ListenSocket = INVALID_SOCKET; //Socket for listening on
SOCKET ClientSocket = INVALID_SOCKET; //Socket for communicating with client
struct addrinfo *result = NULL; //struct to hold address information
struct addrinfo address; //struct to hold connection information
char recvbuf[BUFLEN]; //Buffer for receiving information
char sendbuf[BUFLEN]; //Buffer for sending
// Initialize Winsock
status = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (status != 0)
{
cout << "failed to initialize winsock" << endl;
_getch();
return 1;
}
ZeroMemory(&address, sizeof(address));
address.ai_family = AF_INET;
address.ai_socktype = SOCK_STREAM;
address.ai_protocol = IPPROTO_TCP;
address.ai_flags = AI_PASSIVE;
//Get IP and port info
status = getaddrinfo(NULL, PORT, &address, &result);
if (status != 0)
{
cout << "getaddrinfo failed with error: " << WSAGetLastError() << endl;
freeaddrinfo(result);
_getch();
return 1;
}
//Create a socket for listening
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET)
{
cout << "failed to create socket with error: " << WSAGetLastError() << endl;
freeaddrinfo(result);
_getch();
return 1;
}
//Bind to the port
status = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (status == SOCKET_ERROR)
{
cout << "failed with error " << WSAGetLastError() << " binding to port " << PORT << endl;
freeaddrinfo(result);
_getch();
return 1;
}
else cout << "binded to port " << PORT << endl;
//Done with the results
freeaddrinfo(result);
//Server loop
while (quit == false)
{
//Listening for client connections
//5 is the amount of clients that can wait on queue
status = listen(ListenSocket, 5);
if (status == SOCKET_ERROR)
{
cout << "listen() failed with error: " << WSAGetLastError() << endl;
closesocket(ListenSocket);
WSACleanup();
_getch();
return 0;
}
//Accept client connection
ClientSocket = accept(ListenSocket, NULL, NULL);
if (ClientSocket == INVALID_SOCKET)
{
cout << "accept failed with error: " << WSAGetLastError() << endl;
closesocket(ClientSocket);
WSACleanup();
_getch();
return 1;
}
else cout << "connection accepted from client" << endl;
//set up game...
int cord;
//Initialize ship hitboxes
for (int x = 0; x <5; x++)
{
//Initialize hitbox
for (int i = 0; i<5; i++)
ships[x].Hitbox[i] = Letter[x];
}
//Randomize ship locations
PlaceShips(ships);
status = 1;
//Game loop
while (status > 0)
{
///Receive client's bomb cords
status = recv(ClientSocket, recvbuf, BUFLEN, 0);
cout << endl << "client bombed square " << recvbuf[0] << recvbuf[1] << endl;
//Check if it was a hit or miss and reply to client
if (!Checkhit(ships, recvbuf, ClientSocket))
sendl(ClientSocket, false);
else
HitCounter++;
status = 0;
//generate random cord
do
{
cord = rand() % 8;
if (cord >= 0 && cord < 9)
sendbuf[0] = (cord + 65);
else
status = 1;
cord = rand() % 8;
if (cord >= 0 && cord < 9)
sendbuf[1] = (cord + 49);
else
status = 1;
} while (status == 1);
//send cord guess
send(ClientSocket, sendbuf, BUFLEN, 0);
cout << endl << "guessing " << sendbuf[0] << sendbuf[1] << endl;
//recv hit or miss
status = recv(ClientSocket, recvbuf, BUFLEN, 0);
//Display hit/miss
for (int x = 0; x < status; x++)
{
cout << recvbuf[x];
}
cout << endl;
//If all the boxes have been hit
if (HitCounter == 17)
{
//send game complete
strcpy(sendbuf, "game complete!");
cout << sendbuf << endl;
send(ClientSocket, sendbuf, BUFLEN, 0);
}
}
cout << "client disconnected" << endl;
}
_getch();
return 0;
}
编码:客户端
//Battleship Client
#include <iostream> //For basic I/O operations
#include <conio.h> //For _getch(); to pause the program
#include <winsock2.h> //For network operations
#include <windows.h> //Needed by winsock
#include <ws2tcpip.h> //Used for and addrinfo related functions
#include <string> //For string functions
#include <time.h> //For rand() functions
#define BUFLEN 64 //Default buffer length
#define PORT "3490" //Port to be used
using namespace std;
//Global ship names and corresponding letters
string Shipnames[5] = {
"Aircraft Carrier",
"BattleShip",
"Destroyer",
"Submarine",
"patrol Boat",
};
char Letter[5] = { 'A', 'B', 'D', 'S', 'P' };
struct Ship
{
//To keep track of hits
char Hitbox[5];
//the length of the ship
int len;
//X & Y positions
int X;
int Y;
//Direction
//true = vertical (Y)
//false = horizontal (X)
bool Direction;
};
bool SendLine(int sockfd, string desc)
{
char *Text = new char[BUFLEN];
cout << desc << endl;
cin.getline(Text, BUFLEN, '\n');
if (strcmp(Text, "V") == 0 || strcmp(Text, "v") == 0)
{
delete[] Text;
return true;
}
if (send(sockfd, Text, BUFLEN, 0) == SOCKET_ERROR)
cout << "server down" << endl;
delete[] Text;
return false;
}
//Translates letter cords to numbers
//eg: A5 = 15, B7 = 27, E3 = 53
int TransLettoNumb(char *Cord)
{
char Letters[8] = {
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
};
char Lowercase[8] = {
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
};
//Check through upper case
for (int x = 0; x < 8; x++)
{
if (Cord[0] == Letters[x])
return x+1;
}
//check through lower case
for (int x = 0; x < 8; x++)
{
if (Cord[0] == Lowercase[x])
return x+1;
}
return 0;
}
void UpdateShipGrid(char Grid[8][8], Ship ships[])
{
}
//For checking if the server hit a boat
bool Checkhit(Ship ships[], char Cord[], char ShipGrid[8][8])
{
//Translate cords to ints
int Xcord = TransLettoNumb(Cord);
int Ycord = (Cord[1] - 48); //we -48 to convert from ascii value
//Length of ship
int Len;
//For each ship
for (int n = 0; n < 4; n++)
{
//Set length
if (n == 0)
Len = 5;
else if (n == 1)
Len = 4;
else if (n == 2)
Len = 3;
else if (n == 3)
Len = 3;
else if (n == 4)
Len = 2;
//loop through the hitbox
for (int i = 0; i < Len; i++)
{
//If the x cord equals the ships cords plus hitbox (i), test y cords
if (Xcord == (ships[n].X + i))
{
//loop through the hitbox
for (int i = 0; i < Len; i++)
{
//If the y cord equals the ships cords plus hitbox (i)
if (Ycord == (ships[n].X + i))
{
//the ship was hit, update the hitbox and grid
ships[n].Hitbox[i] = 'X';
UpdateShipGrid(ShipGrid, ships);
return true;
}
}
}
}
}
//The ship was not hit
return false;
}
bool sendl(int sockfd, bool hit)
{
char *Line = new char[BUFLEN];
if (hit)
{
Line = "Hit!";
cout << "Hit!" << endl;
}
else
{
Line = "Miss!";
cout << "Miss!" << endl;
}
bool var = true;
if (send(sockfd, Line, strlen(Line), 0) == SOCKET_ERROR)
var = false;
return var;
}
void DisplayGrid(char GridA[8][8], char GridB[8][8])
{
cout << " Hit Grid Ship Grid " << endl;
cout << " A B C D E F G H A B C D E F G H" << endl;
for (int n = 1; n < 9; n++)
{
cout << n << " ";
for (int i = 0; i < 8; i++)
{
cout << GridA[n][i] << " ";
}
cout << "| ";
for (int t = 0; t < 8; t++)
{
cout << GridB[n][t] << " ";
}
cout << endl;
}
}
void InitGrid(char grid[8][8], Ship ships[])
{
//For the first dimension (x)
for (int n = 0; n < 9; n++)
{
//For the second dimension (y)
for (int i = 0; i < 9; i++)
{
//Give the box an empty space
grid[i][n] = ' ';
}
}
}
void PlaceShips(Ship ships[], char Grid[8][8])
{
int randnumb;
//For each ship
for (int n = 0; n < 5; n++)
{
//Randomize direction
randnumb = rand() % 2;
if (randnumb == 1)
ships[n].Direction = true;
else
ships[n].Direction = false;
do
{
randnumb = 0;
//randomize x
ships[n].X = rand() % 8 + 1;
//randomize y
ships[n].Y = rand() % 8 + 1;
//If direction is true, check y
if (ships[n].Direction)
{
//If the ship hit the wall
if ((ships[n].Y + ships[n].len) > 8)
randnumb = 1;
else
{
//Place each hitbox on grid
for (int i = 0; i < ships[n].len; i++)
Grid[ships[n].X][(ships[n].Y + i)] = ships[n].Hitbox[i];
}
}
else //else check x
{
//If the ship hit the wall
if ((ships[n].X + ships[n].len) > 8)
randnumb = 1;
else
{
//Place each hitbox on grid
for (int i = 0; i < ships[n].len; i++)
Grid[(ships[n].X + i)][ships[n].Y] = ships[n].Hitbox[i];
}
}
} while (randnumb > 0);
}
}
int main(int argc, char **argv)
{
// Validate the parameters
if (argc != 2)
{
cout << "Syntax: <server-ip>" << endl;
_getch();
return 1;
}
//Quit flag
bool quit = false;
//Keep track of hits
int HitCounter = 0;
//Initialize random seed
srand(time(NULL));
//Declare ships
Ship ships[5];
//Initialize ship lengths
ships[0].len = 5;
ships[1].len = 4;
ships[2].len = 3;
ships[3].len = 3;
ships[4].len = 2;
//Declare some winsock variables
int status; //To keep track of errors
WSADATA wsaData; //For winsock initialization
SOCKET ServerSocket = INVALID_SOCKET; //Socket for communicating with server
struct addrinfo *result = NULL; //struct to hold address information
struct addrinfo *Pointer = NULL; //struct to hold point to next ip
struct addrinfo address; //struct to hold connection information
char recvbuf1[BUFLEN]; //Buffer for receiving information
char recvbuf2[BUFLEN]; //Extra Buffer for receiving information
char sendbuf[BUFLEN]; //Buffer for sending information
// Initialize Winsock
status = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (status != 0)
{
cout << "failed to initialize winsock" << endl;
_getch();
return 1;
}
ZeroMemory(&address, sizeof(address));
address.ai_family = AF_INET;
address.ai_socktype = SOCK_STREAM;
address.ai_protocol = IPPROTO_TCP;
address.ai_flags = AI_PASSIVE;
//Get IP and port info
status = getaddrinfo(argv[1], PORT, &address, &result);
if (status != 0)
{
cout << "getaddrinfo failed with error: " << WSAGetLastError() << endl;
freeaddrinfo(result);
_getch();
return 1;
}
// Attempt to connect to an address until one succeeds
for (Pointer = result; Pointer != NULL; Pointer = Pointer->ai_next) {
// Create a SOCKET for connecting to server
ServerSocket = socket(Pointer->ai_family, Pointer->ai_socktype, Pointer->ai_protocol);
if (ServerSocket == INVALID_SOCKET)
{
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
_getch();
return 1;
}
// Connect to server.
status = connect(ServerSocket, Pointer->ai_addr, (int)Pointer->ai_addrlen);
if (status == SOCKET_ERROR)
{
closesocket(ServerSocket);
ServerSocket = INVALID_SOCKET;
continue;
}
break;
}
if (ServerSocket == INVALID_SOCKET)
{
cout << "could not connect " << endl;
_getch();
return 1;
}
else
cout << "connected to " << argv[1] << ":" << PORT << endl;
//Done with the results
freeaddrinfo(result);
//set up game...
//Grids that will be displayed
char HitGrid[8][8];
char ShipGrid[8][8];
//Initialize grids
InitGrid(HitGrid, ships);
InitGrid(ShipGrid, ships);
//Initialize ship hitboxes
for (int x = 0; x <5; x++)
{
//Initialize hitbox
for (int i = 0; i<5; i++)
ships[x].Hitbox[i] = Letter[x];
}
//Randomize ship locations
PlaceShips(ships, ShipGrid);
status = 1;
while (status > 0)
{
//Ask for cords
cout << "Enter a coord to bomb or press v to view grid" << endl;
cin.getline(sendbuf, BUFLEN, '\n');
//If user type 'v' then display grids
while (strcmp(sendbuf, "V") == 0 || strcmp(sendbuf, "v") == 0)
{
//Display the grids
DisplayGrid(HitGrid, ShipGrid);
//Ask for cords
cout << endl << "Enter a coord to bomb or press v to view grid" << endl;
cin.getline(sendbuf, BUFLEN, '\n');
}
//send cords
send(ServerSocket, sendbuf, BUFLEN, 0);
//recv hit/miss
status = recv(ServerSocket, recvbuf1, BUFLEN, 0);
//If we hit a ship, mark it on the hit grid
if (recvbuf1[0] == 'H')
{
//Recieve ship that was hit
status = recv(ServerSocket, recvbuf2, BUFLEN, 0);
//Display shipname
for (int x = 0; x < status; x++)
{
cout << recvbuf2[x];
}
cout << " was hit!" << endl;
//Update the hit grid
HitGrid[(sendbuf[1] - 48)][(TransLettoNumb(sendbuf) -1)] = recvbuf2[0];
}
else
{
HitGrid[(sendbuf[1] - 48)][(TransLettoNumb(sendbuf) - 1)] = 'X';
//Display hit/miss
for (int x = 0; x < status; x++)
{
cout << recvbuf1[x];
}
cout << endl;
}
//recv cord
status = recv(ServerSocket, recvbuf1, BUFLEN, 0);
cout << endl << "server bombed cord " << recvbuf1[0] << recvbuf1[1] << endl;
//Check if it was a hit or miss and reply to server
if (!Checkhit(ships, recvbuf1, ShipGrid))
sendl(ServerSocket, false);
else
{
sendl(ServerSocket, true);
//Add to hit counter
HitCounter++;
}
//update the ship grid
ShipGrid[(recvbuf1[1] - 48)][(TransLettoNumb(recvbuf1) - 1)] = 'X';
//Clear buffer
memset(recvbuf1, 0, sizeof(recvbuf1));
memset(recvbuf2, 0, sizeof(recvbuf2));
if (HitCounter > 17)
{
cout << endl << "the server one the game!" << endl;
_getch();
return 0;
}
}
_getch();
return 0;
}
答案 0 :(得分:-1)
根据我的经验,将套接字程序移植到ubuntu或反之亦然不应该是一个大问题。
我可以给你的第一个建议是将(特定于操作系统的)套接字代码与游戏代码分开。我的建议是为此创建单独的类。
接下来,头文件conio.h,winsock2.h,windows.h和ws2tcpip.h不存在于ubuntu(以及一般的Linux)中,但函数存在于不同的头文件中。看看我非常喜欢的以下教程。它解释了一个完整的教程:http://www.linuxhowtos.org/C_C++/socket.htm
希望这有帮助