网络对战五子棋(来一起PK鸭)

一、本地调用和RPC调用的区别

首先了解一下RPC~
RPC主要是解决了两个问题:

  1. 解决了分布式系统中,服务之间的调用问题
  2. 尤其是在远程调用的时候,可以让调用者感受不到远程调用的过程,调用者就感觉是自己在调用本地的接口

本地调用: 函数的实现在本地,当去调用函数时,就会跳转至本地的对应接口

RPC调用: 实现的方法在远端,调用函数时会跳转至远端进行调用,但是调用者本身感受不到远程调用的过程,就像使用本地调用一样简单。

二、前期环境配置

写这个网络对战的五子棋环境一定要提前配置好咯( ̄▽ ̄)~*
博主当时搞了一天╭(╯^╰)╮
环境配好很重要的,配置环境的时候一定不能焦躁!!

1.高版本的gcc

因为要使用C++的一些新特性,所以就要升级你的gcc
具体戳这里---->使用新版的gcc - Developer Toolset 7

2.安装cmake

需要使用cmake3.7以上的版本进行Makefile的自动化生成
具体戳这里---->cmake升级到cmake-3.9.2版本

3.安装boost库

这个安装起来炒鸡麻烦!!!!!
安装boost库,具体编译的时候,错误提示信息会告诉你
具体戳这里---->CentOS 7下编译安装Boost_1_57_0

4.最后!下载一个REST_RPC

因为我们如果自己实现一个RPC会非常复杂,我们用别人已经写好的RPC框架就最好辽!所以博主找到了一个开源的RPC框架----REST_RPC,我们就用这个来完成网络调用逻辑。我们关注游戏本身~
附上源码链接,阔以自行下载:https://github.com/qicosmos/rest_rpc

三、进入写游戏环节(开始鸡冻了!!!)

网络对战五子棋的主要思路

对于客户端来说,也就是玩家,我肯定要能进行注册,登录,进行匹配,开始游戏(下棋,下棋的节奏),一轮游戏结束我就得知道自己赢了没。这些我们都是通过调用RPC接口,去调用服务器上的相关操作函数。

但是对于客户端我们有两个,这两个客户端的要对一个棋盘进行操作,所以相关的游戏信息都要放在服务器上。比如棋盘信息,玩家的相关基本信息(账号,密码,游戏id),玩家的状态,玩家匹配房间的房间信息,游戏大厅等等。

两个玩家进行游戏的整个过程都是对服务器上的数据进行操作,我只需要把我想要的信息拿到即可。游戏的本质就是两个玩家对同一份服务器上的数据进行修改。

用户基本信息(Player.hpp)
typedef enum
{                        OFFLINE,//离线       ONLINE,//在线              MATCHING,//匹配中            PLAYING//玩游戏中
}status_t;               class Player
{
private:             string name;     string passwd;   uint32_t id;     int win;         int lose;        int tie;//平局                                                                                                                      status_t st;//用户状态uint32_t room_id;
}
用户管理(PlayerManager.hpp)
class PlayerManager
{private:unordered_map<uint32_t, Player> player_set;uint32_t assign_id;//起始id
}
房间信息(Room.hpp)
class Room
{
private:uint32_t one;uint32_t two;uint32_t current;char piece[2];char board[SIZE][SIZE];char result;//X:第一个玩家赢  O:第二个玩家赢  E:平局  N:继续游戏pthread_mutex_t lock;
}
房间管理(RoomManager.hpp)
class RoomManager
{private:unordered_map<uint32_t,Room> room_set;uint32_t assign_id;
}
大厅信息(Hall.hpp)
class Hall
{
private:PlayerManager pm;//用户管理RoomManager rm;//房间管理vector<vector<uint32_t> >  match_pool;//匹配池int match_num;pthread_mutex_t match_lock;pthread_cond_t match_cond;
}

1.注册

用户注册的时候要提供自己的昵称和登录密码,因此在客户端要进行用户的昵称和密码的接收,接收完毕之后,调用RPC接口进行注册,数据保存在服务器上。

具体步骤:
玩家发起注册请求,客户端首先调用本地的Register函数,Register函数内部调用远端服务器的RpcRegister,服务器提前注册好了这个RpcRegister函数,当客户端要调用RpcRegister函数时,就会转为调用Hall里面的Register函数,Hall里面的Register函数又会去调用PlayerManager里的InsertPlayer函数。那么InsertPlayer函数是干什么的呢?它就是将这个用户的信息插入到服务器中的player_set里(这个player_set本质上是一个unordered_map,相当于是我们这个游戏的数据库,这个东东完成了玩家id和玩家信息的一个映射关系),插入成功后就完成了用户的注册。客户端传参时id是一个输出型参数,会返回服务器给客户端的id信息,至此玩家获得自己的id号。

这么看文字大家对于逻辑好像不是很清楚,博主画了函数的调用逻辑如下图(ૢ˃ꌂ˂⁎):

2.登录

