天天看點

消消樂php源碼,PHP實作開心消消樂的算法示例分享

開心消消樂應該對大家來說都不陌生吧,本文主要給大家介紹關于如何利用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分。

二、上代碼<?php

//所有圖形初始化資料,key代表位置,value代表顔色

$xxl = array(

array('', '', '', '', '', '', '', ''),

array('', '', '', '', '', '', '', ''),

array('', '', '', '', '', '', '', ''),

array('', '', '', '', '', '', '', ''),

array('', '', '', '', '', '', '', ''),

array('', '', '', '', '', '', '', ''),

array('', '', '', '', '', '', '', ''),

array('', '', '', '', '', '', '', ''),

);

$point = play($xxl, $point);//開始遊戲

echo "\n共獲得積分數量:{$point}";

$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);

}

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;

}

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;

}

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);//繼續找相鄰的點

}

}

}

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

相關推薦: