C# Winform 云原生多人在线两两对弈五子棋(Fivesonchess)

介绍:
两人在线对弈的策略型棋类游戏
五子棋起源于中国,是全国智力运动会竞技项目之一,是一种两人对弈的纯策略型棋类游戏。双方分别使用黑白两色的棋子,下在棋盘直线与横线的交叉点上,先形成五子连珠者获胜。

主界面 多人在线自动匹配队友
对弈主界面

游戏功能说明

  1. 分为客户端和服务端,服务端控制业务逻辑,客户端展示及交互
  2. 客户端功能包含: 找棋友,重新开始,悔棋,认输,逃跑,棋谱记录,eabei聊天室
    2.1 找棋友: 通过服务器随机分配一名对手,
    2.2 重新开始: 在完成一局之后,如果还想和该对手再来一局,可以点击重新开始,双方都要重新开始才能开始新一局游戏。反之则不能开始;
    2.3 悔棋: 当一名对手下了一子,如果下得不对,想悔一步,则点击悔棋,如果对方想悔棋则是不能的,悔棋可以连续返回到最初开始的状态;
    2.4 认输: 当觉得自己不能战胜对方时,点击认输,这时需要对手的同意才能完成认输过程。
    2.5 逃跑: 当匹配到对手后,在任一时刻都可以逃跑。
    2.6 棋谱记录: 棋谱记录了上一次下棋的过程,并且可以进行回放,回放方式设计了2种模式: 一种是自动回放,另一种是手动回放;
    2.7 Eabei聊天室: 聊天目前只能在匹配对手成功后,都可以进行聊天,如果逃跑,聊天则结束;

找棋友

private void Discovery_DataThreadCallback((string name, string data) obj)
{
    if (Pairung(obj.name, out (PlayerInfo? self, PlayerInfo? rival) pairung, out string msg))
    {
        string userSelfString = JsonSerializer.Serialize<PlayerInfo>(pairung.self);
        string userRivalString = JsonSerializer.Serialize<PlayerInfo>(pairung.rival);
        //发送对手信息
        Global.Instance.EventManager.Publish(new Model.EventParam.EventServerDataResult() { DataHeader = DataHeaderInfo.Discovery, Data = new object[] { obj.name, $"{userSelfString}&{userRivalString}" } });
        Global.Instance.EventManager.Publish(new Model.EventParam.EventServerDataResult() { DataHeader = DataHeaderInfo.Message, Data = new object[] { obj.name, "匹配成功!" } });
        //发送对手信息
        Global.Instance.EventManager.Publish(new Model.EventParam.EventServerDataResult() { DataHeader = DataHeaderInfo.Discovery, Data = new object[] { pairung.rival?.Name, $"{userRivalString}&{userSelfString}" } });
        Global.Instance.EventManager.Publish(new Model.EventParam.EventServerDataResult() { DataHeader = DataHeaderInfo.Message, Data = new object[] { pairung.rival?.Name, "匹配成功!" } });
    }
    else
    {
        Global.Instance.EventManager.Publish(new Model.EventParam.EventServerDataResult() { DataHeader = DataHeaderInfo.Message, Data = new object[] { obj.name, msg } });
    }
}