登录的时候,需要提供用户的id和密码,因此客户端要完成id和密码的接收,接收完成之后调用本地登录接口,本地登录接口调用远端RPC接口,完成用户信息的查找。

具体步骤:
玩家发起登录请求,客户端首先调用本地的Login函数,Login函数内部调用远端服务器的RpcLogin,服务器提前注册好了这个RpcLogin函数,当客户端要调用RpcLogin函数时,就会转为调用Hall里面的Login函数,Hall里面的Login函数又会去调用PlayerManager里的SearchPlayer函数,那SearchPlayer是干什么的呢?它就是在服务器中的player_set里查找这个用户的信息,查找到了,把该id的状态设置为ONLINE,然后就返回这个用户id,客户端收到这个id时,判断id合法的时候就可以提示用户登录成功。但是如果SearchPlayer没有查找到,那么返回的就是对应的错误码,然后告诉玩家是什么问题(1.未注册 2.密码错误 3.链接超时)。

具体看下图的函数调用逻辑(ૢ˃ꌂ˂⁎):

3.匹配

具体步骤:
当玩家登录成功会跳转至游戏界面,玩家在游戏界面发起匹配请求时,会调用客户端的Match函数,Match函数会调用本地实现的的PushIdInMatchPool和CheckReady函数。
那么具体看一下这两个函数:
首先是PushIdInMatchPool会去调用远端服务器的RpcPushIdInMatchPool,也就是把这个用户id放到服务器端的匹配池里,首先把这个id的状态变为MATCHING(因为要开始匹配了),这里的匹配池是一个vector嵌套vector的模式,根据用户的胜率信息,把用户插入到match_pool对应胜率的小vector里,当插入完成之后,匹配的人数加1,然后会唤醒服务器端的匹配线程进行匹配(MatchService)。那么匹配线程干什么呢?匹配线程会一直在后台运行,我们把这个匹配线程设置成一个分离状态,然后它检测匹配的人数是否大于2,如果不大于2,那么这个线程进行等待,如果大于2,它就会把匹配池里的用户id按照胜率的顺序拿出来放到一个新的vector(id_list)里面,(这样做的目的就是尽量把胜率相同的人匹配在一起),然后把匹配的人数变成偶数,两两进行匹配,匹配过后进行游戏的准备阶段(GamePrepare),给两个玩家创建游戏房间,并把他们的状态设置为PLAYING状态,但是如果之前的人数是奇数的话,我们把最后一个人漏掉啦,所以让最后一个人匹配失败,状态重新设置为ONLINE,(其实也可以给这个人匹配一个机器人啦,增强玩家的游戏体验感 (*•ω•)!)。那么这一轮的匹配已经完成了之后,匹配池线程就需要把匹配池(match_pool)进行清空操作(MatchPoolClear),清空之后匹配线程又会继续循环起来,看下一轮匹配池里的人数是否大于2,然后在进行下一轮的匹配~~

如果玩家匹配成功时,状态已经从MATCH状态变为PLAYING状态了,然后客户端还会调用第二个函数CheckReady,这个函数去调用了远端服务器的main里的RpcPlayerReady,RpcPlayerReady调用了Hall里的IsPlayerReady,IsPlayerReady调用了PlayerManager里的Ready,Ready调用了Player里的status也就是返回这个玩家的状态,看它的状态是不是PLAYING,如果是PLAYING状态,那么客户端检测到之后就会告诉玩家匹配成功开始游戏了。如果是MATCHING那就继续隔一秒检测一次,如果是ONLING那就提示用户匹配失败。

至此匹配工作完成~,这里的逻辑稍微有一丢丢绕。

具体看下图的函数调用逻辑(ૢ˃ꌂ˂⁎):

4.游戏

具体步骤: 当玩家的房间创建好之后,双方玩家获得相应的棋子,进行游戏逻辑,每落一次子,对该棋盘进行判定,是否有玩家胜出。

游戏逻辑如下:
获取到棋盘(GetBoard)获取到房间号(GetMyRoomId)获取到我所拿的棋子(GetMyPiece),将棋盘进行打印(ShowBoard),判断一下是不是该我走(IsMyTurn),不该我走时我就等待,该我走时则输入对应下标,判断下标是否合法(PosIsRight),合法之后就进行落子(Step),然后进行游戏结果的判定(Judge)。
其中ShowBoard和PosIsRight可以不用调用rpc接口,在本地实现即可,因为当我们获取到棋盘时就可以在本地进行打印棋盘和判断输入位置是否合法。

具体看下图的函数调用逻辑(ૢ˃ꌂ˂⁎):

