/// <summary>
        /// 打牌
        /// </summary>
        /// <param name="player">玩家</param>
        /// <param name="card">要打的牌</param>
        /// <returns>成功状态</returns>
        public bool PlayCard(int player, MahjongCard card)
        {
            // 只有当前的玩家可以打牌
            if (player == Playing)
            {
                // 获得当前玩家手牌
                List <MahjongCard> player_onhand = GetPlayerCardOnHand(player);

                // 只能从手牌中打出牌来
                IEnumerable <MahjongCard> card_to_play = from c in player_onhand where c == card select c;
                if (card_to_play.Count() == 0)
                {
                    return(false);
                }

                // 玩家打出牌
                GetPlayerInfo(player).PlayCard(card_to_play.First());

                // 向游戏线程发送完成请求
                gameStateMachine.SetState(GameStateMachine.State.SendPlayerAction);
                gameStateMachine.ReleaseSemaphore();

                return(true);
            }

            return(false);
        }
Example #2
0
        /// <summary>
        /// 能够荣和计算(根据当前所有玩家的听牌)
        /// </summary>
        private List <RonAble> isCanRon()
        {
            // 获得刚刚打牌的玩家的牌河和打出的牌
            List <MahjongCard> played_cards = GetPlayerCardPlayed(Playing);
            MahjongCard        last_played  = played_cards.Last(); // 最后一张

            // 比对其他三家的手牌
            List <RonAble> ronAbles = new List <RonAble>();

            // 遍历所有其它玩家
            for (int player = 0; player < 4; player++)
            {
                if (player == Playing)
                {
                    continue; // 跳过自己
                }

                // 获得玩家信息
                PlayerInfo info = player_info[player];

                // 先查询振听状态,如果振听则不能荣和
                if (info.waiting_tsumo == WaitingTsumo.None)
                {
                    // 查询是否是被听的牌
                    IEnumerable <MahjongCard> huCard = from card in info.waiting where card == last_played select card;

                    if (huCard.Count() > 0)
                    {
                        ronAbles.Add(new RonAble(player, last_played));
                    }
                }
            }

            return(ronAbles);
        }
        /// <summary>
        /// 向牌河中打一张牌
        /// </summary>
        /// <param name="card">要打的牌</param>
        public void PlayCard(MahjongCard card)
        {
            // 将牌从手牌打到牌河
            card_played.Add(card);

            // 从手牌中删除这张牌
            card_onhand.Remove(card);
        }
        public static void InitializeMahjongClass()
        {
            Assembly assembly            = Assembly.GetExecutingAssembly();
            string   Path                = (from path in assembly.GetManifestResourceNames() where path.Contains(ResoursePath) select path).First();
            Stream   xStream             = assembly.GetManifestResourceStream(Path);
            XElement xElement            = XElement.Load(xStream);
            IEnumerable <XElement> cards = xElement.Elements("cards").Elements("card");

            CardInfo.Clear();

            foreach (XElement card in cards)
            {
                MahjongCard mahjongCard = new MahjongCard
                {
                    name   = (MahjongCardName)Enum.Parse(typeof(MahjongCardName), card.Element("name").Value),
                    type   = (MahjongCardType)Enum.Parse(typeof(MahjongCardType), card.Element("type").Value),
                    c_name = card.Element("c_name").Value,
                    yao9   = card.Element("yao9").Value.Equals("true") ? true : false,
                    group  = (MahjongCardGroupType)Enum.Parse(typeof(MahjongCardGroupType), card.Element("group").Value),
                };


                if (mahjongCard.yao9)
                {
                    mahjongCard.treasure = 0;
                }
                else
                {
                    mahjongCard.treasure = card.Element("treasure").Value.Equals("true") ? 1 : 0;
                }

                if (mahjongCard.type == MahjongCardType.Char)
                {
                    mahjongCard.squad = (MahjongCardSquadType)Enum.Parse(typeof(MahjongCardSquadType), card.Element("squad").Value);
                    mahjongCard.grade = (MahjongCardGradeType)Enum.Parse(typeof(MahjongCardGradeType), $"G{card.Element("grade").Value}");
                }
                CardInfo.Add(mahjongCard);
            }

            IEnumerable <XElement> yakus = xElement.Elements("yakus").Elements("yaku");

            YakuInfo.Clear();

            foreach (XElement yaku in yakus)
            {
                MahjongYaku mahjongYaku = new MahjongYaku()
                {
                    type    = (MahjongYakuType)Enum.Parse(typeof(MahjongYakuType), yaku.Element("name").Value),
                    c_name  = yaku.Element("c_name").Value,
                    level   = Convert.ToInt32(yaku.Element("level").Value),
                    no_furu = yaku.Element("nofuru").Value.Equals("true") ? true : false,
                    furu_n  = yaku.Element("furun").Value.Equals("true") ? true : false,
                };

                YakuInfo.Add(mahjongYaku);
            }
        }
