6 major server modules (PdkFriendServer/GlobalSever/ServerCore/GameModule/GameNetModule) + game logic (GameFix/GameDAL/ServerData) + network layer (NetWorkMessage) + data layer (ObjectModel) + utilities (MrWu/Core/Config/CloudAPI/dll) + adapters (zyxAdapter/base) .NET 8.0 C# solution, 16 projects, 958 source files
349 lines
14 KiB
C#
349 lines
14 KiB
C#
using ObjectModel.Tool;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using GameFix.Poker;
|
||
using GameMessage.PaoDeKuaiF;
|
||
using GameFix.PaoDeKuaiF;
|
||
|
||
namespace PdkFriendServer.Logic
|
||
{
|
||
|
||
public partial class PdkGameMain
|
||
{
|
||
/// <summary>
|
||
/// 随机值
|
||
/// </summary>
|
||
public readonly Random Random = new Random(unchecked((int)DateTime.UtcNow.Ticks));
|
||
|
||
/// <summary>
|
||
/// 发牌
|
||
/// </summary>
|
||
public void InitCard()
|
||
{
|
||
/*1、经典玩法(必压)、--经典玩法(16张玩法):一副牌,去掉大小王、三个2(保留黑桃2)和黑桃 A ,共48张,每人16张
|
||
15张玩法(必压)、--15张玩法(有大必压):一副牌,去掉大小王、三个2(保留黑桃2)和三个A(保留黑桃 A ),去掉一个K,共45张,每人15张
|
||
关牌(不必压) --一副牌,去掉大小王、三个2(保留黑桃2)和黑桃 A ,共48张,每人16张*/
|
||
byte count = 0;//每个人分多少张牌
|
||
int del2 = 3; //删除2的张数
|
||
int delA = 1;//删除A的张数
|
||
int delK = 3;//删除K的张数
|
||
TCardInfoPdkF[] allCards = null; //初始化牌库
|
||
if (Rule.JingDianWanFa || Rule.GuanPai)
|
||
{
|
||
count = 16;
|
||
delK = 0;
|
||
allCards = new TCardInfoPdkF[48];
|
||
}
|
||
if (Rule.Zhang15)
|
||
{
|
||
delA = 3;
|
||
delK = 1;
|
||
count = 15;
|
||
allCards = new TCardInfoPdkF[45];
|
||
}
|
||
int idx = 0;
|
||
for (byte i = 1; i <= 52; i++)
|
||
{
|
||
PukeTool.ConvertCard(i, out var flower, out var num);
|
||
if (del2 > 0 && num == 2 && flower != 1)
|
||
{
|
||
del2--;
|
||
continue;
|
||
}
|
||
if (delA > 0 && num == 1 && flower != 1)
|
||
{
|
||
delA--;
|
||
continue;
|
||
}
|
||
if (delK > 0 && num == 13 && flower != 1)
|
||
{
|
||
delK--;
|
||
continue;
|
||
}
|
||
allCards[idx].ID = i;
|
||
allCards[idx].Flower = (byte)flower;
|
||
allCards[idx].Num = (byte)num;
|
||
allCards[idx].GameNum = (byte)(num == 1 ? 14 : num == 2 ? 16 : num);
|
||
allCards[idx].GameOwer = 0;
|
||
allCards[idx].Score = 0;
|
||
allCards[idx].GameState = 1;
|
||
idx++;
|
||
}
|
||
for (byte i = 1; i < GamePack.Info.PlayNum; i++)
|
||
{
|
||
PukeTool.ShuffleArray(ref allCards, Random);
|
||
}
|
||
idx = 0;
|
||
//给玩家发牌
|
||
int hei3Wei = -1;//黑桃三发牌的位置
|
||
if (logicMemory.WarCount == 0 && Rule.HeiTao3BiChu)
|
||
{//如果是首局而且是每局黑桃三必出,则第一局必须要发黑桃三
|
||
hei3Wei = Random.Next(0, GamePack.Info.PlayNum);
|
||
}
|
||
if (hei3Wei >= 0)
|
||
{ //要发黑桃3
|
||
List<TCardInfoPdkF> cards = allCards.ToList();
|
||
for (int i = 0; i < GamePack.Info.PlayNum; i++)
|
||
{
|
||
GamePack.CardPack.Cards[i].Init(count);
|
||
int j = 0;
|
||
while (j < count)
|
||
{
|
||
if (j == 0 && i == hei3Wei)
|
||
{
|
||
TCardInfoPdkF temp = cards.Find(x => x.GameNum == 3 && x.Flower == 1);
|
||
if (temp.ID > 0)
|
||
{
|
||
this.GamePack.CardPack.Cards[i].CardInfos[j] = temp;
|
||
cards.Remove(temp);
|
||
}
|
||
else
|
||
{ //如果没有找到,说明黑桃3已经被别人拿走了,就不找了。
|
||
this.GamePack.CardPack.Cards[i].CardInfos[j] = cards[0];
|
||
cards.RemoveAt(0);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
this.GamePack.CardPack.Cards[i].CardInfos[j] = cards[0];
|
||
cards.RemoveAt(0);
|
||
}
|
||
j++;
|
||
}
|
||
GamePack.Info.ShenYuCard[i] = count;
|
||
}
|
||
}
|
||
else
|
||
{ //以前写法
|
||
for (int i = 0; i < GamePack.Info.PlayNum; i++)
|
||
{
|
||
GamePack.CardPack.Cards[i].Init(count);
|
||
for (int j = 0; j < count; j++)
|
||
{
|
||
this.GamePack.CardPack.Cards[i].CardInfos[j] = allCards[idx++];
|
||
}
|
||
GamePack.Info.ShenYuCard[i] = count;
|
||
}
|
||
}
|
||
for (int i = 0; i < GamePack.Info.PlayNum; i++)
|
||
{
|
||
SortWanJiaPaiByGameNum(i + 1);
|
||
#if DEBUG
|
||
if (this.DeskGameDo == null)
|
||
{
|
||
Log($"-------------{(i + 1)}开始-----------------------------");
|
||
for (int j = 0; j < this.GamePack.CardPack.Cards[i].CardInfos.Length; j++)
|
||
{
|
||
Log(this.GamePack.CardPack.Cards[i].CardInfos[j].ToString());
|
||
}
|
||
}
|
||
#endif
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 排序某个玩家手牌,按游戏中的大小排序
|
||
/// </summary>
|
||
/// <param name="pos">玩家位置从1开始</param>
|
||
void SortWanJiaPaiByGameNum(int pos)
|
||
{
|
||
if (pos <= 0 || pos > GamePack.Info.PlayNum) throw new Exception($"参数错误 pos:{pos}");
|
||
pos--;
|
||
Array.Sort(this.GamePack.CardPack.Cards[pos].CardInfos, (x, y) => (y.GameNum * 10 - y.Flower).CompareTo((x.GameNum * 10 - x.Flower)));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置玩家出牌
|
||
/// </summary>
|
||
/// <param name="pos"></param>
|
||
/// <param name="ids"></param>
|
||
void SetCardToOut(int pos, byte[] ids)
|
||
{
|
||
if (ids == null || ids.Length <= 0) return;
|
||
if (pos <= 0 || pos > GamePack.Info.PlayNum) throw new Exception($"参数错误 pos:{pos}");
|
||
pos--;
|
||
GamePack.Info.ShenYuCard[pos] = (byte)(GamePack.Info.ShenYuCard[pos] - ids.Length);
|
||
foreach (var id in ids)
|
||
{
|
||
for (int i = 0; i < this.GamePack.CardPack.Cards[pos].CardInfos.Length; i++)
|
||
{
|
||
if (this.GamePack.CardPack.Cards[pos].CardInfos[i].ID == id)
|
||
{
|
||
this.GamePack.CardPack.Cards[pos].CardInfos[i].GameState = 0;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
#if DEBUG
|
||
Log($"---------------------{(pos + 1)}----- shengyu:{GamePack.Info.ShenYuCard[pos]}-------------");
|
||
//for (int i = 0; i < this.GamePack.CardPack.Cards[pos].CardInfos.Length; i++)
|
||
//{
|
||
// if (this.GamePack.CardPack.Cards[pos].CardInfos[i].GameState == 0) continue;
|
||
// Log(this.GamePack.CardPack.Cards[pos].CardInfos[i].ToString());
|
||
//}
|
||
#endif
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 根据牌的绝对Id返回牌的详细信息
|
||
/// </summary>
|
||
/// <param name="pos">玩家位置从1开始</param>
|
||
/// <param name="ids">牌的Id集合</param>
|
||
/// <returns></returns>
|
||
TCardInfoPdkF[] GetCardByIds(int pos, byte[] ids)
|
||
{
|
||
if (ids == null || ids.Length <= 0) return null;
|
||
if (pos <= 0 || pos > GamePack.Info.PlayNum) return null;
|
||
pos--;
|
||
return PokerLogic.GetCardByIds(GamePack.CardPack.Cards[pos].CardInfos, ids);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 计算玩家炸弹个数
|
||
/// </summary>
|
||
/// <param name="pos">玩家位置,从0开始</param>
|
||
/// <returns></returns>
|
||
byte CalcPlayBombRule(int pos)
|
||
{
|
||
if (pos < 0 || pos >= GamePack.Info.PlayNum) return 0;
|
||
Dictionary<int, int> dic = new Dictionary<int, int>();
|
||
foreach (var item in GamePack.CardPack.Cards[pos].CardInfos)
|
||
{
|
||
if (dic.ContainsKey(item.GameNum))
|
||
{
|
||
dic[item.GameNum]++;
|
||
}
|
||
else
|
||
{
|
||
dic[item.GameNum] = 1;
|
||
}
|
||
}
|
||
byte result = 0;
|
||
foreach (var item in dic)
|
||
{
|
||
if (item.Value <= 2) continue;
|
||
if (Rule.AAAIsZhaDan && item.Key == 14 && item.Value == 3)
|
||
{
|
||
result++;
|
||
continue;
|
||
}
|
||
if (item.Value == 4)
|
||
{
|
||
result++;
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检测玩家的飞机,如果有4连以上的飞机就需要换牌
|
||
/// </summary>
|
||
/// <param name="pos"></param>
|
||
/// <returns></returns>
|
||
void CheckFeiJi()
|
||
{
|
||
try
|
||
{
|
||
int pos = -1; //有4连飞机的位置
|
||
List<int> feiji = null;
|
||
for (int j = 0; j < GamePack.Info.PlayNum; j++)
|
||
{
|
||
feiji = GetFeiJiCount(GamePack.CardPack.Cards[j].CardInfos);
|
||
if (feiji != null && feiji.Count > 3)
|
||
{
|
||
pos = j;
|
||
Log($"飞机数量:{string.Join(",", feiji)},飞机位置:{pos + 1},房号:{this.DeskGameDo.desk.deskinfo.roomNum}", MrWu.Debug.DebugLevel.Warning);
|
||
break;
|
||
}
|
||
}
|
||
if (pos < 0) return;
|
||
for (int i = 0; i < GamePack.Info.PlayNum; i++)
|
||
{
|
||
if (i != pos)
|
||
{
|
||
int idx = -1;
|
||
for (int j = 0; j < GamePack.CardPack.Cards[pos].CardInfos.Length; j++)
|
||
{
|
||
if (GamePack.CardPack.Cards[pos].CardInfos[j].GameNum == feiji[2])
|
||
{
|
||
idx = j;
|
||
break;
|
||
}
|
||
}
|
||
if (idx < 0)
|
||
{
|
||
Log($"没有找到4连飞机的下标日:{idx}", MrWu.Debug.DebugLevel.Warning);
|
||
return;
|
||
}
|
||
for (int i3 = 0; i3 < GamePack.CardPack.Cards[i].CardInfos.Length - 1; i3++)
|
||
{
|
||
//交换其中一张牌
|
||
TCardInfoPdkF temp = GamePack.CardPack.Cards[i].CardInfos[i3];
|
||
if (feiji.IndexOf(temp.GameNum) >= 0) continue; //换的牌不能是飞机的牌,要不容易重复和换出新的炸弹
|
||
Log($"换牌信息:{temp.GameNum}", MrWu.Debug.DebugLevel.Warning);
|
||
GamePack.CardPack.Cards[i].CardInfos[i3] = GamePack.CardPack.Cards[pos].CardInfos[idx];
|
||
GamePack.CardPack.Cards[pos].CardInfos[idx] = temp;
|
||
for (int i2 = 0; i2 < GamePack.Info.PlayNum; i2++)
|
||
{
|
||
SortWanJiaPaiByGameNum(i2 + 1);
|
||
}
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Log($"CheckFeiJi msg:{e.Message}, code:{e.StackTrace}", MrWu.Debug.DebugLevel.Error);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取一个玩家的飞机牌型
|
||
/// </summary>
|
||
/// <param name="selectCards">玩家手里的牌</param>
|
||
/// <returns>玩家的飞机集合</returns>
|
||
public static List<int> GetFeiJiCount(TCardInfoPdkF[] selectCards)
|
||
{
|
||
if (selectCards == null || selectCards.Length < 6) return null;
|
||
List<PokerLogic.XY> list = new List<PokerLogic.XY>();
|
||
foreach (var item in selectCards)
|
||
{
|
||
var t = list.Find(x => x.x == item.GameNum);
|
||
if (t != null)
|
||
{
|
||
t.y++;
|
||
}
|
||
else
|
||
{
|
||
list.Add(new PokerLogic.XY { x = item.GameNum, y = 1 });
|
||
}
|
||
}
|
||
int num = list.Count(x => x.y >= 3);
|
||
if (num < 2) return null;
|
||
list = list.Where(x => x.y >= 3).ToList();
|
||
List<int> fj = new List<int>();
|
||
for (int i = 0; i < list.Count - 1; i++)
|
||
{
|
||
if (list[i].x - 1 == list[i + 1].x)
|
||
{
|
||
if (!fj.Contains(list[i].x))
|
||
{
|
||
fj.Add(list[i].x);
|
||
}
|
||
if (!fj.Contains(list[i + 1].x))
|
||
{
|
||
fj.Add(list[i + 1].x);
|
||
}
|
||
}
|
||
}
|
||
return fj;
|
||
}
|
||
}
|
||
}
|