源码链接:game
效果可能没有那么好,大家可以给点建议。
效果展示
game.h
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3
#define COL 3
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
//打印数据
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\n");
//打印分割的行
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
printf("\n");
}
}
}
void player_move(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家下棋\n");
while (1)
{
printf("请输入坐标:>");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//下棋
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("该坐标被占用,请重新输入\n");
}
}
else
{
printf("坐标非法,请重新输入\n");
}
}
}
void computer_move(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑下棋:>\n");
while (1)
{
x = rand() % row;//0~2
y = rand() % col;//0~2
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
static int if_full(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;//没满
}
}
}
return 1;//满了
}
char is_win(char board[ROW][COL], int row, int col)
{
int i = 0;
//判断行
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
{
return board[i][1];
}
}
//判断列
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
{
return board[1][i];
}
}
//对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
//判断平局
if (if_full(board, row, col) == 1)
{
return 'Q';
}
//继续
return 'C';
}
tcp_client.cc
#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "game.h"
void menu()
{
printf("********************************\n");
printf("********* 1. play *********\n");
printf("********* 0. exit *********\n");
printf("********************************\n");
}
void game()
{
char ret = 0;
// 存放下棋的数据
char board[ROW][COL] = {0};
// 初始化棋盘为全空格
InitBoard(board, ROW, COL);
// 打印棋盘
DisplayBoard(board, ROW, COL);
while (1)
{
// 玩家下棋
player_move(board, ROW, COL);
DisplayBoard(board, ROW, COL);
// 判断输赢
ret = is_win(board, ROW, COL);
if (ret != 'C')
{
break;
}
// 电脑下棋
computer_move(board, ROW, COL);// 随机下棋
DisplayBoard(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
{
printf("恭喜你赢了\n");
}
else if (ret == '#')
{
printf("很遗憾你输了\n");
}
else
{
printf("平局\n");
}
}
void Usage(std::string proc)
{
std::cout << "\nUsage: " << proc << " serverIp serverPort\n"
<< std::endl;
}
void Print(int &sock, std::string &line)
{
ssize_t s = send(sock, line.c_str(), line.size(), 0);
if (s > 0)
{
char buffer[1024];
ssize_t s = recv(sock, buffer, sizeof(buffer) - 1, 0);
if (s > 0)
{
buffer[s] = 0;
std::cout << "server 回应# " << buffer << std::endl;
}
else if (s == 0)
{
close(sock);
}
}
else
{
close(sock);
}
}
int main(int argc, char *argv[])
{
if (argc != 3)
{
Usage(argv[0]);
exit(1);
}
std::string serverip = argv[1];
uint16_t serverport = atoi(argv[2]);
int sock = 0;
std::string line;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0)
{
std::cerr << "socket error" << std::endl;
exit(2);
}
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(serverport);
server.sin_addr.s_addr = inet_addr(serverip.c_str());
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0) // 连接服务器
{
std::cerr << "connect error" << std::endl;
exit(3);
}
std::cout << "connect success" << std::endl;
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
line = "start";
Print(sock, line);
game(); // 游戏
break;
case 0:
line = "quit";
Print(sock, line);
break;
default:
printf("选择错误\n");
break;
}
} while (input);
if (line == "quit")
{
exit(0);
}
return 0;
}
tcp_server.cc
#include "tcp_server.hpp"
#include <memory>
static void Usage(std::string proc)
{
std::cout << "\nUsage" << proc << " port\n" << std::endl;
}
int main(int argc, char* argv[])
{
if(argc != 2)
{
Usage(argv[0]);
exit(1);
}
uint16_t port = atoi(argv[1]);
std::unique_ptr<Tcp_Server> svr(new Tcp_Server(port));
svr->InitServer();
svr->Start();
return 0;
}
tcp_server.hpp
#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <strings.h>
#include <assert.h>
#include <unistd.h>
#include <signal.h>
#include <memory>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
#include <sys/wait.h>
#include "threadPool/log.hpp"
#include "threadPool/thread.hpp"
#include "threadPool/threadPool.hpp"
#include "threadPool/Task.hpp"
#include "game.h"
static void play(int sock, const std::string &clientip, const uint16_t &clientport, const std::string &thread_name)
{
char buffer[1024];
while (true)
{
ssize_t s = read(sock, buffer, sizeof(buffer) - 1);
std::string message;
if (s > 0)
{
buffer[s] = 0;
std::cout << thread_name << "|" << clientip << ":" << clientport << "# " << buffer << std::endl;
if (strcmp(buffer, "start") == 0)
{
message = "玩家请开始游戏";
}
if (strcmp(buffer, "quit") == 0)
{
message = "玩家退出游戏成功";
}
write(sock, message.c_str(), message.size());
}
else if (s == 0) // 对端关闭连接
{
logMessage(NORMAL, "%s:%d 玩家已退出游戏,我也退出", clientip.c_str(), clientport);
break;
}
else
{
logMessage(ERROR, "read socket error, %d:%s", errno, strerror(errno));
break;
}
}
close(sock);
}
class Tcp_Server
{
private:
const static int gbacklog = 20;
public:
Tcp_Server(uint16_t port, std::string ip = "")
: _port(port), _ip(ip), listensock(-1), _threadpool_ptr(ThreadPool<Task>::getThreadPool())
{
}
~Tcp_Server()
{
}
void InitServer()
{
// 1.创建socket
listensock = socket(AF_INET, SOCK_STREAM, 0);
if (listensock < 0)
{
// 创建socket失败
logMessage(FATAL, "create socket error, %d:%S", errno, strerror(errno));
exit(2);
}
logMessage(NORMAL, "create socket success, listensock:%d", listensock);
// 2.bind
struct sockaddr_in local;
memset(&local, 0, sizeof local);
local.sin_family = AF_INET;
local.sin_port = htons(_port);
local.sin_addr.s_addr = _ip.empty() ? INADDR_ANY : inet_addr(_ip.c_str()); // INADDR_ANY:任意IP
if (bind(listensock, (struct sockaddr *)&local, sizeof(local)) < 0)
{
// bind失败
logMessage(FATAL, "bind error, %d:%s", errno, strerror(errno));
exit(3);
}
// 3.建立连接
if (listen(listensock, gbacklog) < 0)
{
// 建立连接失败
logMessage(FATAL, "listen error, %d:%s", errno, strerror(errno));
exit(4);
}
logMessage(NORMAL, "init server success");
}
void Start()
{
_threadpool_ptr->run();
while (true)
{
// 4.获取连接
struct sockaddr_in src;
socklen_t len = sizeof(src);
int servicesock = accept(listensock, (struct sockaddr *)&src, &len);
// 获取连接失败
if (servicesock < 0)
{
logMessage(ERROR, "accept error, %d:%s", errno, strerror(errno));
continue;
}
// 获取连接成功
uint16_t client_port = ntohs(src.sin_port);
std::string client_ip = inet_ntoa(src.sin_addr);
logMessage(NORMAL, "link success, servicesock: %d | %s : %d |\n", servicesock, client_ip.c_str(), client_port);
// 5.开始通信
// 线程池版
Task t(servicesock, client_ip, client_port, play);
_threadpool_ptr->pushTask(t);
}
}
private:
uint16_t _port;
std::string _ip;
int listensock;
std::unique_ptr<ThreadPool<Task>> _threadpool_ptr;
};