Example #5
0
        /// <summary>
        /// 根据指示牌添加宝牌
        /// </summary>
        /// <param name="indicator">指示牌</param>
        private void _add_treasure_card(MahjongCard indicator)
        {
            int t = 0;

            // 将指示牌添加到指示牌列表
            card_indicator.Add(indicator);

            // 获得指示牌的下一张牌
            if (indicator.type == MahjongCardType.Char)
            {
                // 如果是角色牌,则使用官方排序
                // 每种角色9张
                t = (int)indicator.name + 1;
                if ((t == 0x0A) || (t == 0x14) || (t == 0x1E))
                {
                    t -= 9;
                }
            }
            else
            {
                // 如果是应援角色牌,团体牌,则使用自定义排序
                t = (int)indicator.name + 1;
                if (t == 0x22)
                {
                    t -= 3;
                }

                if (t == 0x25)
                {
                    t -= 2;
                }

                if (t == 0x31)
                {
                    t -= 5;
                }
            }

            // 从所有的牌中找到宝牌,将其的宝牌等级+1
            // 先从牌山找
            for (int i = 0; i < card_stacks.Count(); i++)
            {
                // 确认宝牌
                if (t == (int)card_stacks[i].name)
                {
                    card_stacks[i].AddTreasure();
                }
            }

            // 从手牌和副露里找
            for (int i = 0; i < 4; i++)
            {
                player_info[i].SetTreasureCard((MahjongCardName)t);
            }
        }
Example #6
0
        /// <summary>
        /// 摸牌(从牌山取得一张牌)
        /// </summary>
        private MahjongCard TouchCard()
        {
            // 获得牌山顶的牌
            MahjongCard card = card_stacks.First();

            // 从牌山中删除这张牌
            card_stacks.RemoveAt(0);

            // 只要摸牌就加巡数
            round++;

            // 返回所需的牌
            return(card);
        }
 /// <summary>
 /// 创建一个可荣牌组
 /// </summary>
 public RonAble(int playerId, MahjongCard RonCard)
 {
     this.playerId = playerId;
     this.RonCard  = RonCard;
 }
 /// <summary>
 /// 向手牌中加入一张牌
 /// </summary>
 /// <param name="card">要加入的牌</param>
 public void AddHandCard(MahjongCard card) => card_onhand.Add(card);
