前言
本文主要介绍了关于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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
|
<?php
//所有图形初始化数据,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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
=================================开始第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
|
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。
原文链接:https://segmentfault.com/a/1190000011497924