/// <summary>
/// 配对
/// </summary>
/// <param name="name"></param>
/// <param name="msg"></param>
/// <returns></returns>
public bool Pairung(string name, out (PlayerInfo? user_self, PlayerInfo? user_rival) _pairung, out string msg)
{
    msg = string.Empty;
    _pairung = (null, null);
    //过滤自己
    List<string> clientNames = TcpServerManager.Instance.GetClientNameList().Where(s => s != name).ToList();

    if (clientNames.Count == 0)
    {
        msg = $"{Model.DataHeaderInfo.Message}无对手,您已无敌,对手都被吓跑了!";
        return false;
    }
    //判断是否已配对
    var pairungList = DataManager.Instance.GetPairungList();

    (PlayerInfo? user1, PlayerInfo? user2)? this_user = pairungList.FirstOrDefault(q => q.user1?.Name == name || q.user2?.Name == name);
    if (this_user is not null && this_user?.user1 is not null && this_user?.user2 is not null)
    {
        msg = $"{Model.DataHeaderInfo.Message}您已找到合适的棋友, 可以开始下棋了!";
        return false;
    }
    //寻找空闲的棋友
    List<string> clientFree = new();
    //过滤已配对的棋友
    foreach (var item in clientNames)
    {
        (PlayerInfo? name1, PlayerInfo? name2)? _user = pairungList.FirstOrDefault(q => q.user1?.Name == item || q.user2?.Name == item);
        if (_user is not null && _user?.name1 is not null && _user?.name2 is not null) continue;
        clientFree.Add(item);
    }
    if (clientFree.Count == 0)
    {
        msg = $"{Model.DataHeaderInfo.Message}无棋友!";
        return false;
    }
    int rivalIndex = random.Next(0, clientFree.Count);
    var clientRival = clientFree[rivalIndex];

    (PlayerInfo? userSelf, PlayerInfo? userRival) pairung = (new PlayerInfo(), new PlayerInfo());
    (pairung.userSelf.Name, pairung.userRival.Name) = (name, clientRival);
    (pairung.userSelf.State, pairung.userRival.State) = (PlayerState.Prepare, PlayerState.Prepare);
    int campIndex = random.Next(0, 2);
    ChessCardCamp camp = (ChessCardCamp)campIndex;
    (pairung.userSelf.Camp, pairung.userRival.Camp) = (camp, camp == ChessCardCamp.BlackCamp ? ChessCardCamp.WhiteCamp : ChessCardCamp.BlackCamp);

    if (pairung.userSelf.Camp == ChessCardCamp.BlackCamp)
        pairung.userSelf.CurrCamp = ChessCardCamp.BlackCamp;
    else
        pairung.userRival.CurrCamp = ChessCardCamp.BlackCamp;


    _pairung = pairung;
    pairungList.Add(pairung);
    return true;
}

重新开始

private void DataNoneParse_DataThreadCallback((string name, string data) obj)
{
    if (ReStart(obj.name, out (PlayerInfo? self, PlayerInfo? rival) pairung, out string msg))
    {
        pairung.self.State = PlayerState.Prepare;
        pairung.self.Camp = pairung.self.Camp == ChessCardCamp.BlackCamp ? ChessCardCamp.WhiteCamp : ChessCardCamp.BlackCamp;
        Global.Instance.EventManager.Publish(new Model.EventParam.EventServerDataResult() { DataHeader = DataHeaderInfo.Reset, Data = new object[] { obj.name, "" } });
        Global.Instance.EventManager.Publish(new Model.EventParam.EventServerDataResult() { DataHeader = DataHeaderInfo.Message, Data = new object[] { obj.name, "您已准备! 等待对方重新开始!" } });

        pairung.self.Camp = pairung.self.Camp == ChessCardCamp.BlackCamp ? ChessCardCamp.WhiteCamp : ChessCardCamp.BlackCamp;
        if (pairung.rival.State == PlayerState.Prepare)
        {
            pairung.self.CurrCamp = pairung.rival.CurrCamp = ChessCardCamp.BlackCamp;
            if (pairung.self.Camp == ChessCardCamp.BlackCamp)
            {
                pairung.self.Camp = ChessCardCamp.WhiteCamp;
                pairung.rival.Camp = ChessCardCamp.BlackCamp;
            }
            else
            {
                pairung.self.Camp = ChessCardCamp.BlackCamp;
                pairung.rival.Camp = ChessCardCamp.WhiteCamp;
            }

            string selfString = JsonSerializer.Serialize<PlayerInfo>(pairung.self);
            string rivalString = JsonSerializer.Serialize<PlayerInfo>(pairung.rival);
            Global.Instance.EventManager.Publish(new Model.EventParam.EventServerDataResult() { DataHeader = DataHeaderInfo.Reset, Data = new object[] { obj.name, selfString } });
            Global.Instance.EventManager.Publish(new Model.EventParam.EventServerDataResult() { DataHeader = DataHeaderInfo.Reset, Data = new object[] { pairung.rival.Name, rivalString } });

            Global.Instance.EventManager.Publish(new Model.EventParam.EventServerDataResult() { DataHeader = DataHeaderInfo.Message, Data = new object[] { obj.name, "开始!" } });

            Global.Instance.EventManager.Publish(new Model.EventParam.EventServerDataResult() { DataHeader = DataHeaderInfo.Message, Data = new object[] { pairung.rival.Name, "开始!" } });
        }
    }
    else
    {
        Global.Instance.EventManager.Publish(new Model.EventParam.EventServerDataResult() { DataHeader = DataHeaderInfo.Message, Data = new object[] { obj.name, msg } });
    }
}

