消消乐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分。

二、上代码

//所有图形初始化数据,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(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);

}

/*计算获得积分数量

*$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(empty($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;

}

$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

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值