Example #9
0
        private void GamingThread()
        {
            // 多线程状态机
            for (; ;)
            {
                // 等待信号量
                gameStateMachine.WaitSemaphore();

                switch (gameStateMachine.status)
                {
                case GameStateMachine.State.Idle:

                    break;

                case GameStateMachine.State.WaitPlayerAction:

                    break;

                case GameStateMachine.State.SendPlayerAction:
                    // 创建响应
                    List <PlayerAction> playerActions = new List <PlayerAction>();

                    // 判定荣和
                    List <RonAble> RonAbles = isCanRon();
                    if (RonAbles.Count() > 0)
                    {
                        // 发出可以荣和的消息到玩家
                        // 先根据玩家编号分类
                        IEnumerable <RonAble> player_ronable = from ronable in RonAbles group ronable by ronable.playerId into g select g.First();

                        foreach (RonAble ronable in player_ronable)
                        {
                            playerActions.Add(new PlayerAction(ronable));
                        }
                    }

                    // 判定鸣牌的可能性
                    List <FuruAble> Furuables = isCanFuru();
                    if (Furuables.Count > 0)
                    {
                        // 发出可以鸣牌的消息到玩家
                        // 先根据玩家编号分类
                        IEnumerable <FuruAble> player_furuable = from furuable in Furuables group furuable by furuable.playerId into g select g.First();

                        foreach (FuruAble furuable in player_furuable)
                        {
                            foreach (MahjongCardFuru furu in furuable.FuruableList)
                            {
                                playerActions.Add(new PlayerAction(furu, furuable.playerId));
                            }
                        }
                    }

                    // 清空动作预备列表
                    PrepareActionsList.Clear();

                    // 打开玩家动作通道
                    gameStateMachine.OpenPlayerActionChannel();

                    if (playerActions.Count > 0)
                    {
                        // 保存可能的玩家操作列表
                        PlayerActionsList = (from act in playerActions group act by act.playerId into g select g).ToList();

                        // 获得用户响应,将向其他用户广播其响应
                        // 使用响应回调函数
                        PlayerActionResponseCallback(playerActions);

                        // 进入接受用户响应的状态
                        gameStateMachine.SetState(GameStateMachine.State.AcceptingPlayerAction);
                    }
                    else
                    {
                        // 进入用户响应执行状态(跳过)
                        AcceptedPlayerActions.Clear();
                        gameStateMachine.SetState(GameStateMachine.State.ExecutePlayerAction);
                        gameStateMachine.ReleaseSemaphore();
                    }
                    break;

                case GameStateMachine.State.AcceptingPlayerAction:
                    // 取出队列
                    PlayerAction action = gameStateMachine.GetPlayerAction();

                    // 加入动作列表
                    PrepareActionsList.Add(action);

                    // 从可用列表中删除所有该玩家其他操作
                    PlayerActionsList.RemoveAll((match) => match.Key == action.playerId);

                    // 遍历其他所有动作进行优先级比对
                    bool isHighestPriority = true;
                    foreach (IGrouping <int, PlayerAction> player in PlayerActionsList)
                    {
                        foreach (PlayerAction player_act in player)
                        {
                            if (player_act.Priority < action.Priority)
                            {
                                isHighestPriority = false;
                                break;
                            }
                        }
                        if (isHighestPriority)
                        {
                            break;
                        }
                    }

                    if (isHighestPriority || (PlayerActionsList.Count == 0))
                    {
                        // 最高优先级
                        // 关闭动作通道
                        gameStateMachine.ClosePlayerActionChannel();

                        // 处理动作列表
                        int highestPriority = PrepareActionsList.Min((selector) => (selector.Priority));
                        IEnumerable <PlayerAction> accept_list = PrepareActionsList.FindAll((match) => (match.Priority == highestPriority) && (match.actionType != PlayerActionType.Cancel));
                        IEnumerable <PlayerAction> refuse_list = PrepareActionsList.Except(accept_list);

                        AcceptedPlayerActions = accept_list.ToList();

                        foreach (PlayerAction act in accept_list)
                        {
                            // 接受这些请求
                            PlayerActionAcceptedCallback(act.playerId, true);
                        }

                        foreach (PlayerAction act in refuse_list)
                        {
                            // 拒绝/取消这些请求
                            PlayerActionAcceptedCallback(act.playerId, false);
                        }

                        // 将没有反应(被忽略)的玩家拒绝
                        for (int i = 0; i < 4; i++)
                        {
                            if (i == Playing)
                            {
                                continue;
                            }
                            if (PrepareActionsList.FindIndex((match) => match.playerId == i) < 0)
                            {
                                PlayerActionAcceptedCallback(i, false);
                            }
                        }

                        // 进入执行玩家操作状态
                        gameStateMachine.SetState(GameStateMachine.State.ExecutePlayerAction);
                        gameStateMachine.ReleaseSemaphore();
                    }

                    break;

                case GameStateMachine.State.ExecutePlayerAction:
                    if (AcceptedPlayerActions.Count == 0)
                    {
                        // 没有接受的操作,直接跳转到下家
                        _NextPlayer();

                        gameStateMachine.SetState(GameStateMachine.State.Idle);
                    }
                    else
                    {
                        foreach (PlayerAction act in AcceptedPlayerActions)
                        {
                            switch (act.actionType)
                            {
                            case PlayerActionType.Ron:
                            case PlayerActionType.Tsumo:
                                // 和牌

                                break;

                            case PlayerActionType.ChiGrade:
                            case PlayerActionType.ChiSquad:
                            case PlayerActionType.Pong:
                            case PlayerActionType.Kong:
                            case PlayerActionType.Kong_Self:
                            case PlayerActionType.Kong_Add:
                                // 副露
                                // 获得刚刚打牌的玩家的牌河和打出的牌
                                List <MahjongCard> played_cards = GetPlayerCardPlayed(Playing);
                                MahjongCard        last_played  = played_cards.Last(); // 最后一张

                                // 副露对象和副露者
                                int target      = Playing;
                                int furu_player = act.playerId;

                                // 新的副露
                                MahjongCardFuru furu = new MahjongCardFuru()
                                {
                                    target = target,
                                    type   = ActionTypeToFuruType(act.actionType),
                                    cards  = new List <MahjongCard>(),
                                };

                                // 组成副露牌组
                                foreach (MahjongCard card in act.effectCards)
                                {
                                    furu.cards.Add(card);

                                    // 从手牌中删除
                                    player_info[furu_player].card_onhand.Remove(card);
                                }

                                furu.cards.Add(last_played);

                                // 添加到玩家副露
                                player_info[furu_player].card_furu.Add(furu);

                                // 从目标玩家牌河删除
                                player_info[target].card_played.RemoveAt(player_info[target].card_played.Count - 1);

                                // 直接跳转到副露家
                                _ToPlayer(furu_player);

                                gameStateMachine.SetState(GameStateMachine.State.Idle);

                                break;
                            }
                        }
                    }
                    break;

                case GameStateMachine.State.Exit:
                    return;
                }
            }
        }