至此,整个游戏的逻辑就没有太大问题了,后续还可以进行一些改进噢。
附上博主的游戏代码,可以自己实现一下这个游戏,写好之后就算是自己和自己玩耍也是炒鸡有成就感的|ू・ω・` )
github链接:https://github.com/ETalienwx/Project_Management/tree/master/gobang-1

网络对战五子棋(来一起PK鸭)相关推荐

  1. 【181018】VC++ 网络对战五子棋游戏(服务端+用户端)

    VC++ 网络对战五子棋游戏(服务端+客户端),编译后先开启服务器端,服务端管理着各个用户之间的数据传递,用户端是多个的.就像游戏大厅一样.用户登录了后服务端将向用户端发送当前所有在线玩家列表数据.由 ...

  2. C#版网络对战五子棋以及Socket通信

    前言     这个网络版五子棋游戏是今年四月初写的.当时觉得自己应该学一些网络编程的东西.而我课程设计的题目已经定了---做一个Everything. 那就帮我斐哥做个网络版的五子棋吧. 源码:htt ...

  3. 单机版五子棋java功能_java实现单机版和网络对战版五子棋程序

    [实例简介] java实现单机版和网络对战版五子棋,功能包括计时.悔棋.聊天.显示双方状态等等.详细见https://blog.csdn.net/qq_37913997/article/details ...

  4. 五子棋网络对战 java实现

    五子棋网络对战 java实现 最近期末考试,压力实在是太大了.专业不对口的痛苦,别人永远体会不来.闲暇之余,便想着巩固一下java的基础知识,以前看别人写的游戏,心里都觉得哇 好厉害啊,我什么时候才可 ...

  5. Java swing + socket 写的一个五子棋网络对战游戏

    自从开始接触Swing以来,就喜欢写写各种管理系统,写多了就萌生了一种类似于实时在线对战的游戏,经过一番构思后就开始着手设计这个网络对战版本的五子棋了. 游戏代码包含两部分,常规的C/S模式(C代表客 ...

  6. java五子棋联网对战,毕业设计-- 用JAVA实现五子棋网络对战系统

    毕业设计-- 用JAVA实现五子棋网络对战系统 本科生毕业设计(论文)本科生毕业设计(论文) 题 目 用 JAVA 实现五子棋网络对战系统 姓 名 xxxx 学 号 xxxxx 系 别 计算机工程系 ...

  7. java实现单机版和网络对战版五子棋

    java实现单机版和网络对战版五子棋,功能包括计时.悔棋.聊天.显示双方状态等等. 选择com.fivechess.view中的SelectMenu.java开始游戏,效果如图: (1)单机版 点击& ...

  8. Java-基于GUI编程的人机对战五子棋

    1.人员分工 组员 职务 负责模块 刘新臻 组长 AI算法设计.程序逻辑设计 陈钦毅 组员 游戏画面框架,监听器.工具类 文才学 组员 棋子设计类.菜单功能 2.前期调查 根据调研我们需要以下功能 功 ...

  9. Android手游《》斗地主完整的源代码(支持单机和网络对战)

    Android手游<斗地主>完整的源代码(支持单机和网络对战)下载.一个很不错的源代码. 斗地主掌游是一个独特的国内社会斗地主棋牌游戏,之后玩家可以下载网上斗地主和全世界.掌游斗地主特点: ...

最新文章

  1. HPE品牌存储为啥高调? 因为“王炸”多啊!
  2. (转载)OC学习篇之---KVC和KVO操作
  3. HDFS集群balance(3)-- 架构细节
  4. 3-插入排序C实现(递增递减的简单转换)
  5. 对Canvas的研究
  6. Eigen C++开源矩阵计算工具——Eigen的简单用法
  7. CSS3 弹性盒子模型
  8. 2011系统架构师大会分享-自动化运维中的关系管理
  9. [ZT]ASP.NET中如何防范SQL注入式攻击
  10. 19【CTR15】会话兴趣⽹络
  11. c语言课后作业答案第五版第4章,《C语言程序设计》课后习题答案(第四章)
  12. 【老骥伏枥-狗年大礼包】嵌入式linux逆向工程,手把手教你作黑Q-第二讲
  13. python在统计专业的应用_Python统计学statistics实战
  14. 中兴网信发布“广义智慧城市顶层设计框架”
  15. ArcGIS操作系列(一)之地理配准
  16. java ttf_java直接使用ttf字体,解决window和linux之间的差异
  17. 谈古论津丨天津杨柳青年画为何要用娃娃作主题?
  18. java计算机毕业设计ssm兴发农家乐服务管理系统n159q(附源码、数据库)
  19. 不知明镜里,何处得秋霜
  20. dede tag标签作用

热门文章

  1. 【WPF、UWP】搜索蓝牙设备
  2. 使用C++让鼠标指针抖动
  3. 解决ECharts中使用tooltip时鼠标移入抖动问题
  4. 2017计科01-08编译原理模拟测试2--chap03
  5. 拆解:比银行卡面积还小的充电宝,怎么做到10000mAh?
  6. 正规的股票交易软件有哪些?
  7. 大数据分析未来财富管理谁会脱颖而出?
  8. Atmel at91rm9200的armlinux的bootloader启动代码分析
  9. 李宏毅《机器学习》误差
  10. 《肖申克的救赎》- 阅后小记