利用PHP實(shí)現(xiàn)開心消消樂的算法示例
前言
本文主要介紹了關(guān)于PHP如何實(shí)現(xiàn)我們大家都知道的開心消消樂的算法,分享出來供大家參考學(xué)習(xí),下面話不多說了,來一起看看詳細(xì)的介紹吧。
一、需求描述:
1、在一個(gè)8*8的矩陣方格中隨機(jī)出現(xiàn)5種顏色的色塊。
2、當(dāng)有三個(gè)或以上色塊在橫向或縱向上相連,則消除這些色塊。
3、色塊消除后,上方色塊往下平移,并掉下顏色隨機(jī)的色塊填充矩陣空缺。
4、重復(fù)2、3步驟。
5、消除3個(gè)相同色塊加10分,4個(gè)加15分,5個(gè)加20分,6個(gè)加30分,7個(gè)加40分,8個(gè)加70分,9個(gè)加100分,10個(gè)加150分,再往后每增加一個(gè)就比上一個(gè)多加50分。
二、上代碼
<?php
//所有圖形初始化數(shù)據(jù),key代表位置,value代表顏色
$xxl = array(
array('', '', '', '', '', '', '', ''),
array('', '', '', '', '', '', '', ''),
array('', '', '', '', '', '', '', ''),
array('', '', '', '', '', '', '', ''),
array('', '', '', '', '', '', '', ''),
array('', '', '', '', '', '', '', ''),
array('', '', '', '', '', '', '', ''),
array('', '', '', '', '', '', '', ''),
);
$point = play($xxl, $point);//開始游戲
echo "\n共獲得積分?jǐn)?shù)量:{$point}";
/*開始消除
*$xxl array 所有圖形集合
*$point int 獲得積分?jǐn)?shù)量
*/
$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;//組指針
//隨機(jī)填充顏色,并獲得行上相連色塊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);//隨機(jī)填充顏色
}
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]){//同一列上和前一個(gè)顏色不一樣
$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]){//同一行上和前一個(gè)顏色不一樣
$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
}
//隨機(jī)填充顏色,并獲得行上相連色塊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'])){//判斷本點(diǎn)是否已出現(xiàn)在橫向組里
$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);//計(jì)算本次消除獲得積分
$point += $thisPoint;//累計(jì)到總積分
//消除相連色塊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);//打印消除時(shí)的圖形
$next = step($next);
show($next);//打印消除后的圖形
echo "本次消除獲得積分?jǐn)?shù)量:{$thisPoint}\n";
return play($next, $point);
}
/*計(jì)算獲得積分?jǐn)?shù)量
*$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;
}
/*找相鄰點(diǎn)
*$xxl array 相連圖形集合
*$one array 某一個(gè)點(diǎn)
*$arr array 圖形集合里的相鄰的點(diǎn)
*/
function seek($xxl, $one, &$arr){
// global $i;
$near = array();
$near['up'] = ($one[0] - 1).'-'.$one[1];//上面的點(diǎn)
$near['down'] = ($one[0] + 1).'-'.$one[1];//下面的點(diǎn)
$near['left'] = $one[0].'-'.($one[1] - 1);//左面的點(diǎn)
$near['right'] = $one[0].'-'.($one[1] + 1);//右面的點(diǎn)
foreach($near as $v){
if(isset($xxl[$v]) && $xxl[$v][2] == $one[2]){//找到相鄰點(diǎn)
$xj = array_intersect($one['group'], $xxl[$v]['group']);
if(empty($xj)){//如果相鄰的點(diǎn)不是本組的就跳過
continue;
}
if(isset($arr[$v])){//如果該點(diǎn)已被遍歷過則跳過
continue;
}
$arr[$v] = $xxl[$v];
seek($xxl, $xxl[$v], $arr);//繼續(xù)找相鄰的點(diǎn)
}
}
}
/*打印圖形
*$xxl array 所有圖形集合
*/
function show($xxl){
//順時(shí)針旋轉(zhuǎn)矩陣start
$arr = array();
foreach($xxl as $k => $v){
foreach($v as $k2 => $v2){
$arr[7-$k2][$k] = $v2;
}
}
ksort($arr);
//順時(shí)針旋轉(zhuǎn)矩陣end
$str = '';
foreach($arr as $v){
foreach($v as $v2){
$str .= ' '.$v2;
}
$str .= "\n";
}
echo "\n".$str;
}
運(yùn)行結(jié)果如下:
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 本次消除獲得積分?jǐn)?shù)量: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 本次消除獲得積分?jǐn)?shù)量: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 =================================消除完畢!================================== 共獲得積分?jǐn)?shù)量:75
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- PHP機(jī)器學(xué)習(xí)庫(kù)php-ml的簡(jiǎn)單測(cè)試和使用方法
- PHP實(shí)現(xiàn)圖的鄰接矩陣表示及幾種簡(jiǎn)單遍歷算法分析
- PHP對(duì)稱加密算法(DES/AES)類的實(shí)現(xiàn)代碼
- PHP基于回溯算法解決n皇后問題的方法示例
- php實(shí)現(xiàn)的生成迷宮與迷宮尋址算法完整實(shí)例
- PHP實(shí)現(xiàn)的貪婪算法實(shí)例
- PHP實(shí)現(xiàn)的迪科斯徹(Dijkstra)最短路徑算法實(shí)例
- PHP使用棧解決約瑟夫環(huán)問題算法示例
- PHP基于遞歸實(shí)現(xiàn)的約瑟夫環(huán)算法示例
- PHP實(shí)現(xiàn)機(jī)器學(xué)習(xí)之樸素貝葉斯算法詳解
相關(guān)文章
PHP實(shí)現(xiàn)將base64編碼字符串轉(zhuǎn)換成圖片示例
這篇文章主要介紹了PHP實(shí)現(xiàn)將base64編碼字符串轉(zhuǎn)換成圖片,涉及php編碼轉(zhuǎn)換、文件讀寫等簡(jiǎn)單處理技巧,需要的朋友可以參考下2018-06-06
一個(gè)PHP數(shù)組應(yīng)該有多大的分析
PHP在數(shù)組處理上非常低效,尤其是內(nèi)存占用較多,常常使得httpd進(jìn)程消耗太多資源。2009-07-07
解析php中static,const與define的使用區(qū)別
本篇文章是對(duì)php中static,const與define的使用區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06
PHP中usort在值相同時(shí)改變?cè)嘉恢脝栴}的解決方法
從 PHP 4.1.0 后,usort 在比較的值相同時(shí),原始位置可能會(huì)改變,如果比較的2個(gè)值相同,則它們?cè)谂判蚪Y(jié)果中的順序是隨機(jī)的。如果你需要保持相同值的原始位置,可以參考本文的方法。2011-11-11

