1622 lines
36 KiB
Go
1622 lines
36 KiB
Go
package entertainment
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"fmt"
|
|
"go_dreamfactory/comm"
|
|
"go_dreamfactory/pb"
|
|
cfg "go_dreamfactory/sys/configure/structs"
|
|
"go_dreamfactory/utils"
|
|
"math/big"
|
|
)
|
|
|
|
const (
|
|
Width = 7
|
|
Height = 7
|
|
Total = Width * Height
|
|
|
|
FiveType = 3 // 5消类型
|
|
FourUType = 1 // 4消上下类型
|
|
FourLType = 2 // 4消左右类型
|
|
BoomType = 4 // 炸弹类型
|
|
|
|
FireUp = 5 //上烟火
|
|
FireDown = 6 //下烟火
|
|
FireLeft = 7 //左烟火
|
|
FireRight = 8 //右烟火
|
|
)
|
|
|
|
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
|
|
operElem []int32 // 当前移动的元素
|
|
iType int32 // 玩法类型
|
|
}
|
|
|
|
// 1~6随机一个数
|
|
func (this *MapData) GetRandType() int32 {
|
|
return this.module.configure.GetGameNormalElem() // 权重随机
|
|
}
|
|
|
|
// 玩法带入
|
|
func (this *MapData) CreateGride(count int) (girdes []*pb.GirdeData) {
|
|
var (
|
|
id int32
|
|
conf *cfg.GameBlockData
|
|
err error
|
|
) // 权重带入
|
|
for i := 0; i < count; i++ {
|
|
this.oid++
|
|
girde := &pb.GirdeData{ // 默认值
|
|
Oid: this.oid,
|
|
Color: 1,
|
|
Cid: 1,
|
|
Score: 1,
|
|
Special: 0,
|
|
}
|
|
id = this.GetRandType()
|
|
if conf, err = this.module.configure.GetGameBlockByKey(id); err == nil {
|
|
girde.Color = conf.Color
|
|
girde.Cid = conf.Key
|
|
girde.Special = conf.Type
|
|
girde.Score = conf.Score
|
|
girdes = append(girdes, girde)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// 生成自定义地图
|
|
func (this *MapData) SetMap() {
|
|
sz2 := []int32{
|
|
3, 1, 2, 2, 1, 3, 1,
|
|
5, 1, 2, 4, 1, 2, 2,
|
|
2, 4, 3, 1, 3, 1, 6,
|
|
1, 3, 4, 5, 1, 3, 6,
|
|
2, 1, 1, 2, 1, 1, 4,
|
|
1, 6, 3, 26, 3, 4, 3,
|
|
3, 3, 1, 2, 1, 1, 5,
|
|
}
|
|
var pos int
|
|
for index := Width - 1; index >= 0; index-- {
|
|
for j := 0; j < Height; j++ {
|
|
Color := sz2[pos]
|
|
Cid := sz2[pos]
|
|
if sz2[pos] > 6 { // 特殊元素
|
|
conf, err := this.module.configure.GetGameBlockByKey(sz2[pos])
|
|
if err == nil {
|
|
Color = conf.Color
|
|
Cid = conf.Key
|
|
this.Plat[index+j*Height].Special = conf.Type
|
|
}
|
|
}
|
|
this.Plat[index+j*Height].Color = Color
|
|
this.Plat[index+j*Height].Cid = Cid
|
|
pos++
|
|
}
|
|
}
|
|
this.CheckAndRefreshPlat()
|
|
// this.SetIndelibilityPlat()
|
|
}
|
|
|
|
// 初始化地图数据
|
|
func (this *MapData) InitMap(module *Entertainment, iType int32) {
|
|
this.module = module
|
|
this.iType = iType
|
|
this.oid = 1000 // 方便观察 从1000开始
|
|
this.Plat = make([]*pb.GirdeData, Width*Height)
|
|
for i, v := range this.CreateGride(Total) {
|
|
this.Plat[i] = v
|
|
}
|
|
if iType > 1 {
|
|
var sp int32
|
|
var mp map[int32]struct{}
|
|
mp = make(map[int32]struct{}, 0)
|
|
for {
|
|
n1, _ := rand.Int(rand.Reader, big.NewInt(Total))
|
|
mp[int32(n1.Int64())] = struct{}{}
|
|
if len(mp) >= 2 {
|
|
break
|
|
}
|
|
}
|
|
|
|
for key := range mp {
|
|
if iType == 3 {
|
|
sp = 4
|
|
} else if iType == 4 {
|
|
n1, _ := rand.Int(rand.Reader, big.NewInt(4)) // 随机一个消除类型
|
|
sp = int32(n1.Int64()) + 5
|
|
}
|
|
if conf, err := this.module.configure.GetGameBlock(this.Plat[key].Color, sp); err == nil {
|
|
this.Plat[key].Cid = conf.Key
|
|
this.Plat[key].Special = conf.Type
|
|
this.Plat[key].Score = conf.Score
|
|
}
|
|
}
|
|
}
|
|
|
|
this.SetIndelibilityPlat()
|
|
//this.SetMap()
|
|
// this.Plat = this.GetPalatData()
|
|
}
|
|
|
|
// 交换之前先判断是不是特殊元素的交换
|
|
func (this *MapData) CheckSpecialElemChange(oldId, newId int32, color int32) (bSwap bool, szMap []*pb.MapData) {
|
|
this.operElem = []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
|
|
x := make(map[int]struct{})
|
|
if this.Plat[newId].Special != 0 && this.Plat[oldId].Special != 0 { // 都不为0
|
|
tmp := new(pb.GirdeData)
|
|
*tmp = *this.Plat[newId]
|
|
this.Plat[newId] = this.Plat[oldId]
|
|
this.Plat[oldId] = tmp
|
|
this.operElem = append(this.operElem, newId)
|
|
this.operElem = append(this.operElem, oldId)
|
|
|
|
x = this.SpecialElem(int(oldId), this.Plat[oldId].Special)
|
|
xc := this.SpecialElem(int(newId), this.Plat[newId].Special)
|
|
for k := range xc {
|
|
x[k] = struct{}{}
|
|
}
|
|
var energy int32
|
|
var curScore int32
|
|
|
|
for id := range x {
|
|
if this.Plat[id].Color == color {
|
|
energy++
|
|
}
|
|
curScore += this.Plat[id].Score
|
|
this.Plat[id] = &pb.GirdeData{}
|
|
this.operElem = append(this.operElem, int32(id))
|
|
}
|
|
if this.DropGirde() {
|
|
szMap = append(szMap, &pb.MapData{
|
|
Data: this.GetPalatData(),
|
|
CurSocre: curScore,
|
|
CurEnergy: energy,
|
|
})
|
|
}
|
|
} else {
|
|
bSwap = false
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// 交换2个元素(参数 oid )
|
|
func (this *MapData) SwapGirde(oldId, newId int32) (bSwap bool) {
|
|
this.operElem = []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.operElem = append(this.operElem, newId)
|
|
this.operElem = append(this.operElem, oldId)
|
|
}
|
|
//this.Debugf()
|
|
return
|
|
}
|
|
|
|
func (this *MapData) Debugf() {
|
|
fmt.Printf("================\n")
|
|
var v int
|
|
for index := Width - 1; index >= 0; index-- {
|
|
for j := 0; j < Height; j++ {
|
|
v = index + j*7
|
|
fmt.Printf("%d:%d ", v, this.Plat[index+j*Height].Cid)
|
|
|
|
}
|
|
fmt.Printf("\n")
|
|
}
|
|
}
|
|
|
|
// 检查5消 (s 是生成新的一个新的元素 key 下标 value 消除后效果类型)
|
|
func (this *MapData) Check5X() (bEliminate bool, xiaochu []int, s map[int]int) {
|
|
//var xiaochu []int // 即将消除的key
|
|
s = make(map[int]int)
|
|
for k, v := range this.Plat {
|
|
|
|
if v.Cid == 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 {
|
|
s[k+2] = FiveType
|
|
xiaochu = append(xiaochu, []int{k, k + 1, k + 2, k + 3, k + 4}...)
|
|
this.Plat[k].Cid = 0
|
|
this.Plat[k+1].Cid = 0
|
|
this.Plat[k+2].Cid = 0
|
|
this.Plat[k+3].Cid = 0
|
|
this.Plat[k+4].Cid = 0
|
|
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 {
|
|
s[k+2*Width] = FiveType
|
|
xiaochu = append(xiaochu, []int{k, k + Width, k + 2*Width, k + 3*Width, k + 4*Width}...)
|
|
this.Plat[k].Cid = 0
|
|
this.Plat[k+Width].Cid = 0
|
|
this.Plat[k+2*Width].Cid = 0
|
|
this.Plat[k+3*Width].Cid = 0
|
|
this.Plat[k+4*Width].Cid = 0
|
|
bEliminate = true
|
|
}
|
|
}
|
|
}
|
|
|
|
// // 校验上下左右
|
|
// for j := 0; j < Width; j++ {
|
|
// for k := 0; k < Height; k++ {
|
|
// pos := j*Width + k
|
|
// if pos+2 < Height {
|
|
// k1 := this.Plat[pos].Color
|
|
// k2 := this.Plat[pos+1].Color
|
|
// k3 := this.Plat[pos+2].Color
|
|
// var k4 int32
|
|
// var k5 int32
|
|
// if k1 == k2 && k3 == k1 { // 三个颜色相等
|
|
// tmp := pos
|
|
// index := 0
|
|
// for {
|
|
// index++
|
|
// if tmp/Width-2 >= 0 { // k1 的左右
|
|
// k4 = this.Plat[tmp/Width-1].Color
|
|
// k5 = this.Plat[tmp/Width-2].Color
|
|
// if k1 == k4 && k1 == k5 {
|
|
// bEliminate = true
|
|
// s[tmp] = FiveType
|
|
// this.Plat[pos].Cid = 0
|
|
// this.Plat[pos+1].Cid = 0
|
|
// this.Plat[pos+2].Cid = 0
|
|
// this.Plat[tmp/Width-1].Cid = 0
|
|
// this.Plat[tmp/Width-2].Cid = 0
|
|
// }
|
|
// }
|
|
// if tmp/Width+2 < Width {
|
|
// k4 = this.Plat[tmp/Width+1].Color
|
|
// k5 = this.Plat[tmp/Width+2].Color
|
|
// if k1 == k4 && k1 == k5 {
|
|
// bEliminate = true
|
|
// s[tmp] = FiveType
|
|
// this.Plat[pos].Cid = 0
|
|
// this.Plat[pos+1].Cid = 0
|
|
// this.Plat[pos+2].Cid = 0
|
|
// this.Plat[tmp/Width+1].Cid = 0
|
|
// this.Plat[tmp/Width+2].Cid = 0
|
|
// }
|
|
// }
|
|
// tmp = pos + 2
|
|
// if index == 2 {
|
|
// break
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// }
|
|
// }
|
|
return
|
|
}
|
|
|
|
func (this *MapData) Check4X() (bEliminate bool, xiaochu []int, s map[int]int) {
|
|
var (
|
|
newElem int // 生成的一个新的元素CID
|
|
)
|
|
s = make(map[int]int)
|
|
|
|
for k, v := range this.Plat {
|
|
|
|
if v.Cid == 0 {
|
|
continue
|
|
}
|
|
x := int32(k % Height) // x
|
|
newElem = 0
|
|
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 {
|
|
for _, v1 := range this.operElem {
|
|
for i := 0; i <= 3; i++ {
|
|
if int(v1) == k+i {
|
|
newElem = int(v1)
|
|
break
|
|
}
|
|
}
|
|
if newElem != 0 {
|
|
break
|
|
}
|
|
}
|
|
if newElem == 0 {
|
|
newElem = k + 2 // 给个默认值
|
|
}
|
|
// 如果当前生成的也是一个特殊的元素 直接消除
|
|
if this.Plat[newElem].Special == 0 {
|
|
s[newElem] = FourUType
|
|
}
|
|
|
|
xiaochu = append(xiaochu, []int{k, k + 1, k + 2, k + 3}...)
|
|
for _, v := range xiaochu {
|
|
this.Plat[v].Cid = 0
|
|
}
|
|
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 {
|
|
for _, v1 := range this.operElem {
|
|
for i := 0; i <= 3; i++ {
|
|
if int(v1) == k+i*Width {
|
|
newElem = int(v1) // 创建一个特殊的元素
|
|
break
|
|
}
|
|
}
|
|
if newElem != 0 {
|
|
break
|
|
}
|
|
}
|
|
if newElem == 0 {
|
|
newElem = k + 2*Width // 给个默认值
|
|
}
|
|
|
|
// 如果当前生成的也是一个特殊的元素 直接消除
|
|
if this.Plat[newElem].Special == 0 {
|
|
s[newElem] = FourLType
|
|
}
|
|
xiaochu = append(xiaochu, k+Width)
|
|
xiaochu = append(xiaochu, []int{k, k + Width, k + 2*Width, k + 3*Width}...)
|
|
for _, v := range xiaochu {
|
|
this.Plat[v].Cid = 0
|
|
}
|
|
bEliminate = true
|
|
}
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (this *MapData) Check3X() (bEliminate bool, xiaochu []int) {
|
|
//var xiaochu []int // 即将消除的key
|
|
for k, v := range this.Plat {
|
|
b := false
|
|
for _, e := range this.operElem {
|
|
if e == int32(k) {
|
|
b = true
|
|
break
|
|
}
|
|
}
|
|
if v.Cid == 0 && !b {
|
|
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}...)
|
|
this.Plat[k].Cid = 0
|
|
this.Plat[k+1].Cid = 0
|
|
this.Plat[k+2].Cid = 0
|
|
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}...)
|
|
this.Plat[k].Cid = 0
|
|
this.Plat[k+Width].Cid = 0
|
|
this.Plat[k+2*Width].Cid = 0
|
|
bEliminate = true
|
|
}
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 校验地图可消除的 判断各组上面2个和右边两个是否三个相等
|
|
// xc 判断用来是否加体力
|
|
func (this *MapData) CheckMap(color int32, bSkill bool) (szMap []*pb.MapData, xc bool) {
|
|
var (
|
|
tXiaochu map[int]struct{}
|
|
curScore int32
|
|
energy int32
|
|
new map[int]int
|
|
x map[int]struct{}
|
|
//s map[int]int
|
|
)
|
|
|
|
for {
|
|
new = make(map[int]int)
|
|
x = make(map[int]struct{})
|
|
tXiaochu = make(map[int]struct{})
|
|
curScore = 0
|
|
energy = 0
|
|
//s = make(map[int]int)
|
|
for i := 1; i <= 6; i++ {
|
|
xc, s := this.CheckElem(int32(i))
|
|
for k, v := range s {
|
|
new[k] = v
|
|
}
|
|
for _, v := range xc {
|
|
for _, v1 := range v {
|
|
tXiaochu[v1] = struct{}{}
|
|
}
|
|
}
|
|
}
|
|
for id := range tXiaochu {
|
|
if _, ok := new[id]; ok {
|
|
if this.Plat[id].Color == color {
|
|
energy++
|
|
}
|
|
curScore += this.Plat[id].Score
|
|
this.oid++ // 生成一个新的类型元素
|
|
if this.module == nil { // 稍后删掉 方便测试
|
|
this.Plat[id] = &pb.GirdeData{
|
|
Oid: this.oid,
|
|
Color: this.Plat[id].Color,
|
|
Cid: 2*(this.Plat[id].Color-1) + 6 + int32(new[id]),
|
|
Score: 1,
|
|
Special: int32(new[id]),
|
|
}
|
|
} else {
|
|
if s := this.Plat[id].Special; s != 0 {
|
|
for key := range this.SpecialElem(id, s) {
|
|
x[key] = struct{}{}
|
|
}
|
|
x[id] = struct{}{}
|
|
}
|
|
|
|
if conf, err := this.module.configure.GetGameBlock(this.Plat[id].Color, int32(new[id])); err == nil {
|
|
this.Plat[id] = &pb.GirdeData{
|
|
Oid: this.oid,
|
|
Color: this.Plat[id].Color,
|
|
Cid: conf.Key,
|
|
Score: conf.Score,
|
|
Special: conf.Type,
|
|
}
|
|
}
|
|
}
|
|
continue
|
|
}
|
|
if s := this.Plat[id].Special; s != 0 {
|
|
for key := range this.SpecialElem(id, s) {
|
|
x[key] = struct{}{}
|
|
}
|
|
|
|
}
|
|
x[id] = struct{}{}
|
|
}
|
|
|
|
for id := range x {
|
|
if this.Plat[id].Color == color {
|
|
energy++
|
|
}
|
|
curScore += this.Plat[id].Score
|
|
this.Plat[id] = &pb.GirdeData{}
|
|
this.operElem = append(this.operElem, int32(id))
|
|
}
|
|
if this.DropGirde() {
|
|
if !bSkill {
|
|
energy = 0
|
|
}
|
|
szMap = append(szMap, &pb.MapData{
|
|
Data: this.GetPalatData(),
|
|
CurSocre: curScore,
|
|
CurEnergy: energy,
|
|
})
|
|
}
|
|
|
|
// 检查掉落
|
|
this.operElem = []int32{} // 初始化操作元素
|
|
if curScore == 0 {
|
|
break
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// 下落 生成新的格子 (返回掉落所获得的分数)
|
|
func (this *MapData) DropGirde() bool {
|
|
// 需要填充的格子
|
|
var fill []int
|
|
bDrop := false
|
|
for i := 0; i < Width; i++ {
|
|
for j := 0; j < Height; j++ {
|
|
index := i*Width + j
|
|
if this.Plat[index].Cid == 0 { // 说明这列有空
|
|
bDrop = true
|
|
var add int
|
|
for m := j + 1; m < Height; m++ {
|
|
k1 := i*Width + m
|
|
if this.Plat[k1].Cid != 0 {
|
|
this.Plat[index] = this.Plat[k1]
|
|
index++
|
|
add++
|
|
}
|
|
}
|
|
for m := j + add; m < Height; m++ {
|
|
k1 := i*Width + m
|
|
fill = append(fill, k1)
|
|
}
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if len(fill) == 0 {
|
|
return bDrop
|
|
}
|
|
sz := this.CreateGride(len(fill))
|
|
for pos, id := range fill {
|
|
this.Plat[id] = sz[pos]
|
|
}
|
|
if this.iType > 1 {
|
|
var sp int32
|
|
var mp map[int]struct{}
|
|
mp = make(map[int]struct{}, 0)
|
|
var count int32
|
|
|
|
for pos, v := range this.Plat {
|
|
if this.iType == 4 {
|
|
if v.Special == 5 || v.Special == 6 ||
|
|
v.Special == 7 || v.Special == 8 {
|
|
mp[pos] = struct{}{}
|
|
count++
|
|
if count >= 2 {
|
|
break
|
|
}
|
|
}
|
|
} else if this.iType == 3 {
|
|
if v.Special == 4 {
|
|
mp[pos] = struct{}{}
|
|
count++
|
|
if count >= 2 {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if len(mp) < 2 {
|
|
ilen := 2 - len(mp)
|
|
mp = make(map[int]struct{}, ilen)
|
|
for i := 0; i < ilen; i++ {
|
|
n1, _ := rand.Int(rand.Reader, big.NewInt(int64(len(fill))))
|
|
mp[fill[n1.Int64()]] = struct{}{}
|
|
}
|
|
|
|
for key := range mp {
|
|
if this.iType == 3 {
|
|
sp = 4
|
|
} else if this.iType == 4 {
|
|
n1, _ := rand.Int(rand.Reader, big.NewInt(4)) // 随机一个消除类型
|
|
sp = int32(n1.Int64()) + 5
|
|
}
|
|
if conf, err := this.module.configure.GetGameBlock(this.Plat[key].Color, sp); err == nil {
|
|
this.Plat[key].Cid = conf.Key
|
|
this.Plat[key].Special = conf.Type
|
|
this.Plat[key].Score = conf.Score
|
|
} else { // 错误打印
|
|
this.module.Errorf("cond conf err :%v,color:%d", err, this.Plat[key].Color)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return bDrop
|
|
}
|
|
|
|
// 深拷贝
|
|
func (this *MapData) GetPalatData() (data []*pb.GirdeData) {
|
|
for _, v := range this.Plat {
|
|
data = append(data, &pb.GirdeData{
|
|
Oid: v.Oid,
|
|
Color: v.Color,
|
|
Cid: v.Cid,
|
|
Score: v.Score,
|
|
Special: v.Special,
|
|
})
|
|
}
|
|
return data
|
|
}
|
|
|
|
// ai操作
|
|
func (this *MapData) AiSwapGirde() (szMap []*pb.MapData, oid1 int32, oid2 int32, bAddPs bool) {
|
|
|
|
for pos := 0; pos < Total; pos++ {
|
|
y := pos % Height
|
|
if y < Height-1 {
|
|
if b := this.SwapGirde(int32(pos), int32(pos+1)); b {
|
|
oid1 = this.Plat[pos+1].Oid
|
|
oid2 = this.Plat[pos].Oid
|
|
if m, b := this.CheckMap(2, true); len(m) == 0 {
|
|
this.SwapGirde(int32(pos+1), int32(pos))
|
|
this.operElem = []int32{}
|
|
oid1 = 0
|
|
oid2 = 0
|
|
} else {
|
|
|
|
szMap = append(szMap, m...)
|
|
bAddPs = b
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if pos/Width+1 < Width {
|
|
if b := this.SwapGirde(int32(pos), int32(pos+Width)); b {
|
|
oid1 = this.Plat[pos+Width].Oid
|
|
oid2 = this.Plat[pos].Oid
|
|
if m, b := this.CheckMap(2, true); len(m) == 0 {
|
|
this.SwapGirde(int32(pos+Width), int32(pos))
|
|
this.operElem = []int32{}
|
|
oid1 = 0
|
|
oid2 = 0
|
|
} else {
|
|
szMap = append(szMap, m...)
|
|
bAddPs = b
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 释放技能 技能id 和参数
|
|
func (this *MapData) SkillUp(pos int32, color int32, skillid int32, value int32, bDrop bool) (x map[int]struct{}, szMap []*pb.MapData) {
|
|
var (
|
|
skillScore int32 // 技能获得的分数
|
|
skillEnergy int32 // 技能获得的能量
|
|
ids []int
|
|
)
|
|
x = make(map[int]struct{})
|
|
|
|
switch skillid {
|
|
case 1:
|
|
ids = utils.RandomNumbers(0, Total-1, int(value))
|
|
case 2:
|
|
for i := 0; i < Height; i++ {
|
|
ids = append(ids, 3*Width+i)
|
|
}
|
|
case 3: // 将随机6个宝石染成当前盘面上颜色最多的宝石
|
|
this.SkillChangeColor(value)
|
|
bDrop = false
|
|
szMap = append(szMap, &pb.MapData{
|
|
Data: this.GetPalatData(),
|
|
CurSocre: skillScore,
|
|
CurEnergy: skillEnergy,
|
|
})
|
|
if list, _ := this.CheckMap(color, false); len(list) > 0 {
|
|
szMap = append(szMap, list...)
|
|
}
|
|
case 4:
|
|
x := int(pos / Width)
|
|
y := int(pos % Height)
|
|
for i := 1; i < 7; i++ {
|
|
|
|
if x-i >= 0 && y+i < Height { // 左上
|
|
ids = append(ids, (x-i)*Width+(y+i))
|
|
}
|
|
if x-i >= 0 && y-i >= 0 { // 左下
|
|
ids = append(ids, (x-i)*Width+(y-i))
|
|
}
|
|
|
|
if x+i < Width && y+i < Height { // 右上
|
|
ids = append(ids, (x+i)*Width+(y+i))
|
|
}
|
|
if x+i < Width && y-i >= 0 { // 右下
|
|
ids = append(ids, (x+i)*Width+(y-i))
|
|
}
|
|
}
|
|
case 5:
|
|
ids = append(ids, int(pos)) // 包含自己
|
|
x := int(pos / Width)
|
|
y := int(pos % Height)
|
|
if x-1 >= 0 { // 左
|
|
ids = append(ids, (x-1)*Width+(y))
|
|
}
|
|
if y-1 >= 0 { // 下
|
|
ids = append(ids, (x)*Width+(y-1))
|
|
}
|
|
if y+1 < Height { // 上
|
|
ids = append(ids, (x)*Width+(y+1))
|
|
}
|
|
if x+1 < Width { // 右
|
|
ids = append(ids, (x+1)*Width+(y))
|
|
}
|
|
if x-1 >= 0 && y+1 < Height { // 左上
|
|
ids = append(ids, (x-1)*Width+(y+1))
|
|
}
|
|
if x-1 >= 0 && y-1 >= 0 { // 左下
|
|
ids = append(ids, (x-1)*Width+(y-1))
|
|
}
|
|
|
|
if x+1 < Width && y+1 < Height { // 右上
|
|
ids = append(ids, (x+1)*Width+(y+1))
|
|
}
|
|
if x+1 < Width && y-1 >= 0 { // 右下
|
|
ids = append(ids, (x+1)*Width+(y-1))
|
|
}
|
|
case 8:
|
|
for k := range this.SkillManYan(pos, 0) {
|
|
ids = append(ids, k) // 转换成最终消除的坐标
|
|
}
|
|
ids = append(ids, int(pos)) // 包含自己
|
|
default:
|
|
this.module.Errorf("not found skill:%d", skillid)
|
|
return
|
|
}
|
|
|
|
for _, id := range ids {
|
|
if s := this.Plat[id].Special; s != 0 {
|
|
for k := range this.SpecialElem(id, s) {
|
|
x[k] = struct{}{}
|
|
}
|
|
}
|
|
x[id] = struct{}{}
|
|
}
|
|
if bDrop {
|
|
for key := range x {
|
|
if this.Plat[key].Color == color {
|
|
skillEnergy += 1
|
|
}
|
|
skillScore += this.Plat[key].Score
|
|
this.Plat[key] = &pb.GirdeData{}
|
|
}
|
|
if this.DropGirde() {
|
|
szMap = append(szMap, &pb.MapData{
|
|
Data: this.GetPalatData(),
|
|
CurSocre: skillScore,
|
|
CurEnergy: skillEnergy,
|
|
})
|
|
if list, _ := this.CheckMap(color, false); len(list) > 0 {
|
|
szMap = append(szMap, list...)
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// 校验当前地图 有没有能消除的
|
|
func (this *MapData) CheckAndRefreshPlat() (bEliminate bool) {
|
|
bEliminate = false
|
|
for k, v := range this.Plat {
|
|
if v.Color == 0 {
|
|
continue
|
|
}
|
|
x := int32(k % Height)
|
|
y := int32(k / Height)
|
|
if x+2 < Height { // 上
|
|
k1 := this.Plat[k].Color
|
|
k2 := this.Plat[k+1].Color
|
|
if k1 == k2 { // 校验k3 左边和右边
|
|
if true {
|
|
pos := k + 2
|
|
if pos/Width-1 >= 0 { // 左
|
|
p := this.Plat[pos-Width].Color
|
|
if p == k1 {
|
|
bEliminate = true
|
|
return
|
|
}
|
|
}
|
|
if pos/Width+1 < Width { // 右
|
|
p := this.Plat[pos+Width].Color
|
|
if p == k1 {
|
|
bEliminate = true
|
|
return
|
|
}
|
|
}
|
|
if pos%Height+1 < Height { // 上
|
|
p := this.Plat[pos+1].Color
|
|
if p == k1 {
|
|
bEliminate = true
|
|
return
|
|
}
|
|
}
|
|
}
|
|
// xia
|
|
pos := k - 1
|
|
if x > 0 {
|
|
if pos%Height >= 0 { // 左右
|
|
if pos/Width-1 >= 0 { //左
|
|
p := this.Plat[pos-Width].Color
|
|
if p == k1 {
|
|
bEliminate = true
|
|
return
|
|
}
|
|
}
|
|
if pos/Width+1 < Width { // 右
|
|
p := this.Plat[pos+Width].Color
|
|
if p == k1 {
|
|
bEliminate = true
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if x > 1 {
|
|
p := this.Plat[pos-1].Color
|
|
if p == k1 {
|
|
bEliminate = true
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if y+2 < Height { // 左
|
|
k1 := this.Plat[k].Color
|
|
k2 := this.Plat[k+Width].Color
|
|
|
|
if k1 == k2 { // 校验k3 左边和右边
|
|
if true {
|
|
pos := k + 2*Width
|
|
if pos/Width+1 < Width { // 右
|
|
p := this.Plat[pos+Width].Color
|
|
if p == k1 {
|
|
bEliminate = true
|
|
return
|
|
}
|
|
}
|
|
if pos%Height+1 < Width { // 上
|
|
p := this.Plat[pos+1].Color
|
|
if p == k1 {
|
|
bEliminate = true
|
|
return
|
|
}
|
|
}
|
|
if pos%Height-1 >= 0 {
|
|
p := this.Plat[pos-1].Color
|
|
if p == k1 {
|
|
bEliminate = true
|
|
return
|
|
}
|
|
}
|
|
}
|
|
if true {
|
|
pos := k - Width
|
|
if pos >= 0 {
|
|
if pos%Height+1 < Width { // 上
|
|
p := this.Plat[pos+1].Color
|
|
if p == k1 {
|
|
bEliminate = true
|
|
return
|
|
}
|
|
}
|
|
if pos%Height-1 >= 0 { // 下
|
|
p := this.Plat[pos-1].Color
|
|
if p == k1 {
|
|
bEliminate = true
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
if pos/Height-1 >= 0 {
|
|
p := this.Plat[pos-Height].Color
|
|
if p == k1 {
|
|
bEliminate = true
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for k, v := range this.Plat {
|
|
if v.Color == 0 {
|
|
continue
|
|
}
|
|
// x := int32(k % Height) // x
|
|
y := int32(k / Height) // y
|
|
|
|
if y+2 < Width {
|
|
k1 := this.Plat[k].Color
|
|
k2 := this.Plat[k+2*Width].Color
|
|
pos := k + Width
|
|
if k1 == k2 {
|
|
// 上
|
|
if pos%Height+1 < Height {
|
|
p := this.Plat[pos+1].Color
|
|
if p == k1 {
|
|
bEliminate = true
|
|
return
|
|
}
|
|
}
|
|
if pos%Height-1 >= 0 {
|
|
p := this.Plat[pos-1].Color
|
|
if p == k1 {
|
|
bEliminate = true
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// 上下检测中间元素左右互换
|
|
for k, v := range this.Plat {
|
|
if v.Color == 0 {
|
|
continue
|
|
}
|
|
|
|
if k%Height+2 < Height {
|
|
k1 := this.Plat[k].Color
|
|
k2 := this.Plat[k+2].Color
|
|
pos := k + 1
|
|
if k1 == k2 {
|
|
if pos/Height+1 < Width { // 右
|
|
p := this.Plat[pos+Width].Color
|
|
if p == k1 {
|
|
bEliminate = true
|
|
return
|
|
}
|
|
}
|
|
if pos/Height-1 >= 0 { // 右
|
|
p := this.Plat[pos-Width].Color
|
|
if p == k1 {
|
|
bEliminate = true
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if !bEliminate {
|
|
fmt.Printf("=====地图数据不能交换===========\n")
|
|
this.Debugf()
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 生成一个不能消除的地图
|
|
func (this *MapData) SetIndelibilityPlat() {
|
|
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 {
|
|
if this.Plat[k+2].Special == 0 {
|
|
newId := k + 2
|
|
oldId := Total - 1
|
|
for i := 0; i < Total; i++ {
|
|
if this.Plat[oldId].Color == k3 { // 找到颜色不一样的
|
|
if oldId > 0 {
|
|
oldId -= 1
|
|
}
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
tmp := new(pb.GirdeData)
|
|
*tmp = *this.Plat[newId]
|
|
this.Plat[newId] = this.Plat[oldId]
|
|
this.Plat[oldId] = tmp
|
|
}
|
|
}
|
|
}
|
|
|
|
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 {
|
|
if this.Plat[k+2*Width].Special == 0 { // 找最后一个交换
|
|
newId := k + 2*Width
|
|
oldId := Total - 1
|
|
for i := 0; i < Total; i++ {
|
|
if this.Plat[oldId].Color == k3 { // 找到颜色不一样的
|
|
oldId -= 1
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
tmp := new(pb.GirdeData)
|
|
*tmp = *this.Plat[newId]
|
|
this.Plat[newId] = this.Plat[oldId]
|
|
this.Plat[oldId] = tmp
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for {
|
|
if b, _ := this.Check3X(); b {
|
|
fmt.Printf("plat init\n")
|
|
if _, xc := this.CheckMap(0, false); !xc {
|
|
break
|
|
}
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
|
|
this.Plat = this.GetPalatData()
|
|
}
|
|
|
|
// 重新洗牌
|
|
func (this *MapData) RedsetPlatData() {
|
|
|
|
for i := 0; i < Total-1; i++ {
|
|
targetId := comm.GetRandNum(0, Total-1)
|
|
if i == int(targetId) {
|
|
continue
|
|
}
|
|
tmp := new(pb.GirdeData)
|
|
*tmp = *this.Plat[i]
|
|
this.Plat[i] = this.Plat[targetId]
|
|
this.Plat[targetId] = tmp
|
|
}
|
|
|
|
this.SetIndelibilityPlat()
|
|
}
|
|
|
|
//四周蔓延 第一次100% 第二次 60% 第三次 30% 第四次 10% 最多4次
|
|
func (this *MapData) SkillManYan(pos int32, count int32) (m map[int]struct{}) {
|
|
m = make(map[int]struct{}, 0)
|
|
var sz []int
|
|
var percent int32
|
|
var cur []int
|
|
// 先找出可以蔓延的方向
|
|
x := int(pos / Width)
|
|
y := int(pos % Height)
|
|
if x-1 >= 0 { // 左
|
|
sz = append(sz, (x-1)*Width+(y))
|
|
}
|
|
if y-1 >= 0 { // 下
|
|
sz = append(sz, (x)*Width+(y-1))
|
|
}
|
|
if y+1 < Height { // 上
|
|
sz = append(sz, (x)*Width+(y+1))
|
|
}
|
|
if x+1 < Width { // 右
|
|
sz = append(sz, (x+1)*Width+(y))
|
|
}
|
|
|
|
if count == 0 { // 蔓延技能概率调整支持配置
|
|
percent = 100
|
|
} else if count == 1 {
|
|
percent = 60
|
|
} else if count == 2 || count == 3 {
|
|
percent = 30
|
|
} else {
|
|
return
|
|
}
|
|
|
|
szid := utils.RandomNumbers(0, len(sz), 2)
|
|
for _, v := range szid {
|
|
if percent >= comm.GetRandNum(0, 100) {
|
|
m[sz[v]] = struct{}{}
|
|
cur = append(cur, sz[v])
|
|
}
|
|
}
|
|
count++
|
|
|
|
for _, k := range cur {
|
|
for k1 := range this.SkillManYan(int32(k), count) { // 递归蔓延
|
|
m[k1] = struct{}{}
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 获取BoomType 类型周围的所有元素(pos 四周+ 四周的上下左右)
|
|
func (this *MapData) GetBoomElem(pos int) (elem []int) {
|
|
|
|
x := int(pos / Width)
|
|
y := int(pos % Height)
|
|
if x-1 >= 0 { // 左
|
|
elem = append(elem, (x-1)*Width+(y))
|
|
}
|
|
if y-1 >= 0 { // 下
|
|
elem = append(elem, (x)*Width+(y-1))
|
|
}
|
|
if y+1 < Height { // 上
|
|
elem = append(elem, (x)*Width+(y+1))
|
|
}
|
|
if x+1 < Width { // 右
|
|
elem = append(elem, (x+1)*Width+(y))
|
|
}
|
|
if x-1 >= 0 && y+1 < Height { // 左上
|
|
elem = append(elem, (x-1)*Width+(y+1))
|
|
}
|
|
if x-1 >= 0 && y-1 >= 0 { // 左下
|
|
elem = append(elem, (x-1)*Width+(y-1))
|
|
}
|
|
|
|
if x+1 < Width && y+1 < Height { // 右上
|
|
elem = append(elem, (x+1)*Width+(y+1))
|
|
}
|
|
if x+1 < Width && y-1 >= 0 { // 右下
|
|
elem = append(elem, (x+1)*Width+(y-1))
|
|
}
|
|
///
|
|
if x-2 >= 0 { // 左左
|
|
elem = append(elem, (x-2)*Width+(y))
|
|
}
|
|
if y-2 >= 0 { // 下下
|
|
elem = append(elem, (x)*Width+(y-2))
|
|
}
|
|
if y+2 < Height { // 上上
|
|
elem = append(elem, (x)*Width+(y+2))
|
|
}
|
|
if x+2 < Width { // 右右
|
|
elem = append(elem, (x+2)*Width+(y))
|
|
}
|
|
return
|
|
}
|
|
|
|
func (this *MapData) GetFireBoom(pos int, itype int32) (elem []int) {
|
|
x := int(pos / Width)
|
|
y := int(pos % Height)
|
|
if itype == FireUp || itype == FireDown || itype == FireLeft || itype == FireRight {
|
|
elem = append(elem, pos)
|
|
}
|
|
switch itype {
|
|
case FireUp: //上烟火
|
|
for i := 0; i < Height; i++ {
|
|
if y+1 < Height { // 上上
|
|
elem = append(elem, (x)*Width+(y+1))
|
|
y += 1
|
|
}
|
|
}
|
|
case FireDown: //下烟火
|
|
for i := 0; i < Height; i++ {
|
|
if y-1 >= 0 { // 下下
|
|
elem = append(elem, (x)*Width+(y-1))
|
|
y -= 1
|
|
}
|
|
}
|
|
case FireLeft: //左烟火
|
|
for i := 0; i < Height; i++ {
|
|
if x-1 >= 0 { // 左左
|
|
elem = append(elem, (x-1)*Width+(y))
|
|
x -= 1
|
|
}
|
|
}
|
|
case FireRight: //右烟火
|
|
for i := 0; i < Height; i++ {
|
|
if x+1 < Width { // 右右
|
|
elem = append(elem, (x+1)*Width+(y))
|
|
x += 1
|
|
}
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 特殊类型元素 统一处理
|
|
func (this *MapData) SpecialElem(id int, s int32) (x map[int]struct{}) {
|
|
if s <= 0 {
|
|
return
|
|
}
|
|
|
|
x = make(map[int]struct{})
|
|
if s == FourUType { // 4消上下类型
|
|
for i := 0; i < Height; i++ { // id 的一条线位置
|
|
x[(id/Width)*Height+i] = struct{}{}
|
|
}
|
|
} else if s == FourLType { // 左右类型
|
|
for i := 0; i < Width; i++ { // id 的一条线位置
|
|
x[id%Height+i*Width] = struct{}{}
|
|
}
|
|
} else if s == FiveType { // 随机消除
|
|
// 获取配置
|
|
if c, _ := this.module.configure.GetGameBlock(this.Plat[id].Color, FiveType); c != nil {
|
|
ids := utils.RandomNumbers(0, Total-1, int(c.Value))
|
|
for _, v := range ids {
|
|
x[v] = struct{}{}
|
|
}
|
|
}
|
|
|
|
} else if s == BoomType { // 炸弹类型 带走周围一圈+ 上下左右
|
|
for _, key := range this.GetBoomElem(id) {
|
|
x[key] = struct{}{}
|
|
}
|
|
} else if s == FireUp || s == FireDown || s == FireLeft || s == FireRight { // 烟花技能
|
|
for _, key := range this.GetFireBoom(id, s) {
|
|
x[key] = struct{}{}
|
|
}
|
|
}
|
|
this.Plat[id].Special = 0
|
|
x[id] = struct{}{}
|
|
for k := range x {
|
|
if k == id {
|
|
continue
|
|
}
|
|
if this.Plat[k].Special != 0 {
|
|
ids := this.SpecialElem(k, this.Plat[k].Special) // 递归调用
|
|
for key := range ids {
|
|
x[key] = struct{}{}
|
|
}
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
func (this *MapData) HitElem(color int32, curid int32) (szMap []*pb.MapData) {
|
|
var energy int32
|
|
var curScore int32
|
|
if this.Plat[curid].Special == 0 {
|
|
if this.Plat[curid].Color == color {
|
|
energy++
|
|
}
|
|
curScore = this.Plat[curid].Score
|
|
this.Plat[curid] = &pb.GirdeData{}
|
|
if this.DropGirde() {
|
|
szMap = append(szMap, &pb.MapData{
|
|
Data: this.GetPalatData(),
|
|
CurSocre: curScore,
|
|
CurEnergy: energy,
|
|
})
|
|
}
|
|
sz, _ := this.CheckMap(color, false)
|
|
szMap = append(szMap, sz...)
|
|
} else {
|
|
x := this.SpecialElem(int(curid), this.Plat[curid].Special)
|
|
for id := range x {
|
|
if this.Plat[id].Color == color {
|
|
energy++
|
|
}
|
|
curScore += this.Plat[id].Score
|
|
this.Plat[id] = &pb.GirdeData{}
|
|
this.operElem = append(this.operElem, int32(id))
|
|
}
|
|
if this.DropGirde() {
|
|
szMap = append(szMap, &pb.MapData{
|
|
Data: this.GetPalatData(),
|
|
CurSocre: curScore,
|
|
CurEnergy: energy,
|
|
})
|
|
}
|
|
sz, _ := this.CheckMap(color, false)
|
|
szMap = append(szMap, sz...)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (this *MapData) ShuffleElem() {
|
|
|
|
for i := 0; i < Total; i++ {
|
|
n1, _ := rand.Int(rand.Reader, big.NewInt(Total))
|
|
newId := n1.Int64()
|
|
if i != int(n1.Int64()) {
|
|
tmp := new(pb.GirdeData)
|
|
*tmp = *this.Plat[newId]
|
|
this.Plat[newId] = this.Plat[i]
|
|
this.Plat[i] = tmp
|
|
}
|
|
}
|
|
this.SetIndelibilityPlat()
|
|
}
|
|
|
|
func (this *MapData) HitCrossElem(color int32, curid int32) (szMap []*pb.MapData) {
|
|
var (
|
|
ids []int // 十字id
|
|
energy int32
|
|
curScore int32
|
|
xc map[int]struct{}
|
|
)
|
|
x := int(curid / Width)
|
|
y := int(curid % Height)
|
|
xc = make(map[int]struct{}, 0)
|
|
for i := 0; i < Height; i++ { // 上下
|
|
if y+i < Height {
|
|
ids = append(ids, x*Width+(y+i))
|
|
}
|
|
if y-i > 0 {
|
|
ids = append(ids, x*Width+(y-i))
|
|
}
|
|
}
|
|
|
|
for i := 0; i < Height; i++ { // 左右
|
|
if x+i < Width {
|
|
ids = append(ids, (x+i)*Width+(y))
|
|
}
|
|
if x-i >= 0 {
|
|
ids = append(ids, (x-i)*Width+(y))
|
|
}
|
|
}
|
|
for _, v := range ids {
|
|
if this.Plat[curid].Special == 0 {
|
|
xc[v] = struct{}{}
|
|
} else {
|
|
for key := range this.SpecialElem(int(v), this.Plat[v].Special) {
|
|
xc[key] = struct{}{}
|
|
}
|
|
}
|
|
}
|
|
|
|
for id := range xc {
|
|
if this.Plat[id].Color == color {
|
|
energy++
|
|
}
|
|
curScore += this.Plat[id].Score
|
|
this.Plat[id] = &pb.GirdeData{}
|
|
this.operElem = append(this.operElem, int32(id))
|
|
}
|
|
if this.DropGirde() {
|
|
szMap = append(szMap, &pb.MapData{
|
|
Data: this.GetPalatData(),
|
|
CurSocre: curScore,
|
|
CurEnergy: energy,
|
|
})
|
|
}
|
|
return
|
|
}
|
|
|
|
func (this *MapData) checkSp(e []int) (oid int32) {
|
|
oid = -1
|
|
for _, v := range this.operElem {
|
|
for _, v1 := range e {
|
|
if v == int32(v1) {
|
|
oid = v
|
|
break
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
// 检测一个元素
|
|
func (this *MapData) CheckElem(color int32) (xc [][]int, sp map[int]int) {
|
|
var (
|
|
w [14][]int32
|
|
s1 [][]int // heng
|
|
s2 [][]int // shu
|
|
)
|
|
sp = make(map[int]int)
|
|
for pos, v := range this.Plat {
|
|
x := pos / Width
|
|
y := pos % Height
|
|
for i := 0; i < 7; i++ {
|
|
if x == i {
|
|
if v.Color == color {
|
|
w[i+7] = append(w[i+7], v.Color)
|
|
} else {
|
|
w[i+7] = append(w[i+7], 0)
|
|
}
|
|
|
|
}
|
|
if y == i {
|
|
if v.Color == color {
|
|
w[y] = append(w[y], v.Color)
|
|
} else {
|
|
w[y] = append(w[y], 0)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for i := 0; i < 14; i++ {
|
|
var s []int
|
|
for j := 0; j < 7; j++ {
|
|
if j+4 < 7 { // 5
|
|
if w[i][j] != 0 && w[i][j] == w[i][j+1] && w[i][j+2] == w[i][j+3] && w[i][j+3] == w[i][j+4] && w[i][j] == w[i][j+2] { // 1=2 3=4 4=5 1 =3
|
|
//5
|
|
if i >= 7 {
|
|
s = append(s, (i-7)*7+j)
|
|
s = append(s, (i-7)*7+j+1)
|
|
s = append(s, (i-7)*7+j+2)
|
|
s = append(s, (i-7)*7+j+3)
|
|
s = append(s, (i-7)*7+j+4)
|
|
s1 = append(s1, s)
|
|
} else {
|
|
s = append(s, (j)*7+i)
|
|
s = append(s, (j+1)*7+i)
|
|
s = append(s, (j+2)*7+i)
|
|
s = append(s, (j+3)*7+i)
|
|
s = append(s, (j+4)*7+i)
|
|
s2 = append(s2, s)
|
|
}
|
|
|
|
break
|
|
}
|
|
|
|
}
|
|
if j+3 < 7 { // 4
|
|
if w[i][j] != 0 && w[i][j] == w[i][j+1] && w[i][j+2] == w[i][j+3] && w[i][j] == w[i][j+2] { // 1=2 3=4 1 =3
|
|
//4
|
|
if i >= 7 {
|
|
s = append(s, (i-7)*7+j)
|
|
s = append(s, (i-7)*7+j+1)
|
|
s = append(s, (i-7)*7+j+2)
|
|
s = append(s, (i-7)*7+j+3)
|
|
s1 = append(s1, s)
|
|
} else {
|
|
s = append(s, (j)*7+i)
|
|
s = append(s, (j+1)*7+i)
|
|
s = append(s, (j+2)*7+i)
|
|
s = append(s, (j+3)*7+i)
|
|
s2 = append(s2, s)
|
|
//oid := this.checkSp(s)
|
|
// if 0 < oid {
|
|
// sp[int(oid)] = FourLType
|
|
// } else {
|
|
// sp[(j+1)*7+i] = FourLType
|
|
// }
|
|
}
|
|
break
|
|
}
|
|
}
|
|
if j+2 < 7 { // 3
|
|
if w[i][j] != 0 && w[i][j] == w[i][j+1] && w[i][j] == w[i][j+2] { // 1=2 1 =3
|
|
//3
|
|
if i >= 7 {
|
|
s = append(s, (i-7)*7+j)
|
|
s = append(s, (i-7)*7+j+1)
|
|
s = append(s, (i-7)*7+j+2)
|
|
s1 = append(s1, s)
|
|
|
|
} else {
|
|
s = append(s, (j)*7+i)
|
|
s = append(s, (j+1)*7+i)
|
|
s = append(s, (j+2)*7+i)
|
|
s2 = append(s2, s)
|
|
|
|
}
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for _, v := range s1 {
|
|
t, xj, new := CheckInSlice(v, s2) // 横竖相交
|
|
if len(t) > 0 {
|
|
xc = append(xc, t)
|
|
sp[xj] = FiveType
|
|
s2 = new[0:][0:]
|
|
} else {
|
|
if len(v) >= 5 {
|
|
sp[v[len(v)/2]] = FiveType
|
|
} else if len(v) >= 4 {
|
|
oid := this.checkSp(v)
|
|
if 0 < oid {
|
|
sp[int(oid)] = FourUType
|
|
} else {
|
|
sp[v[len(v)/2]] = FourUType
|
|
}
|
|
}
|
|
xc = append(xc, v)
|
|
}
|
|
}
|
|
for _, v := range s2 {
|
|
if len(v) >= 5 {
|
|
sp[v[len(v)/2]] = FiveType
|
|
} else if len(v) >= 4 {
|
|
oid := this.checkSp(v)
|
|
if 0 < oid {
|
|
sp[int(oid)] = FourLType
|
|
} else {
|
|
sp[v[len(v)/2]] = FourLType
|
|
}
|
|
}
|
|
xc = append(xc, v)
|
|
}
|
|
return
|
|
}
|
|
|
|
func CheckInSlice(s []int, sz [][]int) (si []int, xj int, newMatrix [][]int) {
|
|
newMatrix = make([][]int, len(sz))
|
|
for i := 0; i < len(sz); i++ {
|
|
newMatrix[i] = make([]int, len(sz[0]))
|
|
}
|
|
|
|
copy(newMatrix, sz)
|
|
for _, index := range s {
|
|
for pos, v := range sz {
|
|
bfound := false
|
|
for _, vs2 := range v {
|
|
if index == vs2 {
|
|
bfound = true
|
|
xj = index // 相交的点
|
|
si = append(si, v...)
|
|
si = append(si, s...)
|
|
break
|
|
}
|
|
}
|
|
if bfound {
|
|
newMatrix = append(newMatrix[:pos], newMatrix[pos+1:]...)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 将随机6个宝石染成当前盘面上颜色最多的宝石 (count 替换的数量)
|
|
func (this *MapData) SkillChangeColor(count int32) {
|
|
var (
|
|
// 替换成的颜色
|
|
color int32
|
|
elemCount map[int32]int32
|
|
)
|
|
elemCount = make(map[int32]int32, 0)
|
|
for _, v := range this.Plat {
|
|
elemCount[v.Color] += 1
|
|
}
|
|
|
|
for _, v := range elemCount {
|
|
if color < v {
|
|
color = v
|
|
}
|
|
}
|
|
for k, v := range elemCount {
|
|
if color == v {
|
|
color = k
|
|
break
|
|
}
|
|
}
|
|
for i := 0; i < int(count); i++ {
|
|
targetId := comm.GetRandNum(0, Total-1)
|
|
if this.Plat[targetId].Color == color {
|
|
i--
|
|
} else {
|
|
if this.Plat[targetId].Special == 0 {
|
|
this.Plat[targetId].Color = color // 变更颜色
|
|
this.Plat[targetId].Cid = color // 变更颜色
|
|
this.oid++
|
|
this.Plat[targetId].Oid = this.oid // 变唯一id
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|