private bool ReStart(string name, out (PlayerInfo? self, PlayerInfo? rival) result, out string msg)
{
    result = (null, null);
    msg = string.Empty;
    var pairungList = DataManager.Instance.GetPairungList();
    var exists = pairungList.FirstOrDefault(q => q.user1?.Name == name || q.user2?.Name == name);
    if (exists.user1 is null || exists.user2 is null)
    {
        msg = "请先找对手哈!";
        return false;
    }

    var _pairung = pairungList.FirstOrDefault(q => q.user2?.Name == name);

    if (_pairung.user1 is not null && _pairung.user2 is not null)
        result = (_pairung.user2, _pairung.user1);
    else
        result = exists;

    if (result.self.State != PlayerState.Free)
    {
        msg = "无法重新开始, 已准备或已经开始了!";
        return false;
    }
    return true;
}

悔棋

private void RevocationParse_DataThreadCallback((string name, string data) obj)
{
    //命令协议----data   1:请求,发起   2: 询问对方 3:对方返回结果 true: 撤回  false:不撤回 4: 结果应答 true: 撤回  false:不撤回 
    if (string.IsNullOrEmpty(obj.data)) return;
    if (Revocation(obj.name, out (PlayerInfo? self, PlayerInfo? rival) pairung, out string msg))
    {
        string code = obj.data[..1];
        string rivalName = pairung.rival?.Name ?? "";
        switch (code)
        {
            case "1":
                if (pairung.self.CurrCamp != pairung.self.Camp)
                    Global.Instance.EventManager.Publish(new EventServerDataResult() { DataHeader = DataHeaderInfo.Revocation, Data = new object[] { rivalName, "2" } });
                else
                    Global.Instance.EventManager.Publish(new EventServerDataResult() { DataHeader = DataHeaderInfo.Message, Data = new object[] { obj.name, "你不能悔棋!" } });
                break;
            case "3":
                string result = obj.data[1..];
                if (bool.TryParse(result, out bool isOk))
                {
                    if (isOk) pairung.rival.CurrCamp = pairung.self.CurrCamp = pairung.self.CurrCamp == ChessCardCamp.BlackCamp ? ChessCardCamp.WhiteCamp : ChessCardCamp.BlackCamp;
                    Global.Instance.EventManager.Publish(new EventServerDataResult() { DataHeader = DataHeaderInfo.Revocation, Data = new object[] { rivalName, $"4{result}" } });
                }
                break;
        }
    }
    else
    {
        Global.Instance.EventManager.Publish(new Model.EventParam.EventServerDataResult() { DataHeader = DataHeaderInfo.Message, Data = new object[] { obj.name, msg } });
    }
}

private bool Revocation(string name, out (PlayerInfo? self, PlayerInfo? rival) result, out string msg)
{
    result = (null, null);
    msg = string.Empty;
    var pairungList = DataManager.Instance.GetPairungList();
    var exists = pairungList.FirstOrDefault(q => q.user1?.Name == name || q.user2?.Name == name);
    if (exists.user1 is null || exists.user2 is null)
    {
        msg = "请先找对手哈!";
        return false;
    }

    var _pairung = pairungList.FirstOrDefault(q => q.user2?.Name == name);

    if (_pairung.user1 is not null && _pairung.user2 is not null)
        result = (_pairung.user2, _pairung.user1);
    else
        result = exists;

    if (result.self?.State == PlayerState.Free || result.rival?.State == PlayerState.Free)
    {
        msg = "您还没有开始呢!";
        return false;
    }

    if (result.self?.State == PlayerState.Prepare || result.rival?.State == PlayerState.Prepare)
    {
        msg = "刚刚准备好,你悔哪门子的棋!";
        return false;
    }

    //if (result.self?.CurrCamp == result.self?.Camp)
    //{
    //    msg = "你不能撤销!";
    //    return false;
    //}

    return true;
}

认输

