我的游戏是一个网格,你必须通过点击它们来改变它们的颜色。当我生成一个网格时,我必须知道我的游戏允许的所有可能的蓝白色细胞组合,以了解网格的难度级别。
每次创建场景时,我都必须更新一个重要的参数,即一组相互接触的白细胞。
我在我的函数中使用了3个表:
第一个包含所有白细胞的位置。
// example for a 3,3 grid :
[y0 => [x0 => x0, x1 => x1], y1 => [x0 => x0], y2 => [x1 => x1, x2 => x2]]第二个包含相互接触的分组白血球的位置。
// same example
[ [[y0,x0],[y0,x1],[y1,x0]], [[y2,x1],[y2,x2]] ]第三组是第二表中的一组。
// same example
[[y0,x0],[y0,x1],[y1,x0]]我创建了几个函数:
这个表只需要第一个表,然后返回第二个表。在创建网格时,我使用它初始化参数。
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
这个函数只需要第二个表,它更新了一组白细胞,我知道其中一个单元已经变成蓝色了。我不用它是因为它太慢了。
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
这个函数是我使用的函数,因为它是最快的,它需要第二个表和已经变成蓝色的单元格的位置,它更新所有的白细胞组:
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的网格,我可以有数万个),而我的问题是我创建的所有函数都太慢了,你认为我能让我的功能更快吗?
发布于 2021-11-01 16:51:59
好吧,我试过你的第一个功能了。我没时间和其他人在一起。首先,代码,然后我将尝试解释它:
$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);结果是:
[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()这样的数组函数。也许我稍后会尝试处理其他功能。我仍然认为蛮力的方法是不明智的,但由于你不会给我们这个游戏的所有细节,所有我们可以做到的一点与给定的例程。
https://codereview.stackexchange.com/questions/269575
复制相似问题