Example #10
0
        /// <summary>
        /// 能够鸣牌计算
        /// </summary>
        private List <FuruAble> isCanFuru()
        {
            // 获得刚刚打牌的玩家的牌河和打出的牌
            List <MahjongCard> played_cards = GetPlayerCardPlayed(Playing);
            MahjongCard        last_played  = played_cards.Last(); // 最后一张

            // 比对其他三家的手牌
            List <FuruAble> furuAbles = new List <FuruAble>();

            // 记录是否有玩家可以碰或者杠以减少不必要的计算
            bool hasPongKong = false;

            // 遍历所有其它玩家
            for (int player = 0; player < 4; player++)
            {
                if (player == Playing)
                {
                    continue; // 跳过自己
                }

                // 获得手牌
                List <MahjongCard> player_hand = GetPlayerCardOnHand(player);

                // 记录可副露牌组
                FuruAble furuAble = new FuruAble(player);

                // 如果已经有别的玩家可以碰杠,则不可能再有玩家可以碰杠
                if (hasPongKong == false)
                {
                    // 优先找出杠子和刻子
                    IEnumerable <MahjongCard> PongKong = from card in player_hand where card == last_played select card;
                    if (PongKong.Count() >= 2)
                    {
                        hasPongKong = true;

                        // 可以碰
                        furuAble.FuruableList.Add(new MahjongCardFuru()
                        {
                            cards  = Enumerable.Repeat(last_played, 2).ToList(),
                            target = Playing,
                            type   = FuruType.Pong,
                        });

                        if (PongKong.Count() == 3)
                        {
                            // 可以杠
                            furuAble.FuruableList.Add(new MahjongCardFuru()
                            {
                                cards  = Enumerable.Repeat(last_played, 3).ToList(),
                                target = Playing,
                                type   = FuruType.Kong,
                            });
                            hasPongKong = true;
                        }
                    }
                }


                if (last_played.type == MahjongCardType.Char)
                {
                    // 年级和小组顺子(吃)
                    // 年级顺子
                    MahjongCardName      name  = last_played.name;
                    MahjongCardGradeType grade = last_played.grade;
                    MahjongCardGroupType group = last_played.group;
                    IEnumerable <IGrouping <MahjongCardName, MahjongCard> > grade_chi = from card in player_hand
                                                                                        where (card.grade == grade) && (card.name != name) &&
                                                                                        (card.type == MahjongCardType.Char) && (card.@group == @group)
                                                                                        group card by card.name into g
                                                                                        select g;
                    if (grade_chi.Count() == 2)
                    {
                        // 至少要有两种同年级的牌才可以吃
                        // 获得要吃的牌
                        List <MahjongCard> chi = new List <MahjongCard>();
                        foreach (IGrouping <MahjongCardName, MahjongCard> cards in grade_chi)
                        {
                            chi.Add(cards.First());
                        }

                        // 加入可副露列表
                        furuAble.FuruableList.Add(new MahjongCardFuru()
                        {
                            cards  = chi,
                            target = Playing,
                            type   = FuruType.ChiGrade,
                        });
                    }

                    // 小组顺子
                    MahjongCardSquadType squad = last_played.squad;
                    IEnumerable <IGrouping <MahjongCardName, MahjongCard> > squad_chi = from card in player_hand
                                                                                        where (card.squad == squad) && (card.name != name) && (card.type == MahjongCardType.Char)
                                                                                        group card by card.name into g
                                                                                        select g;
                    if (squad_chi.Count() == 2)
                    {
                        // 至少要有两种同小组的牌才可以吃
                        // 获得要吃的牌
                        List <MahjongCard> chi = new List <MahjongCard>();
                        foreach (IGrouping <MahjongCardName, MahjongCard> cards in squad_chi)
                        {
                            chi.Add(cards.First());
                        }

                        // 加入可副露列表
                        furuAble.FuruableList.Add(new MahjongCardFuru()
                        {
                            cards  = chi,
                            target = Playing,
                            type   = FuruType.ChiSquad,
                        });
                    }
                }
                furuAbles.Add(furuAble);
            }

            return(furuAbles);
        }
