开心消消乐游戏算法基础版

消消乐游戏算法

咱们常常看到各种的消除游戏,最近玩了两把消消乐,有想着来理解下其中的规则,市场上主流的是地图型的,几乎是无尽模式,各类消除特效,各类各样的过关方式,玩起来仍是不错的,就是遇到比较难的关卡,要多试几回,运气很是好的时候就过了,否则卡死。 三消涉及到简单的算法以下所示,我会根据这个搭建一个简单的消除游戏:git

  • 随机生成地图的算法
  • 遍历地图三个或三个以上连着的能够进行消除
  • 除去元素,上面的元素补下来
  • 涉及道具

因为篇幅关系,本章只会讲解生成地图的算法,后面我会附上写好的demo,但愿你们能有收获。github

一.随机生成地图的算法

首先游戏界面有各类各样的地图,须要知足如下几个条件:算法

  • 随机生成一张地图,可是不能有三个或三个以上在横向和纵向一样。
  • 用户在移动一步就能造成三个横向或者纵向可消除

1.1 先随机生成一个二维的数组

// 生成一个地图 9 * 9
function productMap(n) {
  const randomMap = []
  for (let i = 0; i < n; i++) {
    for (let j = 0; j < n; j++) {
      const value = parseInt(Math.random() * 5)
      if (!randomMap[i]) {
        randomMap[i] = []
      }
      randomMap[i].push(value)
    }
  }
  return randomMap
}
productMap(9)
复制代码

上面的代码能够获得一个随机的 9*9 的二维数组 当咱们生成一个二维数组后,会发现里面大几率会出现3个或3个以上在横向或者纵向连续且同样的值,这种数组是不知足消消乐的准则之一。数组

1.2 加入不能生成在横众方向连续3个或3个以上同样的值

1.3 最终代码

//  x方向判断有没有连续两个同色
 if (x > 1 && judgeSameColor(randomMap[y], value)) {
    value = getExceptRandom(value)
}
 //  y方向判断有没有连续两个同色
  if (
    y > 1 &&
    judgeSameColor(getTwoArrColumnByIndex(randomMap, y), value)
  ) {
    value = getExceptRandom(value)
  }
  
  // 判断是否连续2个同色
function judgeSameColor(arr, value) {
  return arr.find(
    (item, index) =>
      arr[index - 1] && item === value && arr[index - 1] === value
  )
}
// 获取二维数组某一列的值
function getTwoArrColumnByIndex(arr, n) {
  return arr.map(item => item[n])
}
复制代码

1.3 判断生成的二维数组是不是死地图

死地图条件:用户户移动相邻的一步,不能造成3个或3个以上连续的 【注意】:若是是死地图就须要从新生成地图bash

咱们能够对相邻移动一步的状况进行穷举以下:dom

  • 第一种:

注意 x 的位置,由于第二排有两个同样的连在一块儿,移动一步就能消除的状况有不少种方式,左右两边各有3种状况,找到一个这种,就不是死图了。 ui

  • 第二种:

第二种和第一种相似,只是放到了垂直方向 spa

  • 第三种:

根据上面这些穷举的状况,咱们就能够来写判断是不是死图的代码了。code

