首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PHP游戏-在蓝色和白色网格中更改单元格的颜色,=>更新相互接触的白细胞组。

PHP游戏-在蓝色和白色网格中更改单元格的颜色,=>更新相互接触的白细胞组。
EN

Code Review用户
提问于 2021-10-31 10:41:50
回答 1查看 74关注 0票数 0

我的游戏是一个网格,你必须通过点击它们来改变它们的颜色。当我生成一个网格时,我必须知道我的游戏允许的所有可能的蓝白色细胞组合,以了解网格的难度级别。

每次创建场景时,我都必须更新一个重要的参数,即一组相互接触的白细胞。

我在我的函数中使用了3个表:

第一个包含所有白细胞的位置。

代码语言:javascript
复制
// example for a 3,3 grid : 
[y0 => [x0 => x0, x1 => x1], y1 => [x0 => x0], y2 => [x1 => x1, x2 => x2]]

第二个包含相互接触的分组白血球的位置。

代码语言:javascript
复制
// same example
[ [[y0,x0],[y0,x1],[y1,x0]], [[y2,x1],[y2,x2]] ]

第三组是第二表中的一组。

代码语言:javascript
复制
// same example
[[y0,x0],[y0,x1],[y1,x0]]

我创建了几个函数:

这个表只需要第一个表,然后返回第二个表。在创建网格时,我使用它初始化参数。

代码语言:javascript
复制
function rec($p, $po, $t){
    // $p table containing white cases : [y0 => [x0 => x0, x1 => x1,..], y1 => [x0 => x0, x1 => x1],..]
    // $po position of the first case : [y,x]
    // $t table to record groups
    $u = [];
    if(isset($p[$po[0]][$po[1]+1]) && !in_array([$po[0],$po[1]+1], $t)){
        $u[] = [$po[0],$po[1]+1];
        $t = array_merge($t, [[$po[0],$po[1]+1]]);
    }
    if(isset($p[$po[0]][$po[1]-1]) && !in_array([$po[0],$po[1]-1], $t)){
        $u[] = [$po[0],$po[1]-1];
        $t = array_merge($t, [[$po[0],$po[1]-1]]);
    }
    if(isset($p[$po[0]-1][$po[1]]) && !in_array([$po[0]-1,$po[1]], $t)){
        $u[] = [$po[0]-1,$po[1]];
        $t = array_merge($t, [[$po[0]-1,$po[1]]]);
    }
    if(isset($p[$po[0]+1][$po[1]]) && !in_array([$po[0]+1,$po[1]], $t)){
        $u[] = [$po[0]+1,$po[1]];
        $t = array_merge($t, [[$po[0]+1,$po[1]]]);
    }
    if(count($u) > 0){
        foreach($u as $v){
            $t = rec($p, $v, $t);
        }
        return $t;
    }
    else{
        return $t;
    }
}

$p = [ // an example
    0 => [0 => 0, 2 => 2, 4 => 4],
    1 => [0 => 0, 4 => 4],
    2 => [0 => 0, 2 => 2, 4 => 4],
    3 => [0 => 0, 4 => 4],
    4 => [0 => 0, 1 => 1, 2 => 2, 3 => 3, 4 => 4]
];

$u = [[]];
$z = [];
$c = 0;
foreach($p as $a => $n){
    foreach($n as $b){
        //var_dump($u);
        if(!in_array([$a,$b], $z)){
            $o = [];
            $o = rec($p, [$a,$b], [[$a,$b]]);
            $u[$c++] = $o;
            $z = array_merge($z, $o);
        }
    }
}
var_dump($u);

您可以在这里测试它:jdoodle.com/ia/iTi

这个函数只需要第二个表,它更新了一组白细胞,我知道其中一个单元已经变成蓝色了。我不用它是因为它太慢了。

代码语言:javascript
复制
function updateGroup($group){
    // $gp is only one group a white cells : [[y1,x1],[y1,x2],[y2,x1],..]
    $groupTemp = $group;
    $allNewGroups = [];
    do{
        foreach($group as $x => $cellSearch){
            unset($group[$x]);
            unset($groupTemp[$x]);
            $cellSearchTab = [$cellSearch];
            $newGroup = [];
            $check = false;
            $index = 0;
            do{
                $cellTouchTab = [];
                foreach($cellSearchTab as $cell){
                    if($index == 0){
                        $newGroup[] = $cell;
                    }
                    foreach($groupTemp as $k => $cellTouch){
                        if((abs($cell[0]-$cellTouch[0]) == 1 && $p[1]-$cellTouch[1] == 0) || (abs($cell[1]-$cellTouch[1]) == 1 && $p[0]-$cellTouch[0] == 0)){
                            unset($groupTemp[$k]);
                            unset($group[$k]);
                            $cellTouchTab[] = $cellTouch;
                        }
                    }
                }
                if(!empty($t)){
                    $newGroup = array_merge($newGroup, $cellTouchTab);
                    $cellSearchTab = $cellTouchTab;
                    if(empty($groupTemp)){
                        $check = true;
                    }
                }
                else{
                    $check = true;
                }
                $index++;
            }
            while($check == false);
            $allNewGroups[] = $newGroup;
            break;
        }
    }
    while(!empty($group));
    return $allNewGroups;
}

要测试它:jdoodle.com/ia/iU2 2 2

这个函数是我使用的函数,因为它是最快的,它需要第二个表和已经变成蓝色的单元格的位置,它更新所有的白细胞组:

