利用PHP实现开心消消乐的算法示例
发布:smiling 来源: PHP粉丝网 添加日期:2018-09-09 14:38:50 浏览: 评论:0
本文主要介绍了关于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;
- }//phpfensi.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
Tags: 示例 算法
相关文章
- ·PHP中的cURL请求及示例学习笔记(2014-07-03)
- ·php计划任务示例详解(2014-07-12)
- ·php XMLWriter类的简单示例(2014-08-20)
- ·PHP编程实现的TCP服务端和客户端功能示例(2018-06-06)
- ·使用PHP访问RabbitMQ消息队列的方法示例(2018-06-11)
- ·php PDO实现的事务回滚示例(2018-08-29)
- ·Python实现文件内容批量追加的方法示例(2018-08-31)
- ·PHP memcache在微信公众平台的应用方法示例(2018-09-13)
- ·PHP服务器端API原理及示例讲解(接口开发)(2018-09-14)
- ·PHP使用pdo实现事务处理操作示例(2018-09-14)
- ·php apidoc生成接口文档示例(2018-09-19)
- ·PHP实现多个关键词搜索查询功能示例(2018-10-11)
- ·Laravel框架路由设置与使用示例(2018-10-19)
- ·PHP简单实现定时监控nginx日志文件功能示例(2018-10-19)
- ·PHP设计模式之装饰器模式定义与用法简单示例(2018-10-19)
- ·php实现memcache缓存示例讲解(2020-07-13)
推荐文章
热门文章
最新评论文章
- 写给考虑创业的年轻程序员(10)
- PHP新手上路(一)(7)
- 惹恼程序员的十件事(5)
- PHP邮件发送例子,已测试成功(5)
- 致初学者:PHP比ASP优秀的七个理由(4)
- PHP会被淘汰吗?(4)
- PHP新手上路(四)(4)
- 如何去学习PHP?(2)
- 简单入门级php分页代码(2)
- php中邮箱email 电话等格式的验证(2)