//判断是不是死图
function judgeCanRemoveByOneStep(map) {
  const resultStep = []
  let len = map.length
  for (let y = 0; y < len; y++) {
    for (let x = 0; x < len; x++) {
      const currentValue = map[y][x]
      // 考虑横轴方向
      if (x + 1 < len) {
        // 第一种状况
        if (map[y][x] === map[y][x + 1]) {
          if (x - 2 >= 0) {
            if (map[y][x - 2] === currentValue) {
              resultStep.push({ y, x })
              resultStep.push({ y, x: x + 1 })
              resultStep.push({ y, x: x - 2 })
              return resultStep
            }
          }
          if (x - 1 >= 0 && y - 1 >= 0 && map[y - 1][x - 1] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y, x: x + 1 })
            resultStep.push({ y: y - 1, x: x - 1 })
            return resultStep
          }
          if (x + 2 < len && y - 1 > 0 && map[y - 1][x + 2] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y, x: x + 1 })
            resultStep.push({ y: y - 1, x: x + 2 })
            return resultStep
          }
          if (x + 3 < len && map[y][x + 3] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y, x: x + 1 })
            resultStep.push({ y, x: x + 3 })
            return resultStep
          }
          if (x + 2 < len && y + 1 < len && map[y + 1][x + 2] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y, x: x + 1 })
            resultStep.push({ y: y + 1, x: x + 2 })
            return resultStep

          }
          if (x - 1 > 0 && y + 1 < len && map[y + 1][x - 1] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y, x: x + 1 })
            resultStep.push({ y: y + 1, x: x - 1 })
            return resultStep
          }
        }
        if (x - 1 >= 0 && map[y][x] === map[y + 1][x - 1]) {
          if (y + 1 <= len && x + 1 < len && map[y + 1][x + 1] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y: y + 1, x: x + 1 })
            resultStep.push({ y: y + 1, x: x - 1 })
            return resultStep
          }
          if (y + 2 < len && map[y + 2][x] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y: y + 2, x })
            resultStep.push({ y: y + 1, x: x - 1 })
            return resultStep
          }
        }
        if (x + 2 < len && map[y][x] === map[y][x + 2]) {
          if (x + 1 < len && map[y + 1][x + 1] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y: y, x: x + 2 })
            resultStep.push({ y: y + 1, x: x + 1 })
            return resultStep
          }
        }
      }
      // 纵向
      if (y + 1 < len) {
        if (map[y + 1][x] === currentValue) {
          if (y - 2 >= 0 && map[y - 2][x] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y: y + 1, x })
            resultStep.push({ y: y - 2, x })
            return resultStep
          }
          if (x + 1 < len && y - 1 > 0 && map[y - 1][x + 1] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y: y - 1, x })
            resultStep.push({ y: y - 1, x: x + 1 })
            return resultStep
          }
          if (x + 1 < len && y + 2 < len && map[y + 2][x + 1] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y: y + 1, x })
            resultStep.push({ y: y + 2, x: x + 1 })
            return resultStep
          }
          if (y + 3 < len && map[y + 3][x] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y: y + 1, x })
            resultStep.push({ y: y + 3, x: x })
            return resultStep
          }
          if (x - 1 >= 0 && y + 2 < len && map[y + 2][x - 1] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y: y + 1, x })
            resultStep.push({ y: y + 2, x: x - 1 })
            return resultStep
          }
          if (x - 1 >= 0 && y - 1 >= 0 && map[y - 1][x - 1] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y: y + 1, x })
            resultStep.push({ y: y - 1, x: x - 1 })
            return resultStep
          }
        }
      }
    }
  }
}

复制代码

上面的代码穷举了如下状况,这个算法执行速度仍是很快的,这个算法还记录了当前步骤,能够给用户提示。cdn

总结

咱们能够看下完整的代码,而后本身能够复制下面这段代码运行下,若是有问题,欢迎指出。完整代码以下:

// 生成一个地图 9 * 9
function productMap(n) {
  const randomMap = []
  for (let y = 0; y < n; y++) {
    for (let x = 0; x < n; x++) {
      let value = parseInt(Math.random() * 5 + 1)
      if (!randomMap[y]) {
        randomMap[y] = []
      }
      //  x方向判断有没有连续两个同色
      if (x > 1 && judgeSameColor(randomMap[y], value)) {
        value = getExceptRandom(value)
      }
      if (
        y > 1 &&
        judgeSameColor(getTwoArrColumnByIndex(randomMap, y), value)
      ) {
        value = getExceptRandom(value)
      }
      randomMap[y].push(value)
    }
  }
  return randomMap
}

function getExceptRandom(exceptNum) {
  let value = parseInt(Math.random() * 5 + 1)
  while (value === exceptNum) {
    value = parseInt(Math.random() * 5 + 1)
  }
  return value
}

/**
 * 获取二维数组某一列的值
 * @param {Array} arr
 * @param {number} n
 */
function getTwoArrColumnByIndex(arr, n) {
  return arr.map(item => item[n])
}
// 判断是否连续几个同色
function judgeSameColor(arr, value) {
  return arr.find(
    (item, index) =>
      arr[index - 1] && item === value && arr[index - 1] === value
  )
}

