井字棋源码(网络线程池版)

news2024/11/19 19:32:00

源码链接: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;
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1624467.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CMake:相关概念与使用入门(一)

1、Cmake概述 Cmake是一个项目构建工具&#xff0c;并且是跨平台的。 关于项目构建我们所熟知的有Makefile&#xff0c;然后通过make命令进行项目的构建&#xff0c;并且大多数是IDE都继承了make&#xff0c;比如&#xff1a;VS的nmake&#xff0c;Linux下的GNU make、Qt的qma…

《异常检测——从经典算法到深度学习》27 可执行且可解释的在线服务系统中重复故障定位方法

《异常检测——从经典算法到深度学习》 0 概论1 基于隔离森林的异常检测算法 2 基于LOF的异常检测算法3 基于One-Class SVM的异常检测算法4 基于高斯概率密度异常检测算法5 Opprentice——异常检测经典算法最终篇6 基于重构概率的 VAE 异常检测7 基于条件VAE异常检测8 Donut: …

基础SQL 函数

在MySQL中内置了很多函数&#xff0c;我们可以通过一段程序或者代码直接调用这个函数 一、字符串函数 下面通过例子来验证这些函数 -- 字符串函数-- concat函数 select concat("hello ","world");-- lower函数 select lower("HELLO");-- upper函…

4.18.2 EfficientViT:具有级联组注意力的内存高效Vision Transformer

现有Transformer模型的速度通常受到内存低效操作的限制&#xff0c;尤其是MHSA&#xff08;多头自注意力&#xff09;中的张量整形和逐元素函数。 设计了一种具有三明治布局的新构建块&#xff0c;即在高效FFN&#xff08;前馈&#xff09;层之间使用单个内存绑定的MHSA&#x…

4.24总结

对部分代码进行了修改&#xff0c;将一些代码封装成方法&#xff0c;实现了头像功能&#xff0c;通过FileInputStream将本地的图片写入&#xff0c;再通过FileOutputStream拷贝到服务端的文件夹中&#xff0c;并将服务端的文件路径存入数据库中

OpenHarmony语言基础类库【@ohos.util.Deque (线性容器Deque)】

Deque&#xff08;double ended queue&#xff09;根据循环队列的数据结构实现&#xff0c;符合先进先出以及先进后出的特点&#xff0c;支持两端的元素插入和移除。Deque会根据实际需要动态调整容量&#xff0c;每次进行两倍扩容。 Deque和[Queue]()相比&#xff0c;Queue的特…

Linux中DHCP原理与配置

目录 一.DHCP的原理 1.DHCP的简要概述 2.DHCP的优点 3.DHCP的分配方式 4.DHCP的租约过程 5.DHCP服务 6.可分配的地址信息主要包括 二.DHCP同一网段分配地址实验 windows命令 一.DHCP的原理 1.DHCP的简要概述 DHCP&#xff08;Dynamic Host Configuration Protocol&a…

一文速览Llama 3及其微调:如何通过paper-review数据集微调Llama3 8B

前言 4.19日凌晨正准备睡觉时&#xff0c;突然审稿项目组的文弱同学说&#xff1a;Meta发布Llama 3系列大语言模型了 一查&#xff0c;还真是 本文以大模型开发者的视角&#xff0c;基于Meta官方博客的介绍&#xff1a;Introducing Meta Llama 3: The most capable openly a…

优化大模型的解释性提示以提升文本推理性能:一种无监督数据驱动的方法

介绍一篇大模型前沿论文&#xff0c;《Explanation Selection Using Unlabeled Data for Chain-of-Thought Prompting》。在这篇论文中&#xff0c;作者Xi Ye和Greg Durrett探讨了如何通过优化大语言模型&#xff08;LLMs&#xff09;的解释性提示来提升文本推理任务的性能。他…

星汉未来AI应用市场:一站式AI解决方案平台

星汉未来AI应用市场&#xff1a;一站式AI解决方案平台 在人工智能技术日益渗透到各行各业的今天&#xff0c;星汉未来AI应用市场为我们提供了一个集创新与实用于一体的平台。下面&#xff0c;我将为您详细介绍这个平台的各个方面。 平台特色 星汉未来AI应用市场是一个面向未…

