本文原创文章,转载注明出处,博客地址 https://segmentfault.com/u/to... 第一时间看后续精彩文章。觉得好的话,顺手分享到朋友圈吧,感谢支持。

笔者前段时间做过一款地方麻将游戏的后端,麻将游戏有个特点就是种类繁多,有的玩法木有癞子,有的玩法有4个癞子,有的甚至癞子数量更多,甚至有的有花牌(春夏秋冬等),有的红中可以代替宝牌,具体玩法笔者在此不介绍,做相关开发的自行研究玩法就好

查表法

笔者看过其它的算法思路,比如查表法,首先生成好麻将牌型的表存文件中,通过将牌型与文件中的牌型进行对比,此类算法,简单玩法效率也挺高

缺点:

  1. 是要提前生成好表文件,并且,由于麻将玩法种类繁多,对于复杂的玩法,表记录非常多,多达数百万条记录,虽然算法中有剪枝,但是效率仍然没有显著优势
  2. 表文件读入到内存中,长期占用大量内存
  3. 移植性弱,换一种玩法,就得重新生成表数据

在此笔者根据自己的经验总结出一种通用的麻将胡牌算法

思路

满足M x ABC + N x DDD + EE 即可胡牌

下面表述中的 3同即DDD牌型,3连即ABC牌型,一对将即EE

一个有136张牌,万,饼,条,东西南北中发白34种牌,有四个癞子是直接就胡牌的,最坏的情况是有3个癞子,如果把癞子分别当做其中一张牌,3个癞子有34x34x34=39304接近4万种排列组合,这种算法明显不好

从另外一个大的思路出发,将手牌分离成宝,万,条,筒,风5个一维数组(同类型牌才能形成整扑或将),先不管出癞子,我先计算出剩下的牌形成整扑一将(整扑即ABC或DDD,将即EE),至少需要多少癞子,如果需要的癞子数量小于或等于手上有的癞子数量,即可胡牌

这里刚开始就分成宝,万,条,筒,风5个一维数组的好处是:分类处理,简化后面的判断牌型逻辑,并且对于有花牌或其他特殊类型牌时,可根据玩法,适当调整或增加类型,容易扩展,通用处理方案,且单独提出函数,模块化,容易根据玩法修改

四种情况
  1. 将在[万]中,饼[风]必然是整扑
  2. 将在[饼]中,万[风]必然是整扑
  3. 将在[条]中,万[风]必然是整扑
  4. 将在[风]中,万[条]必然是整扑

那么问题来了,如何判断形成整扑,需要的最少癞子数量?

经过分析,必须从小到大排序后,先去3同,再去3连,再去2同,再去2连,这些最容易形成整扑的去掉后,然后剩下的每张牌都需要2癞子,这才能得到最少的癞子数量

2连:某张牌如果能和后面的牌差为1或2

2同:如某张牌和下张牌相等

麻将的数据结构

根据麻将牌的特别,通过百位数1,2,3,4,5区别牌类型,个位数代表具体哪张牌,方便后面算法中进行判断

整理代码如下:

其中包含了特殊玩法的 制飞 ,十三烂,7对等特殊玩法的判断,读者可下载运行,