代码语言:javascript
复制
function rec5($allGroups, $cellDel){
    // $allGroups is the table containing all the groups of white cells that touch each other [[y1,x1],[y1,x2],[y2,x1],..]
    // $cellDel is the position of the cell that has become blue [y,x]
    $allGroupsTemp = $allGroups;
    foreach($allGroupsTemp as $k2 => $group){
        $indexCellDel = array_search([$cellDel[0],$cellDel[1]], $group);
        if(is_int($indexCellDel)){
            unset($allGroupsTemp[$k2][$indexCellDel]);
            if(!empty($allGroupsTemp[$k2])){
                $newGroups = [];
                foreach($allGroupsTemp[$k2] as $cell){
                    $check = false;
                    $cellsTouch = [];
                    foreach($newGroups as $k3 => $newGrp){
                        if(    in_array([$cell[0]-1,$cell[1]], $newGrp)
                            || in_array([$cell[0],$cell[1]-1], $newGrp)
                            || in_array([$cell[0]+1,$cell[1]], $newGrp)
                            || in_array([$cell[0],$cell[1]+1], $newGrp)){
                            $cellsTouch[] = $k3;
                            $check = true;
                        }
                    }
                    if(!$check){
                        $newGroups[] = [$cell];
                    }
                    else{
                        if(count($cellsTouch) == 1){
                            $newGroups[$cellsTouch[0]][] = $cell;
                        }
                        else{
                            $d = [];
                            foreach($cellsTouch as $bb){
                                $d = array_merge($d, $newGroups[$bb]);
                                unset($newGroups[$bb]);
                            }
                            $d = array_merge([$cell], $d);
                            $newGroups[] = $d;
                        }
                    }
                }

                if(count($newGroups) > 1){
                    unset($allGroupsTemp[$k2]);
                    foreach($newGroups as $newGrp){
                        $allGroupsTemp[] = $newGrp;
                    }
                }
            }
            else{
                unset($allGroupsTemp[$k2]);
            }
        }
    }
    return $allGroupsTemp;
}

要测试它:jdoodle.com/ia/iU3 3 3

According到了网格的大小,我的游戏允许很多蓝色和白色的组合(对于一个5x5的网格,我可以有数万个),而我的问题是我创建的所有函数都太慢了,你认为我能让我的功能更快吗?

EN

回答 1

Code Review用户

回答已采纳

发布于 2021-11-01 16:51:59

好吧,我试过你的第一个功能了。我没时间和其他人在一起。首先,代码,然后我将尝试解释它:

代码语言:javascript
复制
$gameSize = 5;
$gameGrid = [[1, 0, 1, 0, 1],
             [1, 0, 0, 0, 1],
             [1, 0, 1, 0, 1],
             [1, 0, 0, 0, 1],
             [1, 1, 1, 1, 1]];

function touchingCells(&$grid, $y, $x, $cells = [])
{
    $grid[$y][$x] = 0;
    $cells[] = ['y' => $y, 'x' => $x];
    foreach ([-1, 0, 1] as $offsetY) {
        $scanY = $y + $offsetY;
        foreach ([-1, 0, 1] as $offsetX) {
            $scanX = $x + $offsetX;
            if ($grid[$scanY][$scanX] ?? 0 > 0) {
                $cells = touchingCells($grid, $scanY, $scanX, $cells);
            }
        }
    }
    return $cells;
}

$groups = [];
$tempGrid = $gameGrid;
foreach ($gameGrid as $y => $row) {
    foreach ($row as $x => $value) {
        if ($tempGrid[$y][$x] > 0) {
            $groups[] = touchingCells($tempGrid, $y, $x);
        }
    }
}

var_export($groups);

结果是:

代码语言:javascript
复制
[0 => [0 =>  ['y' => 0, 'x' => 0],
       1 =>  ['y' => 1, 'x' => 0],
       2 =>  ['y' => 2, 'x' => 0],
       3 =>  ['y' => 3, 'x' => 0],
       4 =>  ['y' => 4, 'x' => 0],
       5 =>  ['y' => 4, 'x' => 1],
       6 =>  ['y' => 4, 'x' => 2],
       7 =>  ['y' => 4, 'x' => 3],
       8 =>  ['y' => 3, 'x' => 4],
       9 =>  ['y' => 2, 'x' => 4],
       10 => ['y' => 1, 'x' => 4],
       11 => ['y' => 0, 'x' => 4],
       12 => ['y' => 4, 'x' => 4]],      
 1 => [0 =>  ['y' => 0, 'x' => 2]],
 2 => [0 =>  ['y' => 2, 'x' => 2]]];

我不认为这段代码比您的代码快得多;它们都非常快,但我试图使代码的可读性稍差一些,尽管在这方面还远远不够理想。

这里重新定义了输入网格,因此它可以识别为网格。1表示白色单元格,0表示蓝色单元格。

我用$tempGrid检查触摸细胞。一旦检测到已使用的单元格触碰,我就将其设置为零,因此不会再次检测到它,并将其存储在一个名为$cells的数组中。

在这段代码中有几件事情对您来说可能是新的。

  • 此例程使用foreach循环中的偏移量在单元格周围检查。尽管这意味着我需要使用两个额外的循环,但这也意味着我只需要在touchingCells()函数中使用一个D10
  • 我没有首先使用isset(),而是使用零聚结算子来检查单元格是否触碰。我甚至可以将> 0($grid[$scanY][$scanX] ?? 0 > 0)中略去,但我总是更喜欢清晰而不是简洁。
  • 还要注意缺少像array_merge()这样的数组函数。

也许我稍后会尝试处理其他功能。我仍然认为蛮力的方法是不明智的,但由于你不会给我们这个游戏的所有细节,所有我们可以做到的一点与给定的例程。

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/269575

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档