//判断是不是死图
function judgeCanRemoveByOneStep(map) {
  const resultStep = []
  let len = map.length
  for (let y = 0; y < len; y++) {
    for (let x = 0; x < len; x++) {
      const currentValue = map[y][x]
      // 考虑横轴方向
      if (x + 1 < len) {
        // 第一种状况
        if (map[y][x] === map[y][x + 1]) {
          if (x - 2 >= 0) {
            if (map[y][x - 2] === currentValue) {
              resultStep.push({ y, x })
              resultStep.push({ y, x: x + 1 })
              resultStep.push({ y, x: x - 2 })
              return resultStep
            }
          }
          if (x - 1 >= 0 && y - 1 >= 0 && map[y - 1][x - 1] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y, x: x + 1 })
            resultStep.push({ y: y - 1, x: x - 1 })
            return resultStep
          }
          if (x + 2 < len && y - 1 > 0 && map[y - 1][x + 2] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y, x: x + 1 })
            resultStep.push({ y: y - 1, x: x + 2 })
            return resultStep
          }
          if (x + 3 < len && map[y][x + 3] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y, x: x + 1 })
            resultStep.push({ y, x: x + 3 })
            return resultStep
          }
          if (x + 2 < len && y + 1 < len && map[y + 1][x + 2] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y, x: x + 1 })
            resultStep.push({ y: y + 1, x: x + 2 })
            return resultStep

          }
          if (x - 1 > 0 && y + 1 < len && map[y + 1][x - 1] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y, x: x + 1 })
            resultStep.push({ y: y + 1, x: x - 1 })
            return resultStep
          }
        }
        if (x - 1 >= 0 && map[y][x] === map[y + 1][x - 1]) {
          if (y + 1 <= len && x + 1 < len && map[y + 1][x + 1] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y: y + 1, x: x + 1 })
            resultStep.push({ y: y + 1, x: x - 1 })
            return resultStep
          }
          if (y + 2 < len && map[y + 2][x] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y: y + 2, x })
            resultStep.push({ y: y + 1, x: x - 1 })
            return resultStep
          }
        }
        if (x + 2 < len && map[y][x] === map[y][x + 2]) {
          if (x + 1 < len && map[y + 1][x + 1] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y: y, x: x + 2 })
            resultStep.push({ y: y + 1, x: x + 1 })
            return resultStep
          }
        }
      }
      // 纵向
      if (y + 1 < len) {
        if (map[y + 1][x] === currentValue) {
          if (y - 2 >= 0 && map[y - 2][x] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y: y + 1, x })
            resultStep.push({ y: y - 2, x })
            return resultStep
          }
          if (x + 1 < len && y - 1 > 0 && map[y - 1][x + 1] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y: y - 1, x })
            resultStep.push({ y: y - 1, x: x + 1 })
            return resultStep
          }
          if (x + 1 < len && y + 2 < len && map[y + 2][x + 1] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y: y + 1, x })
            resultStep.push({ y: y + 2, x: x + 1 })
            return resultStep
          }
          if (y + 3 < len && map[y + 3][x] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y: y + 1, x })
            resultStep.push({ y: y + 3, x: x })
            return resultStep
          }
          if (x - 1 >= 0 && y + 2 < len && map[y + 2][x - 1] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y: y + 1, x })
            resultStep.push({ y: y + 2, x: x - 1 })
            return resultStep
          }
          if (x - 1 >= 0 && y - 1 >= 0 && map[y - 1][x - 1] === currentValue) {
            resultStep.push({ y, x })
            resultStep.push({ y: y + 1, x })
            resultStep.push({ y: y - 1, x: x - 1 })
            return resultStep
          }
        }
      }
    }
  }
}

function getRandomMap(n) {
  let map = productMap(n)
  if (!judgeCanRemoveByOneStep(map)) {
    map = productMap(n)
  }
  console.log(map)
}
getRandomMap(9)

复制代码

如下是随机产生的地图

生成地图的方法我大概就将我理解的讲完了,后续有时间会具体分析其余的进行讲解,但愿能给你们带来收获,如下是个人项目源码,后续会逐渐完善这个项目。谢谢观看。

相关文章
相关标签/搜索