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


Posted in PHP onOctober 12, 2017

前言

本文主要介绍了关于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 相关文章推荐
require(),include(),require_once()和include_once()区别
Mar 27 PHP
屏蔽机器人从你的网站搜取email地址的php代码
Nov 14 PHP
PHP CodeBase:将时间显示为&quot;刚刚&quot;&quot;n分钟/小时前&quot;的方法详解
Jun 06 PHP
处理(php-cgi.exe - FastCGI 进程超过了配置的请求超时时限)的问题
Jul 03 PHP
PHP imagegrabscreen和imagegrabwindow(截取网站缩略图)的实例代码
Nov 07 PHP
PHP 登录完成后如何跳转上一访问页面
Jan 14 PHP
微信公众平台天气预报功能开发
Jul 06 PHP
PHP制作万年历
Jan 07 PHP
php仿微信红包分配算法的实现方法
May 13 PHP
PHP Yaf框架的简单安装使用教程(推荐)
Jun 08 PHP
Thinkphp3.2.3整合phpqrcode生成带logo的二维码
Jul 21 PHP
Laravel5.5+ 使用API Resources快速输出自定义JSON方法详解
Apr 06 PHP
深入理解PHP中mt_rand()随机数的安全
Oct 12 #PHP
php表单习惯用的正则表达式
Oct 11 #PHP
彻底搞懂PHP 变量结构体
Oct 11 #PHP
利用php + Laravel如何实现部署自动化详解
Oct 11 #PHP
Laravel 5使用Laravel Excel实现Excel/CSV文件导入导出的功能详解
Oct 11 #PHP
laravel migrate初学常见错误的解决方法
Oct 11 #PHP
Laravel学习基础之migrate的使用教程
Oct 11 #PHP
You might like
模拟flock实现文件锁定
2007/02/14 PHP
php 404错误页面实现代码
2009/06/22 PHP
在PHP中利用wsdl创建标准webservice的实现代码
2011/12/07 PHP
PHP中图片等比缩放的实例
2013/03/24 PHP
Thinkphp搜索时首页分页和搜索页保持条件分页的方法
2014/12/05 PHP
基于Jquery的表格隔行换色,移动换色,点击换色插件
2010/12/22 Javascript
js onload事件不起作用示例分析
2013/10/09 Javascript
jquery表单验证框架提供的身份证验证方法(示例代码)
2013/12/27 Javascript
JS延迟加载加快页面打开速度示例代码
2013/12/30 Javascript
jQuery实现弹出窗口中切换登录与注册表单
2015/06/05 Javascript
jQuery获取cookie值及删除cookie用法实例
2016/04/15 Javascript
原生JS实现图片懒加载(lazyload)实例
2017/06/13 Javascript
基于Vue单文件组件详解
2017/09/15 Javascript
微信小程序实现搜索功能
2020/03/10 Javascript
vue中v-for循环选中点击的元素并对该元素添加样式操作
2020/07/17 Javascript
vue抽出组件并传值实例
2020/07/31 Javascript
Ant Design Vue table中列超长显示...并加提示语的实例
2020/10/31 Javascript
[01:53]DOTA2超级联赛专访Zhou 五年职业青春成长
2013/05/29 DOTA
[02:25]DOTA2英雄基础教程 生死判决瘟疫法师
2013/12/06 DOTA
[48:45]Ti4 循环赛第二日 NEWBEE vs EG
2014/07/11 DOTA
[00:52]玛尔斯技能全介绍
2019/03/06 DOTA
python 的列表遍历删除实现代码
2020/04/12 Python
浅谈插入排序算法在Python程序中的实现及简单改进
2016/05/04 Python
Python实现基本数据结构中栈的操作示例
2017/12/04 Python
python3+PyQt5实现自定义流体混合窗口部件
2018/04/24 Python
使用python+whoosh实现全文检索
2019/12/09 Python
使用tensorflow显示pb模型的所有网络结点方式
2020/01/23 Python
python用TensorFlow做图像识别的实现
2020/04/21 Python
Python的历史与优缺点整理
2020/05/26 Python
python 制作python包,封装成可用模块教程
2020/07/13 Python
多个版本的python共存时使用pip的正确做法
2020/10/26 Python
Python日志打印里logging.getLogger源码分析详解
2021/01/17 Python
反洗钱宣传活动总结
2014/08/26 职场文书
幼儿园六一活动总结
2014/08/27 职场文书
python垃圾回收机制原理分析
2022/04/13 Python
mysql函数之截取字符串的实现
2022/08/14 MySQL