go_dreamfactory/modules/entertainment/xxlPlat.go
2023-10-20 22:55:06 +08:00

482 lines
11 KiB
Go

package entertainment
import (
"crypto/rand"
"fmt"
"go_dreamfactory/pb"
"math/big"
)
const (
Width = 7
Height = 7
Total = Width * Height
FiveType = 3 // 5消类型
FourUType = 1 // 4消上下类型
FourLType = 2 // 4消左右类型
)
type Girde struct {
oid int32 // 唯一ID
color int32 // 颜色
cid int32 // 配置表id
score int32 // 分数
special int32 // 消除特效
}
//地图数据
type MapData struct {
Plat []*pb.GirdeData // 地图
oid int32 // 唯一id
module *Entertainment
}
// 1~6随机一个数
func GetRandType() int32 {
n, _ := rand.Int(rand.Reader, big.NewInt(6))
return int32(n.Int64() + 1)
}
func (this *MapData) CreateGride(index int32) *pb.GirdeData {
t := GetRandType()
fmt.Printf("create=====index: %d, color:%d \n", index, t)
this.oid++
return &pb.GirdeData{
Oid: this.oid,
Color: t,
Cid: GetRandType(),
Score: 1,
Special: 0,
}
}
// 初始化地图数据
func (this *MapData) InitMap(module *Entertainment) {
this.module = module
this.oid = 1000 // 方便观察 从1000开始
this.Plat = make([]*pb.GirdeData, Width*Height)
for i := 0; i < Width*Height; i++ {
this.Plat[i] = this.CreateGride(int32(i))
}
this.SetMap() // 方便测试固定地图
}
// 交换2个元素(参数 oid )
func (this *MapData) SwapGirde(oldId, newId int32, color int32) (bSwap bool, xCount int32) {
if (oldId%Height-1 < Total && oldId+1 == newId) ||
(oldId%Height > 0 && oldId-1 == newId) ||
(oldId+Width < Total && oldId+Width == newId) ||
(oldId-Width > 0 && oldId-Width == newId) {
bSwap = true
tmp := new(pb.GirdeData)
*tmp = *this.Plat[newId]
this.Plat[newId] = this.Plat[oldId]
this.Plat[oldId] = tmp
}
//this.CheckMap(color)
return
}
func (this *MapData) SetMap() {
sz2 := []int32{
5, 1, 2, 5, 1, 5, 2,
3, 1, 5, 4, 2, 4, 4,
4, 4, 2, 1, 6, 4, 1,
6, 3, 1, 4, 3, 6, 3,
6, 1, 3, 5, 1, 6, 1,
5, 6, 5, 5, 1, 3, 1,
6, 1, 5, 1, 2, 1, 4,
}
var pos int
for index := Width - 1; index >= 0; index-- {
for j := 0; j < Height; j++ {
this.Plat[index+j*Height].Color = sz2[pos]
this.Plat[index+j*Height].Cid = sz2[pos]
pos++
}
}
}
func (this *MapData) Debugf() {
fmt.Printf("================\n")
for index := Width - 1; index >= 0; index-- {
for j := 0; j < Height; j++ {
fmt.Printf("%d:%d ", this.Plat[index+j*Height].Oid, this.Plat[index+j*Height].Color)
}
fmt.Printf("\n")
}
}
// 检查5消
func (this *MapData) Check5X(color int32) (bEliminate bool, score int32, count int32) {
var xiaochu []int // 即将消除的key
for k, v := range this.Plat {
if v.Color == 0 {
continue
}
x := int32(k % Height) // x
if x+4 < Height {
k1 := this.Plat[k].Color
k2 := this.Plat[k+1].Color
k3 := this.Plat[k+2].Color
k4 := this.Plat[k+3].Color
k5 := this.Plat[k+4].Color
if k1 == k2 && k3 == k4 && k5 == k1 && k2 == k3 {
this.oid++
// 生成一个新的类型元素
if conf, err := this.module.configure.GetGameBlock(k1, FiveType); err != nil {
this.Plat[k+2] = &pb.GirdeData{
Oid: this.oid,
Color: k1,
Cid: conf.Key,
Score: conf.Score,
Special: conf.Type,
}
} else {
xiaochu = append(xiaochu, k+2)
}
xiaochu = append(xiaochu, []int{k, k + 1, k + 3, k + 4}...)
bEliminate = true
}
}
if k+4*Width < Total {
k1 := this.Plat[k].Color
k2 := this.Plat[k+Width].Color
k3 := this.Plat[k+2*Width].Color
k4 := this.Plat[k+3*Width].Color
k5 := this.Plat[k+4*Width].Color
if k1 == k2 && k3 == k4 && k5 == k1 && k2 == k3 {
this.oid++
// 生成一个新的类型元素
if conf, err := this.module.configure.GetGameBlock(k1, FiveType); err != nil {
this.Plat[k+2*Width] = &pb.GirdeData{
Oid: this.oid,
Color: k1,
Cid: conf.Key,
Score: conf.Score,
Special: conf.Type,
}
} else {
xiaochu = append(xiaochu, k+2*Width)
}
xiaochu = append(xiaochu, []int{k, k + Width, k + 3*Width, k + 4*Width}...)
bEliminate = true
}
}
}
var next []int
for _, id := range xiaochu {
if s := this.Plat[id].Special; s != 0 {
if s == FourUType { // 4消上下类型
for i := 0; i < Total; i++ {
if id/Height == i/Height {
next = append(next, i)
}
}
next = append(next, 1)
} else if s == FourLType { // 左右类型
for i := 0; i < Total; i++ {
if id%Height == i%Height {
next = append(next, i)
}
}
} else if s == FiveType { // 随机消除
}
} else { // 普通类型 直接消除
if this.Plat[id].Color == color {
count++
}
score += this.Plat[id].Score
this.Plat[id] = &pb.GirdeData{}
}
}
for _, v := range next {
if this.Plat[v].Color == color {
count++
}
score += this.Plat[v].Score
this.Plat[v] = &pb.GirdeData{}
}
return
}
func (this *MapData) Check4X(color int32) (bEliminate bool, score int32, count int32) {
var xiaochu []int // 即将消除的key
for k, v := range this.Plat {
if v.Color == 0 {
continue
}
x := int32(k % Height) // x
if x+3 < Height {
k1 := this.Plat[k].Color
k2 := this.Plat[k+1].Color
k3 := this.Plat[k+2].Color
k4 := this.Plat[k+3].Color
if k1 == k2 && k3 == k4 && k2 == k3 {
this.oid++
// 生成一个新的类型元素
if this.module != nil {
if conf, err := this.module.configure.GetGameBlock(k1, FourUType); err != nil { // 上下类型
this.Plat[k+1] = &pb.GirdeData{
Oid: this.oid,
Color: k1,
Cid: conf.Key,
Score: conf.Score,
Special: conf.Type,
}
} else {
xiaochu = append(xiaochu, k+1)
}
}
xiaochu = append(xiaochu, k+1)
xiaochu = append(xiaochu, []int{k, k + 2, k + 3}...)
bEliminate = true
}
}
if k+3*Width < Total {
k1 := this.Plat[k].Color
k2 := this.Plat[k+Width].Color
k3 := this.Plat[k+2*Width].Color
k4 := this.Plat[k+3*Width].Color
if k1 == k2 && k3 == k4 && k2 == k3 {
this.oid++
if this.module != nil {
// 生成一个新的类型元素
if conf, err := this.module.configure.GetGameBlock(k1, FourLType); err != nil { // 左右类型
this.Plat[k+Width] = &pb.GirdeData{
Oid: this.oid,
Color: k1,
Cid: conf.Key,
Score: conf.Score,
Special: conf.Type,
}
if k1 == color {
count++
}
} else {
xiaochu = append(xiaochu, k+Width)
}
}
xiaochu = append(xiaochu, k+Width)
xiaochu = append(xiaochu, []int{k, k + 2*Width, k + 3*Width}...)
bEliminate = true
}
}
}
var next []int
for _, id := range xiaochu {
if s := this.Plat[id].Special; s != 0 {
if s == FourUType { // 4消上下类型
for i := 0; i < Total; i++ {
if id/Height == i/Height {
next = append(next, i)
}
}
next = append(next, 1)
} else if s == FourLType { // 左右类型
for i := 0; i < Total; i++ {
if id%Height == i%Height {
next = append(next, i)
}
}
} else if s == FiveType { // 随机消除
}
} else { // 普通类型 直接消除
if this.Plat[id].Color == color {
count++
}
score += this.Plat[id].Score
this.Plat[id] = &pb.GirdeData{}
}
}
for _, v := range next {
if this.Plat[v].Color == color {
count++
}
score += this.Plat[v].Score
this.Plat[v] = &pb.GirdeData{}
}
return
}
func (this *MapData) Check3X(color int32) (bEliminate bool, score int32, count int32) {
var xiaochu []int // 即将消除的key
for k, v := range this.Plat {
if v.Color == 0 {
continue
}
x := int32(k % Height) // x
if x+2 < Height {
k1 := this.Plat[k].Color
k2 := this.Plat[k+1].Color
k3 := this.Plat[k+2].Color
if k1 == k2 && k2 == k3 {
xiaochu = append(xiaochu, []int{k, k + 1, k + 2}...)
bEliminate = true
}
}
if k+2*Width < Total {
k1 := this.Plat[k].Color
k2 := this.Plat[k+Width].Color
k3 := this.Plat[k+2*Width].Color
if k1 == k2 && k2 == k3 {
xiaochu = append(xiaochu, []int{k, k + Width, k + 2*Width}...)
bEliminate = true
}
}
}
var next []int
for _, id := range xiaochu {
if s := this.Plat[id].Special; s != 0 {
if s == FourUType { // 4消上下类型
for i := 0; i < Total; i++ {
if id/Height == i/Height {
next = append(next, i)
}
}
next = append(next, 1)
} else if s == FourLType { // 左右类型
for i := 0; i < Total; i++ {
if id%Height == i%Height {
next = append(next, i)
}
}
} else if s == FiveType { // 随机消除
}
} else { // 普通类型 直接消除
if this.Plat[id].Color == color {
count++
}
score += this.Plat[id].Score
this.Plat[id] = &pb.GirdeData{}
}
}
for _, v := range next {
if this.Plat[v].Color == color {
count++
}
score += this.Plat[v].Score
this.Plat[v] = &pb.GirdeData{}
}
return
}
// 校验地图可消除的 判断各组上面2个和右边两个是否三个相等
func (this *MapData) CheckMap(color int32) (score int32, szMap []*pb.MapData, count int32) {
var curScore int32
for {
curScore = 0
this.DropGirde() // 先掉落
if bRet, s, c := this.Check5X(color); bRet {
fmt.Printf("=====检测消除5x===========\n")
curScore += s
count += c
}
if bRet, s, c := this.Check4X(color); bRet {
fmt.Printf("=====检测消除4x===========\n")
curScore += s
count += c
}
if bRet, s, c := this.Check3X(color); bRet {
fmt.Printf("=====检测消除3x===========\n")
curScore += s
count += c
}
score += curScore // 总分
szMap = append(szMap, &pb.MapData{
Data: this.Plat,
CurSocre: curScore,
})
if curScore == 0 {
break
}
}
//this.Debugf()
return
}
// 下落 生成新的格子 (返回掉落所获得的分数)
func (this *MapData) DropGirde() {
for i := 0; i < Width; i++ {
for j := 0; j < Height; j++ {
index := i*Width + j
if this.Plat[index].Color == 0 { // 说明这列有空
var add int
for m := j + 1; m < Height; m++ {
k1 := i*Width + m
if this.Plat[k1].Color != 0 {
this.Plat[index] = this.Plat[k1]
index++
add++
}
}
for m := j + add; m < Height; m++ {
k1 := i*Width + m
this.Plat[k1] = this.CreateGride(int32(k1))
}
break
}
}
}
this.Debugf()
return
}
// ai操作
func (this *MapData) AiSwapGirde() bool {
var (
bSwap bool // 能否交换
)
for pos := 0; pos < Total; pos++ {
y := pos % Height
if y < Height-1 {
if b, _ := this.SwapGirde(int32(pos), int32(pos+1), 2); b {
if s, _, _ := this.CheckMap(2); s == 0 {
this.SwapGirde(int32(pos+1), int32(pos), 2)
} else {
bSwap = true
break
}
}
}
if pos/Width+1 < Width {
if b, _ := this.SwapGirde(int32(pos), int32(pos+Width), 2); b {
if s, _, _ := this.CheckMap(2); s == 0 {
this.SwapGirde(int32(pos+Width), int32(pos), 2)
} else {
bSwap = true
break
}
}
}
}
return bSwap
}