482 lines
11 KiB
Go
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
|
|
}
|