微博聚类分析和可视化

首先对聚类分析作系统介绍。其次对聚类算法进行文献回顾&#xff0c;对其概况、基本思想、算法进行详细介绍&#xff0c;再是通过对微博数据分析具体来强化了解聚类算法&#xff0c;本文的数据是由所设计地软件在微博平台上获取的数据&#xff0c;最后得到相关结论和启示。 聚…

春季过敏症状高发如何防护?约克VRF中央空调为您支招

百花齐放的春季,对于易过敏人群来说却像是“噩梦”的开场。据了解,许多人都会出现打喷嚏、流鼻涕、皮肤瘙痒等春季过敏症状,皮肤上出现红疹甚至“痒不欲生”,并且断断续续不停复发,身上被挠得“体无完肤”,严重影响睡眠。 到底是哪些致敏因素导致春季过敏高发?易过敏人群又该…

基于51单片机空气质量监测报警仿真LCD1602液晶显示( proteus仿真+程序+设计报告+原理图+讲解视频)

基于51单片机空气质量监测报警仿真LCD显示 1. 主要功能&#xff1a;2. 讲解视频&#xff1a;3. 仿真设计&#xff1a;4. 程序代码5. 设计报告6. 原理图7. 设计资料内容清单&&下载链接 基于51单片机空气质量监测报警仿真LCD显示( proteus仿真程序设计报告原理图讲解视频…

CTF之变量1

拿到题目发现是一个php代码&#xff0c;意思是用get方式获取args参数。 至于下面那个正则表达式怎么绕过暂且不知&#xff0c;但是题目最上面告诉我们lag In the variable ! &#xff08;意思是flag就在变量中&#xff09;。 那我们就传入全局变量globals&#xff08;&#xf…

maixcam如何无脑运行运行别人的模型(以安全帽模型为例)

maixcam如何无脑运行运行别人的模型&#xff08;以安全帽模型为例&#xff09; 本文章主要讲如何部署上传的模型文件&#xff0c;以及如果你要把你模型按照该流程应该怎么修改&#xff0c;你可以通过该文章得到你想要的应该&#xff0c;该应用也包含的退出按钮&#xff0c;是屏…

分布式与一致性协议之CAP(三)

CAP ACID理论:CAP的"酸"&#xff0c;追求一致性。 提到ACID,它很容易理解&#xff0c;在单机上实现也不难&#xff0c;比如可以通过锁、时间序列等机制保障操作的顺序执行&#xff0c;让系统实现ACID特性。但是一说要实现分布式系统的ACID特性比较难实现呢&#xf…

Prompt之美:如何设计提示词让大模型变“聪明”

目录 一. Prompt关键要素 二. Prompt技巧 三. 实战中的Prompt优化 四. 参考文献 一. Prompt关键要素 Prompt是一个简短的文本输入&#xff0c;用于引导AI模型生成特定的回答或执行特定任务。换句话说&#xff0c;Prompt是你与AI模型沟通的方式。一个好的Prompt可以让AI更准…

SpringBoot (批量)生成二维码工具类多种方法示例

一、引入依赖 <dependency><groupId>com.google.zxing</groupId><artifactId>javase</artifactId><version>3.4.1</version> </dependency><dependency><groupId>com.google.zxing</groupId><artifactId…

Java中使用Graphics2D绘制字符串文本自动换行 算法

效果&#xff1a; 代码&#xff1a; /*** return void* Author xia* Description //TODO 写字换行算法* Date 18:08 2021/4/1* Param []**/private static void drawWordAndLineFeed(Graphics2D g2d, Font font, String words, int wordsX, int wordsY, int wordsWidth) {FontD…

SPRD Android 14 通过属性控制系统设置显示双栏或者单栏

SPRD Android 14 通过属性控制系统设置显示双栏或者单栏 第一步 确认有添加静态库第二步 验证第三步 修改源码在合适的地方配置 ro.product.is_support_SettingsSplitEnabled 即可。第一步 确认有添加静态库 --- a/packages/apps/Settings/Android.bp +++ b/packages/apps/Set…