package algorithmimport ("fmt""sort""log"
)/*** WuMing*2017/7/6 下午2:40*针对瑞金麻将的函数*/var (ruiJinmahjongArr = []int{101, 102, 103, 104, 105, 106, 107, 108, 109, //#万101, 102, 103, 104, 105, 106, 107, 108, 109,101, 102, 103, 104, 105, 106, 107, 108, 109,101, 102, 103, 104, 105, 106, 107, 108, 109,201, 202, 203, 204, 205, 206, 207, 208, 209, //#饼201, 202, 203, 204, 205, 206, 207, 208, 209,201, 202, 203, 204, 205, 206, 207, 208, 209,201, 202, 203, 204, 205, 206, 207, 208, 209,301, 302, 303, 304, 305, 306, 307, 308, 309, //#条301, 302, 303, 304, 305, 306, 307, 308, 309,301, 302, 303, 304, 305, 306, 307, 308, 309,301, 302, 303, 304, 305, 306, 307, 308, 309,401, 402, 403, 404, 405, 406, 407, //# 东 西 南 北 中 发 白401, 402, 403, 404, 405, 406, 407,401, 402, 403, 404, 405, 406, 407,401, 402, 403, 404, 405, 406, 407,501, 502, 503, 504, //花(春夏秋冬)}
)/**
吴名
2017/7/10 下午5:26
3n+2牌型的胡牌
*/
func isHU(arr []int, bao int) bool {mjArr := append([]int{}, arr...)//宝,万,筒,条,风sptArr := seperateRuiJinArr(mjArr, bao)baoNum := len(sptArr[0]) //手牌中宝的数量if baoNum == 4 || (bao > 500 && baoNum == 3) {//飞log.Println("胡:所有的宝牌都在一家,飞")return false}//检测牌数量if len(mjArr)%3 != 2 {log.Println("牌数量不符合3n+2")return false}needBaoArr := [5]int{}for i := 1; i <= 4; i++ {a := append([]int{}, sptArr[i]...)needNum := getNeedBaoNumToZhengPu(a)needBaoArr[i] = needNum}// 吴名 2017/7/7 下午8:30 将在"万"中needBaoNum := needBaoArr[2] + needBaoArr[3] + needBaoArr[4]if needBaoNum <= baoNum {leftBaoNum := baoNum - needBaoNum //剩下可用于去拼 "万"成整扑一将的癞子数量num := getBaoNumToZhengPuJiang(sptArr[1])if leftBaoNum >= num {return true}}// 吴名 2017/7/7 下午8:30 将在"筒"中needBaoNum = needBaoArr[1] + needBaoArr[3] + needBaoArr[4]if needBaoNum <= baoNum {leftBaoNum := baoNum - needBaoNum //剩下可用于去拼 "筒"成整扑一将的癞子数量num := getBaoNumToZhengPuJiang(sptArr[2])if leftBaoNum >= num {return true}}// 吴名 2017/7/7 下午8:31 将在"条"中needBaoNum = needBaoArr[1] + needBaoArr[2] + needBaoArr[4]if needBaoNum <= baoNum {leftBaoNum := baoNum - needBaoNum //剩下可用于去拼 "条"成整扑一将的癞子数量num := getBaoNumToZhengPuJiang(sptArr[3])if leftBaoNum >= num {return true}}// 吴名 2017/7/7 下午8:31 将在"风"中needBaoNum = needBaoArr[1] + needBaoArr[2] + needBaoArr[3]if needBaoNum <= baoNum {leftBaoNum := baoNum - needBaoNum //剩下可用于去拼 "风"成整扑一将的癞子数量num := getBaoNumToZhengPuJiang(sptArr[4])if leftBaoNum >= num {return true}}return false
}/**
吴名
2017/7/12 下午3:05
判断制飞是否成功:来任何一张牌都能胡(2,减去手上一张宝之后,剩下的牌形成整扑 1,减去手上一张宝之后,剩下的牌形成6对子)
*/
func zhiFei(arr []int, bao int) bool {mjArr := append([]int{}, arr...)//宝,万,筒,条,风sptArr := seperateRuiJinArr(mjArr, bao)//1:  13张牌,7对的制飞if len(mjArr) == 13 {danNum := 0for i, arr := range sptArr {l := len(arr)switch i {case 0://宝不需要去除对子if l == 4 || (bao > 500 && l == 3) {log.Println("对对胡:所有的宝牌都在一家,飞")return false}default:danArr, _ := separate2Same(arr)danNum += len(danArr)}}//4,宝数量>=剩下的单张数量(去掉一张宝后,12张牌形成了6对)if len(sptArr[0])-1 >= danNum {log.Println("对对胡:制飞成功")return true}}//2, 减掉一张宝之后,剩下牌形成整扑//检测牌数量if len(mjArr)%3 != 1 {log.Println("牌数量不符合3n+1,不能飞")return false}needBaoNumToZhengPu := 0for i := 1; i <= 4; i++ {needBaoNumToZhengPu += getNeedBaoNumToZhengPu(sptArr[i])}if len(sptArr[0])-1 == needBaoNumToZhengPu {log.Println("3n+2胡:制飞成功")return true}return false
}/**
吴名
2017/7/11 下午1:50
烂胡(在调用这个之前,已经排除了)
*/
func lanHu(arr []int, bao int) bool {mjArr := append([]int{}, arr...)//1,判断牌长度,必须为14if len(mjArr) != 14 {return false}//2,按类型分组//宝,万,筒,条,风sptArr := seperateRuiJinArr(mjArr, bao)//3,万筒条任意两张牌的差必须>=3//4,风牌任何两张牌不能相等for i, arr := range sptArr {l := len(arr)switch i {case 0://宝不需要处理,只要万筒条风符合要求,不管几个宝,都可以配合if l == 4 || (bao > 500 && l == 3) {log.Println("烂胡:所有的宝牌都在一家,飞")return false}case 4://风(任何两张不能相等)for j, _ := range arr {if j <= l-2 && arr[j] == arr[j+1] {log.Println("烂胡:风相等")return false}}default://万筒条(差必须>=3),seperateRuiJinArr()返回的已经是排序后的for k, _ := range arr {if k <= l-2 && arr[k+1]-arr[k] <= 2 {log.Println("烂胡:万筒条未跳两张")return false}}}}log.Println("符合烂胡")return true
}func duiDuiHu(arr []int, bao int) bool {mjArr := append([]int{}, arr...)//1,判断牌长度,必须为14if len(mjArr) != 14 {return false}//2,按类型分组//宝,万,筒,条,风sptArr := seperateRuiJinArr(mjArr, bao)//3,去掉所有对子,得到单张数量danNum := 0for i, arr := range sptArr {l := len(arr)switch i {case 0://宝不需要去除对子if l == 4 || (bao > 500 && l == 3) {log.Println("对对胡:所有的宝牌都在一家,飞")return false}default:danArr, _ := separate2Same(arr)danNum += len(danArr)}}//4,宝数量>=剩下的单张数量if len(sptArr[0]) >= danNum {return true}return false
}/**
吴名
2017/7/8 下午5:01
万,筒,条,风,成为整扑一将需要的最少癞子数量
*/
func getBaoNumToZhengPuJiang(arr []int) int {if len(arr) <= 0 {//如果数组为空,至少需要2个癞子组成一对将return 2}//寻找对子//吴名 2017/7/8 下午8:09 先去掉顺子的影响t := arr[0] / 100 //万筒条风类型a := []int{}switch t {case 4:a = separateFeng3Lian_ruiJin(arr)default:a, _ = separate3Lian(arr)}l := len(a)switch l {case 0:return 2case 1:return 1default://可能是一张牌,两张牌,或3张牌for i, _ := range a {switch i {//只有2张牌,进入这里,为第一张case l - 2:if l == 2 && a[i] == a[i+1] {//找到对子了b := append(a[:i], a[i+2:]...)return getNeedBaoNumToZhengPu(b)}//最后1张牌case l - 1://到最后一张牌,还没有找到对子//此时的3同参与不了顺子subArr := separate3Same(a)//2连不能拿去拼对子//吴名 2017/7/10 上午11:53 分离2连,再形成对子(101,104,105)canLianNum := 0switch t {case 4:subArr, canLianNum = separateFeng2Lian_ruiJin(subArr)default:subArr, canLianNum, _ = separate2Lian(subArr, -1, false)}switch len(subArr) {case 0:return canLianNum + 2case 1:return canLianNum + 1default://101,105,105,105,不能拆3同return 1 + canLianNum + getNeedBaoNumToZhengPu(subArr[:len(subArr)-1]) //剩下的,最后1张牌拿去拼将去了(只能最后一张,101,101,101,104)}default://101,104,104,104,107,不拆开3同(3同对形成顺子无影响)//举例总结:3同能参与形成顺子时,拆掉3同需要癞子数<=不拆,3同不能参与形成顺子时,3同利用不到,不能拆3同switch t {case 4:if a[i] == a[i+2] {//3同对子,但是对形成顺子有影响(401,401,401,404)if i >= 1 && (a[i] <= 404 || a[i-1] >= 405) {//401,404,404,404 或 405,406,406,406//3同能和前面形成顺子或有影响(包括4同)b := append(a[:i], a[i+2:]...)return getNeedBaoNumToZhengPu(b)}if l-i >= 4 && (a[i+3] <= 404 || a[i] >= 405) {//403,403,403,404 或 406,406,406,407//3同能和后面形成顺子或有影响(包括4同)b := append(a[:i], a[i+2:]...)return getNeedBaoNumToZhengPu(b)}} else {//纯对子(非3同中的对子)if a[i] == a[i+1] {if i == 0 || a[i-1] != a[i] {b := append(a[:i], a[i+2:]...)return getNeedBaoNumToZhengPu(b)}}}default:if a[i] == a[i+2] {//3同对子,但是对形成顺子有影响(101,103,103,103,105)if i >= 1 && a[i]-a[i-1] <= 2 {//3同能和前面形成顺子或有影响(包括4同)b := append(a[:i], a[i+2:]...)return getNeedBaoNumToZhengPu(b)}if l-i >= 4 && a[i+3]-a[i+2] <= 2 {//3同能和后面形成顺子或有影响(包括4同)b := append(a[:i], a[i+2:]...)return getNeedBaoNumToZhengPu(b)}} else {//纯对子(非3同中的对子)if a[i] == a[i+1] {if i == 0 || a[i-1] != a[i] {b := append(a[:i], a[i+2:]...)fmt.Println("b:", b)return getNeedBaoNumToZhengPu(b)}}}}}}}return 0
}/**
吴名
2017/7/6 下午7:05
万,筒,条,风,成为顺子或者三连需要的癞子数量
*/
func getNeedBaoNumToZhengPu(subArr []int) int {length := len(subArr) //万的张数switch length {case 0:return 0case 1:return 2case 2:t := subArr[0] / 100 //万筒条风类型switch t {case 4://风if subArr[1] <= 404 {//两个都是东南西北(不管做顺子或刻),东南西北任何三个也可以互吃return 1}if subArr[0] >= 405 {//两个都是中发白,中发白任何三个可以互吃return 1}//一个东南西北,一个是中法白return 4default://万,筒,条d := subArr[1] - subArr[0] //subArr是已经经过排序的if d <= 2 {//1万1万,1万2万,1万3万return 1} else {//1万4万return 4}}default://3张以上万筒条或风//++++++++必须从小到大排序后,先去3同,再去3连,再去2同,再去2连,这些最容易形成整扑的去掉后,然后剩下牌两个一组分割算需要癞子数,这才能得到最少的癞子数量++++++++++//1,分离3同subArr = separate3Same(subArr)if len(subArr) <= 2 {//去除3同后剩余牌数<=2,直接结束return getNeedBaoNumToZhengPu(subArr)}t := subArr[0] / 100 //万筒条风类型switch t {case 4://风//2,分离3连subArr = separateFeng3Lian_ruiJin(subArr)l := len(subArr)if l <= 2 {return getNeedBaoNumToZhengPu(subArr)} else {needCount := 0//3,分离2同subArr, duiZiNum := separate2Same(subArr)needCount += duiZiNum //有多少个对子就需要多少个癞子把它变整扑//3,分离2连subArr, canLianNum := separateFeng2Lian_ruiJin(subArr)needCount += canLianNum + getNeedBaoNumToZhengPu(subArr)return needCount}default://万或筒或条//2,分离3连subArr, _ = separate3Lian(subArr)l := len(subArr)if l <= 2 {return getNeedBaoNumToZhengPu(subArr)} else {needCount := 0//3,分离2同和2连(相当于只需要1癞子就能成的牌都去掉)subArr, canLianOrSameNum, _ := separate2LianAnd2Same(subArr, -1, false)needCount += canLianOrSameNum + getNeedBaoNumToZhengPu(subArr) //有多少个对子或2连就需要多少个癞子把它变整扑return needCount}}}
}/**
吴名
2017/7/8 上午11:54
分离2连(风,适用):返回去除后的数组,以及2连数量(里面3顺子,对子必须提前已去除)
*/
func separateFeng2Lian_ruiJin(arr []int) ([]int, int) {is := falselianNum := 0l := len(arr)for i, _ := range arr {if arr[i] != 0 && i <= l-2 {if arr[i+1] <= 404 || arr[i] >= 405 {//1,东南西北三张互吃 2,中发白互吃(对子前一步已经去除,所以不可能相等)arr[i] = 0arr[i+1] = 0lianNum++is = truebreak}}}if is {//如果祛除过顺子,那么需要清洗0之后继续祛除r := []int{}for _, v := range arr {if v != 0 {r = append(r, v)}}a, num := separateFeng2Lian_ruiJin(r)return a, lianNum + num} else {return arr, 0}
}/**
吴名
2017/7/7 下午5:45
分离顺子(针对风):东南西北任何三个也可以互吃,中发白任何三个可以互吃
*/
func separateFeng3Lian_ruiJin(arr []int) []int {is := falsefor i, _ := range arr {//前3张无对子的情况下(401,402,403,404)if i <= len(arr)-3 {if arr[i+2] <= 404 && arr[i] != arr[i+1] && arr[i+1] != arr[i+2] {//连续3张都是中南西北,且三张各不相等,可以互吃arr[i] = 0arr[i+1] = 0arr[i+2] = 0//log.Println("去除顺子:%v", arr)is = truebreak}if arr[i] == 405 && arr[i+1] == 406 && arr[i+2] == 407 {//连续3张是中发白arr[i] = 0arr[i+1] = 0arr[i+2] = 0//log.Println("去除顺子:%v", arr)is = truebreak}}//前3张有对子的情况下(401,401,402,403,404)if i <= len(arr)-4 {if arr[i+3] <= 404 && arr[i] != arr[i+1] && arr[i+1] != arr[i+3] {arr[i] = 0arr[i+1] = 0arr[i+3] = 0//log.Println("去除顺子:%v", arr)is = truebreak}}}if is {//如果祛除过顺子,那么需要清洗0之后继续祛除r := []int{}for _, v := range arr {if v != 0 {r = append(r, v)}}return separateFeng3Lian_ruiJin(r)} else {return arr}
}/**
吴名
2017/7/6 下午4:27
分割 宝,万,筒,条,风
*/
func seperateRuiJinArr(mjArr []int, bao int) [5][]int {result := [5][]int{}for _, mj := range mjArr {index := mj / 100//宝是花牌if bao > 500 {switch index {case 5://宝result[0] = append(result[0], mj)default:result[index] = append(result[index], mj)}} else {switch index {case 5://此时花牌处理成宝的本位牌i := bao / 100result[i] = append(result[i], bao)default:if mj == bao {//宝result[0] = append(result[0], mj)} else {result[index] = append(result[index], mj)}}}}//升序排列for _, arr := range result {sort.Sort(sort.IntSlice(arr))}return result
}

单元测试及性能测试:

func Test_lanHu(t *testing.T) {//arr := []int{101, 104, 104, 104, 104}arr := []int{101, 104, 104, 107, 201, 204, 209, 302, 305, 309, 403, 406, 409, 501}t.Logf("烂胡:%v", lanHu(arr, 104))
}func Test_duiDuiHu(t *testing.T) {arr := []int{101, 101, 104, 104, 201, 201, 209, 209, 305, 306, 407, 407, 407, 407}t.Logf("对对胡:%v", duiDuiHu(arr, 407))
}func Test_zhiFei(t *testing.T) {arr := []int{101, 101, 104, 104, 201, 201, 209, 209, 305, 306, 407, 407, 407}t.Logf("制飞:%v", zhiFei(arr, 407))
}func Test_isHU(t *testing.T) {arr := []int{101, 101, 104, 104, 201, 201, 209, 209, 305, 306, 307, 407, 407, 407}t.Logf("胡:%v", isHU(arr, 407))
}
func Benchmark_isHU(b *testing.B) {for i := 0; i < b.N; i++ {arr := []int{101, 101, 104, 104, 201, 201, 209, 209, 305, 306, 307, 407, 407, 407}isHU(arr, 407)//b.Logf("胡:%v", isHU(arr, 407))}//b.RunParallel(func(pb *testing.PB) {////    for pb.Next() {//        arr := []int{101, 101, 104, 104, 201, 201, 209, 209, 305, 306, 307, 407, 407, 407}//        isHU(arr, 407)//        //b.Logf("胡:%v", isHU(arr, 407))//    }//})
}

性能测试结果

1s=10^3ms(毫秒)=10^6μs(微秒)=10^9ns(纳秒)
可胡牌:
arr := []int{101, 101, 104, 104, 201, 201, 209, 209, 305, 306, 307, 407, 407, 407}

可胡牌情况下,一次判断只需要4822ns,即一秒钟可以执行约20万次判断,如果牌数量更少时的n%3=2,则效率更高

pkg: dataStructures-algorithm-demo/麻将相关算法
300000          4822 ns/op
--- BENCH: Benchmark_isHU-8ruijinMjHu_test.go:95: 胡:true

不可胡牌时,效率比可胡牌的牌型效率略高一些

pkg: dataStructures-algorithm-demo/麻将相关算法
500000          3711 ns/op
--- BENCH: Benchmark_isHU-8ruijinMjHu_test.go:95: 胡:false

综上,此算法不仅效率很高,且通用性很强(任何类型玩法的麻将都可用)

完整代码已上传GitHub,欢迎star并提出优化建议,如发现bug,欢迎给予指正,希望和大神们共同进步

可带癞子的通用麻将胡牌算法相关推荐

  1. Unity3D 通用麻将胡牌算法

    https://blog.csdn.net/qq_38064109/article/details/78933589 正常的麻将胡牌方式为满足N * ABC + M *DDD +EE 的形式,及存在一 ...

  2. 麻将胡牌算法带癞子 python实现

    姐姐:你去帮我和闺蜜打麻将? 学霸哥哥:可是我不会打麻将呀! 姐姐:你不是学霸吗?我教你一个麻将公式,我闺蜜可是单身哟! 学霸哥哥:什么公式? 姐姐:麻将胡牌公式: AAA*M+ABC*N+BB,WM ...

  3. 麻将 胡牌 算法(任意癞子)

    分享一个麻将胡牌算法,支持多癞子,自己对麻将胡牌的理解写的一套快速识别胡牌逻辑,核心逻辑500行代码,仅对同条万进行处理,字花牌不包含在内,易理解,1M次随机胡牌牌型大概3秒左右.原创分享,我的算法也 ...

  4. 癞子麻将胡牌算法实现

    最先实现的就是算法的实现. 需求:碰杠胡  ,不能吃 ,不能听 ,仅仅能自摸胡,当中癞子能够做随意牌可是不能碰和杠. 写的时候还不会玩麻将,还是老板教的.^_^ 最麻烦的是胡牌算法.之前搜到的都是不包 ...

  5. 麻将胡牌算法 极速(速度接近理论极限)

    此麻将胡牌算法优点: 1.可处理多赖子牌(万能牌) 2.算法速度极快:1ms可大约计算1W+副手牌是否可胡(带赖子.0.08us左右),不带赖子的牌型更快.(最新版的算法速度感觉已很接近理论极限值) ...

  6. 麻将胡牌算法——C#

    这里只介绍普通的麻将胡牌算法,也就是7个对子或者 1个对子+3*N; N = 三个顺子或者三个一样的 ,其中字牌(东南西北中发白)不能算顺子. 首先对于每张牌 它有牌的的数字 1-9,牌的种类 (万条 ...

  7. 麻将胡牌算法(遍历+剪枝)

    麻将胡牌算法(遍历+剪枝) 简介 麻将胡牌算法及代码 1. 方法引入 2. 类型定义 2.1 牌定义 2.2 牌特征定义 3. 计算胡牌 3.1 检测十三幺牌型 3.2 检测七小对牌型 3.3 检测普 ...

  8. 麻将胡牌算法,带癞子

    貌似去年去面试一家公司,问了麻将的算法.虽然之前做过广东麻将,但是胡牌算法在服务端,就没有在意. 现在在网上搜了一些算法试了试 = =! 麻将普通的胡牌就是刻子+顺子+将.癞子可以充当任意一张牌. 参 ...

  9. 包含癞子的麻将胡牌算法

    记录一下麻将的通用胡牌算法实现,只要满足M x ABC + N x DDD + EE 即可胡牌. 在这里先分析一下最简单的胡牌思路:先找出所有可能的将牌,若除去两张将牌之外的所有牌都能成扑,则可胡牌. ...

最新文章

  1. 谈谈document.ready和window.onload的区别
  2. 乐峰VS聚美,明星也要吃咸盐
  3. java 字符串去掉换行_java第一个程序quot;helloworldquot;
  4. 以太坊智能合约安全入门了解一下(上)
  5. oracle 11g安装过程中问题:找不到WFMLRSVCApp.ear
  6. centos7恢复mysql数据库_mysql数据库恢复过程记录
  7. 25个恶意JavaScript 库通过NPM官方包仓库分发
  8. c#图像处理-图像预览全解
  9. Web Deploy 发布网站错误 检查授权和委派设置
  10. M3DGIS三维电子沙盘大数据人工智能元宇宙地理信息系统第5课
  11. Simulink中步长、powergui采样时间、模块采样时间、控制周期的关系
  12. 类似123321特殊数的输出
  13. TMS VCL UI Pack Crack,完整源代码
  14. Python爬虫:新浪新闻详情页的数据抓取(函数版)
  15. 利用C++实现简单的文件加密
  16. python 有损和无损 方式替换表情符号
  17. pdf转换成word转换器在线哪个最好
  18. GitBook 制作电子书
  19. java后端开发三年,你还不了解JVM,凭什么给你涨薪
  20. 如何删除右键“新建”菜单中的不需要的菜单 | 如何禁止或删除powerdesigner桌面右键“新建”菜单 powerdesigner菜单选项

热门文章

  1. 实战项目-百思不得姐-精华
  2. 文件夹加密超级大师会把文件上传到服务器吗,共享文件夹加密超级大师怎么加密文件夹?...
  3. ​赛分科技冲刺科创板上市:拟募资8亿元,复星、高瓴为股东​
  4. 人工智能发展简史——未来是属于AI人工智能的。
  5. 小程序云开发——创建第一个商品数据
  6. 2020最新kali安装中文输入法
  7. (转)GCC内联汇编入门
  8. 天地劫幽城再临服务器维护,天地劫幽城再临开服时间是什么时候_天地劫幽城再临开服时间一览_3DM手游...
  9. 轻松学透Markdown的终极教程 #5: GFM(GitHub Flavored Markdown)语法
  10. android手机 u盘 启动不起来,安卓手机不识别U盘、不能连接PC的处理方法