Implementing a Match‑3 (Happy Elimination) Game Algorithm in PHP
This article explains the requirements, scoring rules, and complete PHP implementation of a classic 8×8 match‑3 (Happy Elimination) game, including random color generation, detection of horizontal and vertical groups, removal, gravity handling, and recursive scoring until no more matches remain.
The article introduces a PHP implementation of the popular "Happy Elimination" (match‑3) game, describing the game board, color blocks, elimination rules, and scoring system.
Requirement description: An 8×8 matrix is filled with five random colors; any three or more identical colors aligned horizontally or vertically are removed, points are awarded based on the number of blocks removed, and the board collapses with new random colors filling the gaps. The process repeats until no more matches exist.
Full source code:
<?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);
}
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){
$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;
}
?>The sample output shows three game steps, the board state before and after each elimination, and the points earned (55, 20, and a final total of 75). The algorithm recursively continues until no further matches are found, demonstrating a complete backend solution for a match‑3 puzzle game in PHP.
php中文网 Courses
php中文网's platform for the latest courses and technical articles, helping PHP learners advance quickly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.