package entertainment import ( "crypto/rand" "fmt" "go_dreamfactory/lego/core" "go_dreamfactory/pb" "math/big" ) const ( Width = 7 Height = 7 ) // type Girde struct { // X int32 // x // Y int32 // ID int32 // Itype int32 // } //地图数据 type MapData struct { Data map[int32]*pb.GirdeData // 地图数据 } func (this *MapData) Init(service core.IService, module core.IModule, comp core.IModuleComp, options core.IModuleOptions) (err error) { this.Data = make(map[int32]*pb.GirdeData, Width*Height) return } // 1~6随机一个数 func GetRandType() int32 { n, _ := rand.Int(rand.Reader, big.NewInt(6)) return int32(n.Int64() + 1) } func (this *MapData) GetKeyType(key int32) int32 { var itype int32 if v, ok := this.Data[key]; ok { itype = v.Itype } return itype } func (this *MapData) GetKeyData(key int32) (data *pb.GirdeData) { if v, ok := this.Data[key]; ok { return v } return } // 初始化地图数据 func (this *MapData) InitMap() { this.Data = make(map[int32]*pb.GirdeData, Width*Height) for i := 0; i < Width; i++ { for j := 0; j < Height; j++ { tmp := GetRandType() key := int32(i*10 + j) bOk := true // OK 的 this.Data[key] = &pb.GirdeData{ X: int32(i), Y: int32(j), Id: key, Itype: tmp, Cid: tmp, Score: 1, } // 校验 检查格子的左边的左边 和下边和下下边 if j-2 >= 0 { i1 := this.GetKeyType(int32(i*10 + j - 1)) i2 := this.GetKeyType(int32(i*10 + j - 2)) if i1 == i2 && tmp == i1 { bOk = false } } if i-2 >= 0 { i1 := this.GetKeyType(int32((i-1)*10 + j)) i2 := this.GetKeyType(int32((i-2)*10 + j)) if i1 == i2 && tmp == i1 { bOk = false } } if !bOk { for i := 0; i < Width*Height; i++ { itype := GetRandType() if tmp != itype { tmp = itype break } } this.Data[key].Itype = tmp } } } // 测试地图数据 sz2 := []int32{ 5, 1, 3, 5, 1, 5, 2, 3, 1, 5, 4, 2, 4, 4, 4, 4, 1, 5, 6, 4, 1, 6, 3, 1, 1, 3, 6, 3, 6, 3, 5, 2, 4, 6, 1, 5, 6, 5, 5, 1, 3, 1, 6, 5, 5, 1, 2, 1, 4, } var index = 0 for j := Height - 1; j >= 0; j-- { for i := 0; i < Width; i++ { key := int32(i*10 + j) this.Data[key].Itype = sz2[index] index++ } } this.Debugf() } // 交换2个元素(参数 id ) func (this *MapData) SwapGirde(i, j int32) bool { var ( bSwap bool // 能否交换 tmp *pb.GirdeData ) g1 := this.GetKeyData(i) g2 := this.GetKeyData(j) if g1 == nil || g2 == nil { return bSwap } // 校验是不是挨着的 if g1.X-1 == g2.X || g1.X+1 == g2.X || g1.Y+1 == g2.Y || g1.Y-1 == g2.Y { bSwap = true // 更新地图数据 tmp = &pb.GirdeData{ X: g1.X, Y: g1.Y, Id: g1.Id, Itype: g1.Itype, Cid: g1.Cid, Score: g1.Score, } this.Data[i] = g2 this.Data[j] = tmp if !this.CheckSwape(i, j) { // 交换后不能消除 this.Data[i] = tmp this.Data[j] = g2 bSwap = false } } this.Debugf() return bSwap } func (this *MapData) Debugf() { fmt.Printf("================\n") for j := Height - 1; j >= 0; j-- { for i := 0; i < Width; i++ { key := int32(i*10 + j) fmt.Printf("%d ", this.Data[key].Itype) } fmt.Printf("\n") } } // 检查5消 func (this *MapData) Check5X() (bEliminate bool, score int32) { m := make(map[int32]struct{}, 5) bEliminate = true del := make(map[int32]int32) for i := 0; i < Width; i++ { for j := 0; j < Height; j++ { m = make(map[int32]struct{}, 0) key := int32(i*10 + j) iType := this.GetKeyType(key) if iType == 0 { continue } curKey := this.Data[key].Itype if curKey == 0 { continue } m[curKey] = struct{}{} if i+4 < Width { i1 := this.Data[int32((i+1)*10+j)] i2 := this.Data[int32((i+2)*10+j)] i3 := this.Data[int32((i+3)*10+j)] i4 := this.Data[int32((i+4)*10+j)] m[i1.Itype] = struct{}{} m[i2.Itype] = struct{}{} m[i3.Itype] = struct{}{} m[i4.Itype] = struct{}{} if len(m) == 1 { del[int32((i+1)*10+j)] = i1.Score del[int32((i+2)*10+j)] = i2.Score del[int32((i+3)*10+j)] = i3.Score del[int32((i+4)*10+j)] = i4.Score del[key] = this.Data[key].Score } } m = map[int32]struct{}{} if j+4 < Height { i1 := this.Data[int32(i*10+j+1)] i2 := this.Data[int32(i*10+j+2)] i3 := this.Data[int32(i*10+j+3)] i4 := this.Data[int32(i*10+j+4)] m[i1.Itype] = struct{}{} m[i2.Itype] = struct{}{} m[i3.Itype] = struct{}{} m[i4.Itype] = struct{}{} if len(m) == 1 { // 1 2 3 4 5 del[int32(i*10+j+1)] = i1.Score del[int32(i*10+j+2)] = i2.Score del[int32(i*10+j+3)] = i3.Score del[int32(i*10+j+4)] = i4.Score del[key] = this.Data[key].Score } } } } // 顺着删除列表删除各组 for k, v := range del { this.Data[k].Itype = 0 score += v } if len(del) > 0 { bEliminate = false fmt.Printf("5x消除格子===del:%v\n", del) } return } func (this *MapData) Check4X() (bEliminate bool, score int32) { bEliminate = true del := make(map[int32]int32) for i := 0; i < Width; i++ { for j := 0; j < Height; j++ { key := int32(i*10 + j) iType := this.GetKeyType(key) if iType == 0 { continue } if i+3 < Width { i1 := this.Data[int32((i+1)*10+j)] i2 := this.Data[int32((i+2)*10+j)] i3 := this.Data[int32((i+3)*10+j)] if i1.Itype == i2.Itype && i2.Itype == i3.Itype && i1.Itype == iType { del[int32((i+1)*10+j)] = i1.Score del[int32((i+2)*10+j)] = i2.Score del[int32((i+3)*10+j)] = i3.Score del[key] = this.Data[key].Score } } if j+3 < Height { i1 := this.Data[int32(i*10+j+1)] i2 := this.Data[int32(i*10+j+2)] i3 := this.Data[int32(i*10+j+3)] if i1.Itype == i2.Itype && i2.Itype == i3.Itype && i1.Itype == iType { del[int32(i*10+j+1)] = i1.Score del[int32(i*10+j+2)] = i2.Score del[int32(i*10+j+3)] = i3.Score del[key] = this.Data[key].Score } } } } // 顺着删除列表删除各组 for k, v := range del { this.Data[k].Itype = 0 score += v } if len(del) > 0 { bEliminate = false fmt.Printf("4x消除格子===del:%v\n", del) } return } func (this *MapData) Check3X() (bEliminate bool, score int32) { bEliminate = true del := make(map[int32]int32) for i := 0; i < Width; i++ { for j := 0; j < Height; j++ { key := int32(i*10 + j) iType := this.GetKeyType(key) if iType == 0 { continue } if i+2 < Width { i1 := this.Data[int32((i+1)*10+j)] i2 := this.Data[int32((i+2)*10+j)] if i1.Itype == i2.Itype && i1.Itype == iType { del[int32((i+1)*10+j)] = i1.Score del[int32((i+2)*10+j)] = i1.Score del[key] = i1.Score } } if j+2 < Height { i1 := this.Data[int32(i*10+j+1)] i2 := this.Data[int32(i*10+j+2)] if i1.Itype == i2.Itype && i1.Itype == iType { del[int32(i*10+j+1)] = i1.Score del[int32(i*10+j+2)] = i1.Score del[key] = i1.Score } } } } // 顺着删除列表删除各组 for k, v := range del { this.Data[k].Itype = 0 score += v } if len(del) > 0 { bEliminate = false fmt.Printf("3x消除格子===del:%v\n", del) } return } func (this *MapData) CheckSwape(g1, g2 int32) (bEliminate bool) { for i := 0; i < Width; i++ { for j := 0; j < Height; j++ { key := int32(i*10 + j) iType := this.GetKeyType(key) if iType == 0 { continue } if j+2 < Height { k1 := int32((i+1)*10 + j) k2 := int32((i+2)*10 + j) i1 := this.Data[k1] i2 := this.Data[k2] if i1.Itype == i2.Itype && i1.Itype == iType { if g1 == key || k1 == g1 || k2 == g1 || g2 == key || k1 == g2 || k2 == g2 { return true } } } if i+2 < Width { k1 := int32(i*10 + j + 1) k2 := int32(i*10 + j + 2) i1 := this.Data[k1] i2 := this.Data[k2] if i1.Itype == i2.Itype && i1.Itype == iType { if g1 == key || k1 == g1 || k2 == g1 || g2 == key || k1 == g2 || k2 == g2 { return true } } } } } return } // 校验地图可消除的 判断各组上面2个和右边两个是否三个相等 func (this *MapData) CheckMap() (score int32) { score = 0 if bRet, s := this.Check5X(); !bRet { fmt.Printf("=====检测消除5x===========\n") score += s } if bRet, s := this.Check4X(); !bRet { fmt.Printf("=====检测消除4x===========\n") score += s } if bRet, s := this.Check3X(); !bRet { fmt.Printf("=====检测消除3x===========\n") score += s } this.Debugf() return } // 下落 生成新的格子 (返回掉落所获得的分数) func (this *MapData) DropGirde() (score int32, szMap []*pb.MapData) { var bDrop bool for { bDrop = false for _, v := range this.Data { // 校验是否有下落 if v.Itype == 0 { fmt.Printf("检测有掉落\n") bDrop = true // 有空位置 说明可以掉落 break } } if !bDrop { break } for i := 0; i < Width; i++ { for j := 0; j < Height; j++ { key := int32(i*10 + j) var sz []int32 var l int // 落下多少个 if this.GetKeyType(key) == 0 { // 找上面的 for m := j; m < Height; m++ { key1 := int32(i*10 + m) t := this.GetKeyData(key1) if t.Itype != 0 { sz = append(sz, t.Itype) l++ } } for pos, v := range sz { key := int32(i*10 + j + pos) this.Data[key].Itype = v } for n := j + l; n < Height; n++ { key := int32(i*10 + n) tmp := GetRandType() this.Data[key].Itype = tmp } break // 完成该列 } } } if s := this.CheckMap(); s > 0 { fmt.Printf("本次掉落得分:%d\n", s) score += s szMap = append(szMap, &pb.MapData{ Data: this.Data, }) } } this.Debugf() return } // func (this *MapData) AiOperator() bool { // var ( // bSwap bool // 能否交换 // tmp *pb.GirdeData // ) // g1 := this.GetKeyData(i) // g2 := this.GetKeyData(j) // if g1 == nil || g2 == nil { // return bSwap // } // // 校验是不是挨着的 // if g1.X-1 == g2.X { // bSwap = true // } // if g1.X+1 == g2.X { // bSwap = true // } // if g1.Y+1 == g2.Y { // bSwap = true // } // if g1.Y-1 == g2.Y { // bSwap = true // } // // 更新地图数据 // tmp = &pb.GirdeData{ // X: g1.X, // Y: g1.Y, // Id: g1.Id, // Itype: g1.Itype, // } // this.Data[i] = g2 // this.Data[j] = tmp // //this.Debugf() // return bSwap // }