Example #11
0
        /// <summary>
        ///  和牌判定(除去雀头和副露)
        /// </summary>
        /// <param name="cards">手牌</param>
        /// <param name="start">从第几张手牌开始找刻子</param>
        /// <returns>是否和牌</returns>
        private bool isHu(List <MahjongCard> cards, int start, ref List <HuCard> huCard)
        {
            if (cards.Count == 0)
            {
                return(true); // 空牌和
            }

            if (cards.Count < 3)
            {
                return(false); // 剩牌不和
            }

            // 针对第一张牌开始寻找刻子和顺子
            IEnumerable <MahjongCard> u = from card in cards where card.name == cards[start].name select card;
            int count = u.Count();

            if (count >= 3)
            {
                // 将刻子加入牌组
                HuCard hucard = new HuCard()
                {
                    type  = HuCardType.PongKong,
                    furu  = false,
                    cards = new List <MahjongCard>()
                    {
                        cards[start], cards[start + 1], cards[start + 2]
                    },
                };
                huCard.Add(hucard);

                // 删除这个刻子
                for (int m = 0; m < 3; m++)
                {
                    cards.RemoveAt(start);
                }

                // 递归判和
                return(isHu(cards, ref huCard));
            }
            else
            {
                if (start + 1 < cards.Count)
                {
                    return(isHu(cards, start + 1, ref huCard));
                }
                else
                {
                    // 寻找顺子(年级和小组顺子)
                    MahjongCard cur_card = u.First();

                    // 获得牌种
                    MahjongCardType type = cur_card.type;

                    // 只有角色牌才可以凑成年级或小组顺子
                    if (type == MahjongCardType.Char)
                    {
                        // 获得团体、年级和小组信息
                        MahjongCardGroupType group = cur_card.group;
                        MahjongCardGradeType grade = cur_card.grade;
                        MahjongCardSquadType squad = cur_card.squad;

                        // 确认同团体的牌有至少三张
                        IEnumerable <MahjongCard> same_group = from card in cards where (card.name != cur_card.name) && (card.@group == @group) && (card.type == MahjongCardType.Char) select card;
                        if (same_group.Count() >= 2)
                        {
                            // 判断同年级/同小组
                            IEnumerable <MahjongCard> same_grade = from card in same_group where card.grade == grade select card;
                            IEnumerable <MahjongCard> same_squad = from card in same_group where card.squad == squad select card;
                            IEnumerable <MahjongCard> determine;

                            bool GradeOrSquad = false;
                            if (same_grade.Count() >= 2)
                            {
                                GradeOrSquad = false;
                                determine    = same_grade;         // 判断同年级
                            }
                            else if (same_squad.Count() >= 2)
                            {
                                GradeOrSquad = true;
                                determine    = same_squad; // 判断同小队
                            }
                            else
                            {
                                return(false);
                            }

                            // 每种牌只找出一张
                            IEnumerable <MahjongCard> not_same = from card in determine group card by card.name into g select g.First();

                            if (not_same.Count() >= 2)
                            {
                                MahjongCard[] not_same_cards = not_same.ToArray();

                                // 将顺子加入牌组
                                HuCard hucard = new HuCard()
                                {
                                    type  = (GradeOrSquad) ? HuCardType.SquadChi : HuCardType.GradeChi,
                                    furu  = false,
                                    cards = new List <MahjongCard>()
                                    {
                                        cur_card, not_same_cards[0], not_same_cards[1]
                                    },
                                };
                                huCard.Add(hucard);

                                // 从手牌中删除
                                bool p = true, q = true, r = true; // 防止重复删除
                                for (int i = 0; i < cards.Count; i++)
                                {
                                    if ((cards[i].name == cur_card.name) && p)
                                    {
                                        p = false; cards.RemoveAt(i); i--; continue;
                                    }
                                    if ((cards[i].name == not_same_cards[0].name) && q)
                                    {
                                        q = false; cards.RemoveAt(i); i--; continue;
                                    }
                                    if ((cards[i].name == not_same_cards[1].name) && r)
                                    {
                                        r = false; cards.RemoveAt(i); i--; continue;
                                    }
                                    if (!(p || q || r))
                                    {
                                        break;
                                    }
                                }

                                // 递归判和
                                return(isHu(cards, ref huCard));
                            }
                        }
                    }
                }

                return(false);
            }
        }