本文主要介绍了关于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分。
二、上代码
1 <?php 2 //所有图形初始化数据,key代表位置,value代表颜色 3 $xxl = array( 4 array('', '', '', '', '', '', '', ''), 5 array('', '', '', '', '', '', '', ''), 6 array('', '', '', '', '', '', '', ''), 7 array('', '', '', '', '', '', '', ''), 8 array('', '', '', '', '', '', '', ''), 9 array('', '', '', '', '', '', '', ''), 10 array('', '', '', '', '', '', '', ''), 11 array('', '', '', '', '', '', '', ''), 12 ); 13 $point = play($xxl, $point);//开始游戏 14 echo " 共获得积分数量:{$point}"; 15 16 /*开始消除 17 *$xxl array 所有图形集合 18 *$point int 获得积分数量 19 */ 20 $bu = 0; 21 function play($xxl, $point){ 22 global $bu; 23 $bu ++; 24 echo '=================================开始第'.$bu.'步=================================='; 25 $color = array(1 => 'red',2 => 'green',3 => 'yellow',4 => 'blue',5 => 'black');//代表5种颜色 26 $samCol = array();//列上相连色块集合 27 $nowCol = array();//列上相连色块指针 28 $samArr = array();//相连色块总集合 29 $group = 1;//组指针 30 31 //随机填充颜色,并获得行上相连色块start 32 foreach($xxl as $k1 => $v1){ 33 $sam = array();//行上相连色块集合 34 $now = 1;//行上相连色块指针 35 foreach($v1 as $k2 => $v2){ 36 if(empty($v2) || $v2 == ' '){ 37 $v2 = $xxl[$k1][$k2] = array_rand($color);//随机填充颜色 38 } 39 if(!isset($nowCol[$k2])){ 40 $nowCol[$k2] = 1; 41 } 42 if($k1 === 0){ 43 $samCol[$k2][$nowCol[$k2]][$k1 .'-'. $k2] = array($k1, $k2, $v2, $k1 .'-'. $k2 .'-'. $v2); 44 }else{ 45 if($v2 != $xxl[$k1-1][$k2]){//同一列上和前一个颜色不一样 46 $nowCol[$k2] ++; 47 } 48 $samCol[$k2][$nowCol[$k2]][$k1 .'-'. $k2] = array($k1, $k2, $v2, $k1 .'-'. $k2 .'-'. $v2); 49 } 50 51 52 if($k2 === 0){ 53 $sam[$now][$k1 .'-'. $k2] = array($k1, $k2, $v2, $k1 .'-'. $k2 .'-'. $v2); 54 }else{ 55 if($v2 != $xxl[$k1][$k2-1]){//同一行上和前一个颜色不一样 56 $now++; 57 } 58 $sam[$now][$k1 .'-'. $k2] = array($k1, $k2, $v2, $k1 .'-'. $k2 .'-'. $v2); 59 } 60 } 61 //获得行上相连色块start 62 foreach($sam as $x => $y){ 63 if(count($y) > 2){ 64 $key = 'R-'.$group; 65 foreach($y as $x2 => $y2){ 66 $y[$x2]['group']['r'] = $key; 67 } 68 $samArr += $y; 69 $group ++; 70 } 71 } 72 //获得行上相连色块end 73 } 74 //随机填充颜色,并获得行上相连色块end 75 76 //获得列上相连色块start 77 $group = 1; 78 foreach($samCol as $k => $v){ 79 foreach($v as $x => $y){ 80 if(count($y) > 2){ 81 $key = 'L-'.$group; 82 foreach($y as $x2 => $y2){ 83 $y[$x2]['group']['l'] = $key; 84 if(isset($samArr[$x2]['group']['r'])){//判断本点是否已出现在横向组里 85 $samArr[$x2]['group']['l'] = $key; 86 } 87 } 88 $samArr += $y; 89 $group ++; 90 } 91 } 92 } 93 //获得列上相连色块end 94 95 //查找相连色块start 96 $res = array();//相连色块集合 97 $hasRes = array(); 98 foreach($samArr as $k => $v){ 99 if(isset($hasRes[$k])){ 100 continue; 101 } 102 $arr = array(); 103 seek($samArr, $v, $arr); 104 $res[] = array_keys($arr); 105 $hasRes += $arr; 106 } 107 //查找相连色块end 108 show($xxl);//打印消除前的图形 109 if(empty($res)){//如果没有相连色块则退出递归 110 echo '=================================消除完毕!=================================='; 111 return $point; 112 } 113 $thisPoint = countPoint($res);//计算本次消除获得积分 114 $point += $thisPoint;//累计到总积分 115 116 //消除相连色块start 117 $next = $xxl; 118 foreach($res as $k => $v){ 119 foreach($v as $k2 => $v2){ 120 $y = $samArr[$v2][0]; 121 $x = $samArr[$v2][1]; 122 $xxl[$y][$x] = '*'; 123 unset($next[$y][$x]); 124 } 125 } 126 //消除相连色块end 127 128 show($xxl);//打印消除时的图形 129 $next = step($next); 130 show($next);//打印消除后的图形 131 echo "本次消除获得积分数量:{$thisPoint} "; 132 return play($next, $point); 133 } 134 135 /*计算获得积分数量 136 *$xxl array 相连色块集合 137 */ 138 function countPoint($xxl){ 139 //初始化积分配置start 140 $config = array(3 => 10, 4 => 15, 5 => 20, 6 => 30, 7 => 40, 8 => 70, 9 => 100); 141 for($i = 10; $i <= 64; $i++){ 142 $config[$i] = 100 + ($i - 9) * 50; 143 } 144 //初始化积分配置end 145 $point = 0; 146 foreach($xxl as $v){ 147 $key = count($v); 148 $point += $config[$key]; 149 } 150 return $point; 151 } 152 153 /*消掉并左移 154 *$xxl array 所有图形集合 155 */ 156 function step($xxl){ 157 foreach($xxl as $k => $v){ 158 $temp = array_merge($v); 159 $count = count($temp); 160 if($count == 8){ 161 continue; 162 } 163 for($i = $count; $i <= 7; $i++){ 164 $temp[$i] = ' '; 165 } 166 $xxl[$k] = $temp; 167 } 168 return $xxl; 169 } 170 171 /*找相邻点 172 *$xxl array 相连图形集合 173 *$one array 某一个点 174 *$arr array 图形集合里的相邻的点 175 */ 176 function seek($xxl, $one, &$arr){ 177 // global $i; 178 $near = array(); 179 $near['up'] = ($one[0] - 1).'-'.$one[1];//上面的点 180 $near['down'] = ($one[0] + 1).'-'.$one[1];//下面的点 181 $near['left'] = $one[0].'-'.($one[1] - 1);//左面的点 182 $near['right'] = $one[0].'-'.($one[1] + 1);//右面的点 183 foreach($near as $v){ 184 if(isset($xxl[$v]) && $xxl[$v][2] == $one[2]){//找到相邻点 185 $xj = array_intersect($one['group'], $xxl[$v]['group']); 186 if(empty($xj)){//如果相邻的点不是本组的就跳过 187 continue; 188 } 189 if(isset($arr[$v])){//如果该点已被遍历过则跳过 190 continue; 191 } 192 $arr[$v] = $xxl[$v]; 193 seek($xxl, $xxl[$v], $arr);//继续找相邻的点 194 } 195 } 196 } 197 198 /*打印图形 199 *$xxl array 所有图形集合 200 */ 201 function show($xxl){ 202 //顺时针旋转矩阵start 203 $arr = array(); 204 foreach($xxl as $k => $v){ 205 foreach($v as $k2 => $v2){ 206 $arr[7-$k2][$k] = $v2; 207 } 208 } 209 ksort($arr); 210 //顺时针旋转矩阵end 211 $str = ''; 212 foreach($arr as $v){ 213 foreach($v as $v2){ 214 $str .= ' '.$v2; 215 } 216 $str .= " "; 217 } 218 echo " ".$str; 219 }
运行结果如下:
12345分别代表5种颜色。
1 =================================开始第1步================================== 2 3 3 2 2 1 1 1 4 3 4 3 4 3 4 1 1 3 4 3 1 4 1 1 4 1 2 5 2 3 4 3 1 2 4 4 6 4 2 4 2 2 2 1 4 7 3 3 2 1 2 3 1 1 8 5 2 1 3 2 1 4 5 9 3 4 5 1 3 2 3 3 10 11 3 3 2 2 * * * 4 12 4 3 * 3 4 1 * 3 13 3 1 * 1 1 4 * 2 14 2 3 * 3 1 2 4 4 15 4 2 * * * * 1 4 16 3 3 2 1 * 3 1 1 17 5 2 1 3 * 1 4 5 18 3 4 5 1 3 2 3 3 19 20 3 3 4 21 4 3 2 3 22 3 1 3 1 2 23 2 3 1 4 4 4 24 4 2 2 3 4 2 1 4 25 3 3 2 1 1 3 1 1 26 5 2 1 3 1 1 4 5 27 3 4 5 1 3 2 3 3 28 本次消除获得积分数量:55 29 =================================开始第2步================================== 30 3 3 2 2 3 3 2 4 31 4 3 3 2 1 3 3 3 32 3 1 3 3 4 1 4 2 33 2 3 5 1 2 4 4 4 34 4 2 2 3 4 2 1 4 35 3 3 2 1 1 3 1 1 36 5 2 1 3 1 1 4 5 37 3 4 5 1 3 2 3 3 38 39 3 3 2 2 3 3 2 4 40 4 3 3 2 1 * * * 41 3 1 3 3 4 1 4 2 42 2 3 5 1 2 * * * 43 4 2 2 3 4 2 1 4 44 3 3 2 1 1 3 1 1 45 5 2 1 3 1 1 4 5 46 3 4 5 1 3 2 3 3 47 48 3 3 2 2 3 49 4 3 3 2 1 50 3 1 3 3 4 3 2 4 51 2 3 5 1 2 1 4 2 52 4 2 2 3 4 2 1 4 53 3 3 2 1 1 3 1 1 54 5 2 1 3 1 1 4 5 55 3 4 5 1 3 2 3 3 56 本次消除获得积分数量:20 57 =================================开始第3步================================== 58 3 3 2 2 3 4 1 3 59 4 3 3 2 1 4 2 5 60 3 1 3 3 4 3 2 4 61 2 3 5 1 2 1 4 2 62 4 2 2 3 4 2 1 4 63 3 3 2 1 1 3 1 1 64 5 2 1 3 1 1 4 5 65 3 4 5 1 3 2 3 3 66 =================================消除完毕!================================== 67 共获得积分数量:75