从18个形状、5个颜色、是否旋转3个维度设计一个独一无二的游戏数据

规则说明:

  1. 只有一个图块只出现一次,其他图块至少出现2次;
  2. 需要控制出现的颜色、形状、旋转来控制难度

设计思路

  1. 首先定义好所有的形状和颜色
  2. 根据配置的形状数量和颜色数量,组成一个图形合集A(静止的图形)
  3. 根据配置的旋转方向和最大旋转种类数,跟图形合集合并成一个完整的图形合集B(包含静止和旋转的图形),将合集打乱,第一个元素为独一无二的图块A,将图块A中合集B中删除
  4. 根据需要的图块数量,计算出最多需要生成的干扰项数量最大值(因为干扰图块至少有2个图块,故干扰数量最大值=图块数量/2并向下取整)
  5. 干扰数量最小值可以动态配置,最小值不可大于最大值;从干扰数量的最小值和最大值中随机取一个数字当作干扰数量,用图块数量-干扰数量
  6. 根据配置的最大旋转图块数量和独一无二的图块是否是旋转,计算出干扰图块中的旋转数量的最大值(如果旋转数量大于干扰数量,那旋转数量最大值等于干扰数量),从1-旋转数量最大值中随机取一个当作旋转的干扰图块数量
  7. 如果图形合集B的数量与干扰数量相等,那就直接把图形合集B当作最终的图形合集C
  8. 如果没有旋转的干扰图块,那就直接从图形合集A中取出干扰数量对应的图块当作最终的图形合集C
  9. 如果需要旋转的干扰图块,首先从图形合集B中的旋转图形中选取旋转的干扰图块数量放入图形合集C中,如果干扰数量不足,就从图形合集A中获取补充合集D(如果图形合集A中的图块不足,就取出A中所有的图块;),将补充合集D的所有图块(非独一无二的图块A,如果有多余的就补充,没有就算了)都放入图形合集C中
  10. 每个图块最少出现2次,那么会有(图块数量-1-(图形合集C的数量*2))个随机图形,每个随机图形从图形合集C中随机抽取一个。

代码实现

框架语言说明:Laravel 6.x,PHP7.2.25

    /**
     *
     * @param int $maxShapes 最多几个形状
     * @param int $maxColors 最多几个颜色
     * @param int $maxRotations 最大旋转种类
     * @param int $rotation 是否旋转
     * @param int $interferenceCount 图块数量
     * @return void
     */
    public function createDywe($maxShapes,$maxColors,$maxRotations,$rotation,$interferenceCount)
    {

      $shapeMap = array('shape1','shape2','shape3','shape4','shape5','shape6','shape7','shape8','shape9','shape10','shape11','shape12','shape13','shape14','shape15','shape16','shape17','shape18'); // 数字到形状的映射
      $colorMap = array('red', 'blue', 'green', 'orange', 'purple'); // 数字到颜色的映射
      // $rotationMap = array('0' => '静止', '1' => '顺时针', '2' => '逆时针'); // 数字到旋转方向的映射


      shuffle($shapeMap);
      shuffle($colorMap);
      $allMaps = [];
      foreach ($shapeMap as $key => $shape) {
        if($key < $maxShapes){
            foreach ($colorMap as $k => $color) {
              if($k < $maxColors){
                $allMaps[] = $shape.'-'.$color;
              }
            }
        }
      }
      $finalMaps = $allMaps;
        // 干扰图形的种类最多有多少种
      $maxCount = (int) floor(($interferenceCount - 1) / 2);
      $minCount = (int) ceil($maxCount / 2);
      if ($minCount < 1) {
          $minCount = 1;
      }
      //  干扰图形的数量
      $ganraoNum = rand($minCount, $maxCount);
      // 干扰图形种有几个旋转图形呢
      $rotaNum = 0;
      if ($rotation > 0) {
          $minRota = 1;
          // 旋转图形的数量
          $maxRota = $maxRotations > $ganraoNum ? $ganraoNum : $maxRotations;
          $rotaNum = rand($minRota, $maxRota);
      }
      // 多余的可以随机抽的
      $randNum = $interferenceCount - 1 - $ganraoNum * 2;
      // 加上旋转
      if($rotaNum > 0){
          switch ($rotation) {
            case 1:
                // 单方向旋转
                $fangxiang = rand(1,2);
                foreach ($allMaps as $map) {
                    $finalMaps[] = $map.'-'.$fangxiang;
                }
                break;
            case 2:
                // 多方向旋转
                // 单方向旋转
                foreach ($allMaps as $map) {
                    $fangxiang = rand(1,2);
                    $finalMaps[] = $map.'-'.$fangxiang;
                }
                break;
            default:
                break;
        }
      }



      $result = [];
      // 随机打乱
      shuffle($finalMaps);
      // 第一个就是独一无二的
      $result[] = $finalMaps[0];
      $answer = $finalMaps[0];
      unset($finalMaps[0]);
      shuffle($finalMaps);

      if(strpos($answer,'-1') !== false || strpos($answer,'-2') !== false ){
          if($rotaNum > 0){
            $rotaNum--;
          }
      }
      // 如果只有干扰项与元素一致
      if(count($finalMaps) === $ganraoNum){
        $maps = $finalMaps;
      }else{
        if($rotaNum > 0){
          // 有旋转的
          $rotationMaps = Arr::where($finalMaps,function($val){
            return count(explode('-',$val)) === 3;
          });
          $maps = [];
          shuffle($rotationMaps);
          // 取旋转干扰项
          foreach ($rotationMaps as $idx => $map) {
              if ($idx >= $rotaNum) {
                  break;
              }
              $maps[] = $map;
          }

          if($ganraoNum > count($maps) ){
            if(count($allMaps)< $ganraoNum - count($maps)){
              $randNum +=$ganraoNum - count($maps) -count($allMaps);
              $maps2 = $allMaps;
            }else{
              $maps2 = Arr::random($allMaps,$ganraoNum - count($maps));
            }
              foreach ($maps2 as $map) {
                 if($map === $answer){
                    // 再取一个新的
                    $maps3 = array_diff($allMaps,$maps2);
                    if(count($maps3) === 0){
                      continue;
                    }
                    $maps3 = array_values($maps3);
                    shuffle($maps3);
                    $map = $maps3[0];
                 }
                 $maps[] = $map;
              }
          }


        }else{
          // 没旋转的
          if(count($finalMaps)< $ganraoNum){
            $randNum +=$ganraoNum -count($finalMaps);
            $maps = $finalMaps;
          }else{
            $maps = Arr::random($finalMaps,$ganraoNum);
          }
        }
      }

      // 先把至少2个弄进去
      foreach ($maps as $map) {
          $result[] = $map;
          $result[] = $map;
      }
      // 实际测试过程中发现最终生成的数量不对,在重新 调整下
      if(count($result) + $randNum !== $interferenceCount){
        $randNum = $interferenceCount - count($result);
      }
      // 再把随机的弄进去
      for ($i = $randNum; $i > 0; $i--) {
          $rand = rand(0, count($maps) - 1);
          $result[] = $maps[$rand];
      }
      return $result;

    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值