一个算法示例:PHP实现开心消消乐

本文主要介绍了关于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(empty($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(empty($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(empty($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;
  }
  $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

关于一个算法示例:PHP实现开心消消乐的文章就分享到这,如果对你有帮助欢迎继续关注我们哦

本文来自投稿,不代表重蔚自留地立场,如若转载,请注明出处https://www.cwhello.com/41784.html

如有侵犯您的合法权益请发邮件951076433@qq.com联系删除

(0)
php学习php学习订阅用户
上一篇 2022年6月23日 16:30
下一篇 2022年6月23日 16:30

相关推荐

  • PHP8函数:fdiv()的精度计算技巧。

    PHP8是目前最新的PHP语言版本,它引入了许多令人兴奋的新功能和改进。其中之一就是fdiv()函数,它可以用于准确地计算浮点数的除法运算。在以前的PHP版本中,使用基本的除法运算符(/)可能会导致精度问题。这是因为…

    2023年5月21日
    01
  • PHP8中的新函数:array_key_last()的实用技巧。

    PHP是世界上最受欢迎的编程语言之一,它的实用性和易用性让它成为了许多程序员的首选。在最新发布的PHP8中,引入了一些新的函数和特性,其中一个特别值得关注的新函数是array_key_last()。这个函数的实用技巧在本文…

    2023年5月21日
    02
  • PHP中使用Redis实现限时任务处理。

    随着互联网和移动互联网的发展,越来越多的应用需要进行后台任务处理。这些任务可能包括发送电子邮件、统计数据、生成报告等。在PHP中,通常使用CRON定时任务或者队列任务来实现后台任务处理。但是,在某些情况下,…

    2023年5月21日
    03
  • PHP入门指南:SQL注入。

    PHP入门指南:SQL注入随着互联网的快速发展,Web应用程序越来越普及,其安全性也成为了人们极为关注的问题。SQL注入是 Web应用程序中的一种常见攻击方式,它可以导致严重的安全问题,从而对 Web应用程序的正常运行…

    2023年5月22日
    01
  • 详解php命令行写shell实例

    php 可以像java perl python 那样运行,今天发现如果我早早知道这个,或许我不会去学习java 和 python当年学java不过为了一个程序放在服务器上,不停的跑啊跑,原来 php 也可以。php -h Usage: php [options] [-f] …

    2022年6月18日
    0169
  • PHP入门指南:ReactPHP编程框架。

    随着互联网技术的日益发展,Web应用程序已经渐渐成为了我们日常生活和工作中离不开的一部分。而PHP作为一个广泛应用于Web开发的语言,也在不断地发展和改进。本文将为你介绍一种基于PHP的编程框架——ReactPHP,帮助…

    2023年5月22日
    014
  • PHP自学get和post数据同时提交的情形

    一般就只有一种html语法形式会出现该情形,如下: <form  action="abc.php?a=5&b=10"  method="POST" > ... 项目1: <input type=”text”   name=”uName”   /> 项目2: <input type=”password”  …

    2017年11月7日
    0444
  • 直击PHP进程管理器php-fpm

    php-fpm是什么php-fpm是PHP的一个进程管理器。php下面的众多work进程皆有php-fpm进程管理器管理。php-fpm的工作原理php-fpm全名是PHP FastCGI进程管理器。php-fpm启动后会先读php.ini,然后再读相应的conf配置文件…

    2022年6月13日 PHP自学教程
    0128

联系我们

QQ:951076433

在线咨询:点击这里给我发消息邮件:951076433@qq.com工作时间:周一至周五,9:30-18:30,节假日休息