private void GiveupParse_DataThreadCallback((string name, string data) obj)
{
    //命令协议----data   1:请求,发起   2: 询问对方 3:对方返回结果 true: 同意  false:不同意 4: 结果应答 true: 同意  false:不同意
    if (string.IsNullOrEmpty(obj.data)) return;
    if (Giveup(obj.name, out (PlayerInfo? self, PlayerInfo? rival) pairung, out string msg))
    {
        string code = obj.data[..1];
        string rivalName = pairung.rival?.Name ?? "";
        switch (code)
        {
            case "1":
                //if (pairung.self.CurrCamp != pairung.self.Camp)
                Global.Instance.EventManager.Publish(new EventServerDataResult() { DataHeader = DataHeaderInfo.Giveup, Data = new object[] { rivalName, "2" } });
                //else
                //Global.Instance.EventManager.Publish(new EventServerDataResult() { DataHeader = DataHeaderInfo.Message, Data = new object[] { obj.name, "你不能悔棋!" } });
                break;
            case "3":
                string result = obj.data[1..];
                if (bool.TryParse(result, out bool isOk))
                {
                    if (isOk)
                    {
                        (pairung.self.State, pairung.rival.State) = (PlayerState.Free, PlayerState.Free);
                        //Global.Instance.EventManager.Publish(new EventServerDataResult() { DataHeader = DataHeaderInfo.Giveup, Data = new object[] { rivalName, $"4{result}" } });
                        Global.Instance.EventManager.Publish(new EventServerDataResult() { DataHeader = DataHeaderInfo.Message, Data = new object[] { obj.name, $"对方已认输!" } });

                        Global.Instance.EventManager.Publish(new EventServerDataResult() { DataHeader = DataHeaderInfo.Message, Data = new object[] { rivalName, $"对方同意你认输!" } });
                    }
                    else
                    {
                        Global.Instance.EventManager.Publish(new EventServerDataResult() { DataHeader = DataHeaderInfo.Message, Data = new object[] { rivalName, $"对方不同意你认输!" } });
                    }
                }
                break;
        }
    }
    else
    {
        Global.Instance.EventManager.Publish(new EventServerDataResult()
        {
            DataHeader = DataHeaderInfo.Message,
            Data = new object[] { obj.name, msg }
        });
    }
}

private bool Giveup(string name, out (PlayerInfo? self, PlayerInfo? rival) result, out string msg)
{
    result = (null, null);
    msg = string.Empty;
    var pairungList = DataManager.Instance.GetPairungList();
    var exists = pairungList.FirstOrDefault(q => q.user1?.Name == name || q.user2?.Name == name);
    if (exists.user1 is null || exists.user2 is null)
    {
        msg = "请先找对手哈!";
        return false;
    }

    var _pairung = pairungList.FirstOrDefault(q => q.user2?.Name == name);

    if (_pairung.user1 is not null && _pairung.user2 is not null)
        result = (_pairung.user2, _pairung.user1);
    else
        result = exists;

    if (result.self.State == PlayerState.Free || result.rival.State == PlayerState.Free)
    {
        msg = "还没有开始!";
        return false;
    }
    if (result.self.State == PlayerState.Prepare || result.rival.State == PlayerState.Prepare)
    {
        msg = "刚开始, 认什么输, 相信自己!";
        return false;
    }
    return true;
}

逃跑

private void RunawayParse_DataThreadCallback((string name, string data) obj)
{
    if (Runaway(obj.name, out (PlayerInfo? self, PlayerInfo? rival) result, out string msg))
    {
        string rivalName = result.rival?.Name ?? "";
        Global.Instance.EventManager.Publish(new Model.EventParam.EventServerDataResult() { DataHeader = DataHeaderInfo.Message, Data = new object[] { rivalName, $"你的对手逃跑了!" } });

        Global.Instance.EventManager.Publish(new Model.EventParam.EventServerDataResult() { DataHeader = DataHeaderInfo.Runaway, Data = new object[] { rivalName, $"" } });
        Global.Instance.EventManager.Publish(new Model.EventParam.EventServerDataResult() { DataHeader = DataHeaderInfo.Runaway, Data = new object[] { obj.name, $"" } });
    }
    else
    {
        Global.Instance.EventManager.Publish(new EventServerDataResult()
        {
            DataHeader = DataHeaderInfo.Message,
            Data = new object[] { obj.name, msg }
        });
    }
}

private bool Runaway(string name, out (PlayerInfo? self, PlayerInfo? rival) result, out string msg)
{
    result = (null, null);
    msg = string.Empty;
    var pairungList = DataManager.Instance.GetPairungList();
    var exists = pairungList.FirstOrDefault(q => q.user1?.Name == name || q.user2?.Name == name);
    if (exists.user1 is null || exists.user2 is null)
    {
        msg = "请先找对手哈!";
        return false;
    }

    var _pairung = pairungList.FirstOrDefault(q => q.user2?.Name == name);

    if (_pairung.user1 is not null && _pairung.user2 is not null)
        result = (_pairung.user2, _pairung.user1);
    else
        result = exists;

    pairungList.Remove(exists);

    return true;
}

源码下载地址:Fivesonchess C#云原生 Winform在线五子棋

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值