加入收藏 | 设为首页 | 会员中心 | 我要投稿 威海站长网 (https://www.0631zz.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

运用PHP实现开心消消乐的算法示例

发布时间:2022-02-23 21:33:45 所属栏目:PHP教程 来源:互联网
导读:本文主要介绍了关于PHP如何实现我们大家都知道的开心消消乐的算法,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。 一、需求描述: 1、在一个8*8的矩阵方格中随机出现5种颜色的色块。 2、当有三个或以上色块在横向或纵向上相连,则消除
  本文主要介绍了关于PHP如何实现我们大家都知道的开心消消乐的算法,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。
 
  一、需求描述:
 
  1、在一个8*8的矩阵方格中随机出现5种颜色的色块。
 
  2、当有三个或以上色块在横向或纵向上相连,则消除这些色块。
 
  3、色块消除后,上方色块往下平移,并掉下颜色随机的色块填充矩阵空缺。
 
  4、重复2、3步骤。
 
  5、消除3个相同色块加10分,4个加15分,5个加20分,6个加30分,7个加40分,8个加70分,9个加100分,10个加150分,再往后每增加一个就比上一个多加50分。
 
  二、上代码:
 
  <?php
  //所有图形初始化数据,key代表位置,value代表颜色
  $xxl = array(
   array('', '', '', '', '', '', '', ''),
   array('', '', '', '', '', '', '', ''),
   array('', '', '', '', '', '', '', ''),
   array('', '', '', '', '', '', '', ''),
   array('', '', '', '', '', '', '', ''),
   array('', '', '', '', '', '', '', ''),
   array('', '', '', '', '', '', '', ''),
   array('', '', '', '', '', '', '', ''),
  );
  $point = play($xxl, $point);//开始游戏
  echo "/n共获得积分数量:{$point}";
    
  /*开始消除
   *$xxl  array 所有图形集合
   *$point int  获得积分数量
  */
  $bu = 0;
  function play($xxl, $point){
   global $bu;
   $bu ++;
   echo '=================================开始第'.$bu.'步==================================';
   $color = array(1 => 'red',2 => 'green',3 => 'yellow',4 => 'blue',5 => 'black');//代表5种颜色
   $samCol = array();//列上相连色块集合
   $nowCol = array();//列上相连色块指针
   $samArr = array();//相连色块总集合
   $group = 1;//组指针
    
   //随机填充颜色,并获得行上相连色块start
   foreach($xxl as $k1 => $v1){
    $sam = array();//行上相连色块集合
    $now = 1;//行上相连色块指针
    foreach($v1 as $k2 => $v2){
     if(emptyempty($v2) || $v2 == ' '){
      $v2 = $xxl[$k1][$k2] = array_rand($color);//随机填充颜色
     }
     if(!isset($nowCol[$k2])){
      $nowCol[$k2] = 1;
     }
     if($k1 === 0){
      $samCol[$k2][$nowCol[$k2]][$k1 .'-'. $k2] = array($k1, $k2, $v2, $k1 .'-'. $k2 .'-'. $v2);
     }else{
      if($v2 != $xxl[$k1-1][$k2]){//同一列上和前一个颜色不一样
       $nowCol[$k2] ++;
      }
      $samCol[$k2][$nowCol[$k2]][$k1 .'-'. $k2] = array($k1, $k2, $v2, $k1 .'-'. $k2 .'-'. $v2);
     }
    
    
     if($k2 === 0){
      $sam[$now][$k1 .'-'. $k2] = array($k1, $k2, $v2, $k1 .'-'. $k2 .'-'. $v2);
     }else{
      if($v2 != $xxl[$k1][$k2-1]){//同一行上和前一个颜色不一样
       $now++;
      }
      $sam[$now][$k1 .'-'. $k2] = array($k1, $k2, $v2, $k1 .'-'. $k2 .'-'. $v2);
     }
    }
    //获得行上相连色块start
    foreach($sam as $x => $y){
     if(count($y) > 2){
      $key = 'R-'.$group;
      foreach($y as $x2 => $y2){
       $y[$x2]['group']['r'] = $key;
      }
      $samArr += $y;
      $group ++;
     }
    }
    //获得行上相连色块end
   }
   //随机填充颜色,并获得行上相连色块end
    
   //获得列上相连色块start
   $group = 1;
   foreach($samCol as $k => $v){
    foreach($v as $x => $y){
     if(count($y) > 2){
      $key = 'L-'.$group;
      foreach($y as $x2 => $y2){
       $y[$x2]['group']['l'] = $key;
       if(isset($samArr[$x2]['group']['r'])){//判断本点是否已出现在横向组里
        $samArr[$x2]['group']['l'] = $key;
       }
      }
      $samArr += $y;
      $group ++;
     }
    }
   }
   //获得列上相连色块end
    
   //查找相连色块start
   $res = array();//相连色块集合
   $hasRes = array();
   foreach($samArr as $k => $v){
    if(isset($hasRes[$k])){
     continue;
    }
    $arr = array();
    seek($samArr, $v, $arr);
    $res[] = array_keys($arr);
    $hasRes += $arr;
   }
   //查找相连色块end
   show($xxl);//打印消除前的图形
   if(emptyempty($res)){//如果没有相连色块则退出递归
    echo '=================================消除完毕!==================================';
    return $point;
   }
   $thisPoint = countPoint($res);//计算本次消除获得积分
   $point += $thisPoint;//累计到总积分
    
   //消除相连色块start
   $next = $xxl;
   foreach($res as $k => $v){
    foreach($v as $k2 => $v2){
     $y = $samArr[$v2][0];
     $x = $samArr[$v2][1];
     $xxl[$y][$x] = '*';
     unset($next[$y][$x]);
    }
   }
   //消除相连色块end
    
   show($xxl);//打印消除时的图形
   $next = step($next);
   show($next);//打印消除后的图形
   echo "本次消除获得积分数量:{$thisPoint}/n";
   return play($next, $point);
  }
    
  /*计算获得积分数量
   *$xxl  array 相连色块集合
   */
  function countPoint($xxl){
   //初始化积分配置start
   $config = array(3 => 10, 4 => 15, 5 => 20, 6 => 30, 7 => 40, 8 => 70, 9 => 100);
   for($i = 10; $i <= 64; $i++){
    $config[$i] = 100 + ($i - 9) * 50;
   }
   //初始化积分配置end
   $point = 0;
   foreach($xxl as $v){
    $key = count($v);
    $point += $config[$key];
   }
   return $point;
  }
    
  /*消掉并左移
   *$xxl  array 所有图形集合
   */
  function step($xxl){
   foreach($xxl as $k => $v){
    $temp = array_merge($v);
    $count = count($temp);
    if($count == 8){
     continue;
    }
    for($i = $count; $i <= 7; $i++){
     $temp[$i] = ' ';
    }
    $xxl[$k] = $temp;
   }
   return $xxl;
  }
    
  /*找相邻点
   *$xxl  array 相连图形集合
   *$one   array 某一个点
   *$arr   array 图形集合里的相邻的点
  */
  function seek($xxl, $one, &$arr){
  // global $i;
   $near = array();
   $near['up'] = ($one[0] - 1).'-'.$one[1];//上面的点
   $near['down'] = ($one[0] + 1).'-'.$one[1];//下面的点
   $near['left'] = $one[0].'-'.($one[1] - 1);//左面的点
   $near['right'] = $one[0].'-'.($one[1] + 1);//右面的点
   foreach($near as $v){
    if(isset($xxl[$v]) && $xxl[$v][2] == $one[2]){//找到相邻点
     $xj = array_intersect($one['group'], $xxl[$v]['group']);
     if(emptyempty($xj)){//如果相邻的点不是本组的就跳过
      continue;
     }
     if(isset($arr[$v])){//如果该点已被遍历过则跳过
      continue;
     }
     $arr[$v] = $xxl[$v];
     seek($xxl, $xxl[$v], $arr);//继续找相邻的点
    }
   }
  }
    
  /*打印图形
   *$xxl  array 所有图形集合
   */
  function show($xxl){
   //顺时针旋转矩阵start
   $arr = array();
   foreach($xxl as $k => $v){
    foreach($v as $k2 => $v2){
     $arr[7-$k2][$k] = $v2;
    }
   }
   ksort($arr);
   //顺时针旋转矩阵end
   $str = '';
   foreach($arr as $v){
    foreach($v as $v2){
     $str .= ' '.$v2;
    }//Cuoxin.com
    $str .= "/n";
   }
   echo "/n".$str;
  }
  运行结果如下:
 
  12345分别代表5种颜色。
 
  =================================开始第1步==================================
   3 3 2 2 1 1 1 4
   4 3 4 3 4 1 1 3
   3 1 4 1 1 4 1 2
   2 3 4 3 1 2 4 4
   4 2 4 2 2 2 1 4
   3 3 2 1 2 3 1 1
   5 2 1 3 2 1 4 5
   3 4 5 1 3 2 3 3
    
   3 3 2 2 * * * 4
   4 3 * 3 4 1 * 3
   3 1 * 1 1 4 * 2
   2 3 * 3 1 2 4 4
   4 2 * * * * 1 4
   3 3 2 1 * 3 1 1
   5 2 1 3 * 1 4 5
   3 4 5 1 3 2 3 3
    
   3 3   4
   4 3 2  3
   3 1 3 1 2
   2 3 1 4 4 4
   4 2 2 3 4 2 1 4
   3 3 2 1 1 3 1 1
   5 2 1 3 1 1 4 5
   3 4 5 1 3 2 3 3
  本次消除获得积分数量:55
  =================================开始第2步==================================
   3 3 2 2 3 3 2 4
   4 3 3 2 1 3 3 3
   3 1 3 3 4 1 4 2
   2 3 5 1 2 4 4 4
   4 2 2 3 4 2 1 4
   3 3 2 1 1 3 1 1
   5 2 1 3 1 1 4 5
   3 4 5 1 3 2 3 3
    
   3 3 2 2 3 3 2 4
   4 3 3 2 1 * * *
   3 1 3 3 4 1 4 2
   2 3 5 1 2 * * *
   4 2 2 3 4 2 1 4
   3 3 2 1 1 3 1 1
   5 2 1 3 1 1 4 5
   3 4 5 1 3 2 3 3
    
   3 3 2 2 3   
   4 3 3 2 1   
   3 1 3 3 4 3 2 4
   2 3 5 1 2 1 4 2
   4 2 2 3 4 2 1 4
   3 3 2 1 1 3 1 1
   5 2 1 3 1 1 4 5
   3 4 5 1 3 2 3 3
  本次消除获得积分数量:20
  =================================开始第3步==================================
   3 3 2 2 3 4 1 3
   4 3 3 2 1 4 2 5
   3 1 3 3 4 3 2 4
   2 3 5 1 2 1 4 2
   4 2 2 3 4 2 1 4
   3 3 2 1 1 3 1 1
   5 2 1 3 1 1 4 5
   3 4 5 1 3 2 3 3
  =================================消除完毕!==================================
  共获得积分数量:75 

(编辑:威海站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读