本文主要介紹了關於PHP如何實現我們大家都知道的開心消消樂的演算法,分享PHP教程出來供大家參考學習,下麵話不多說了,來一起看看詳細的介紹吧。 一、需求描述: 1、在一個8*8的矩陣方格中隨機出現5種顏色的色塊。 2、當有三個或以上色塊在橫向或縱向上相連,則消除這些色塊。 3、色塊消除後,上方色塊往下 ...
本文主要介紹了關於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 "\n共獲得積分數量:{$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}\n"; 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 .= "\n"; 217 } 218 echo "\n".$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