Я работаю над игрой на PHP. У меня есть система, которая может случайным образом генерировать карты с путями в них. Вот пример:
http://i1244.photobucket.com/albums/gg579/Xeniar117/Map.png
(Я обновил этот пост, не имея достаточного количества повторений для этого изображения, чтобы оно оставалось непосредственно на странице, которую кто-то другой сделал возможным с помощью своего представителя, извините)
Каждой ячейке карты присвоена четырехзначная строка, обозначающая путешествие (W, N, E, S). Таким образом, ячейка 11 на карте выше будет иметь строку 1110, а ячейка 17 будет иметь строку 1001. Эта строка (она же NavString) генерируется случайным образом в рамках правил, чтобы предотвратить отправку игроков с карты.
Любые ячейки, имеющие только одно направление движения, помещаются в $ endcaps (массив). Кроме того, любые ячейки с 3 и 4 направлениями перемещения помещаются в $ endcaps, но с таким же количеством входов в $ endcaps, как и направления перемещения (например, 3-стороннее пересечение получает 3 входа в $ endcaps) Ячейки, имеющие только 2 направления, не добавляются в Это потому, что у них есть 1 вход и только 1 другой выход, так что это прямой путь внутрь и наружу; ни разветвлений, ни тупиков.
Я выполняю цикл через $ endcaps, чтобы получить начальную точку для каждого раздела пути, который я хочу записать. Используя NavString, я следую по каждому пути из ячейки, собранной из $ endcaps, пока не доберусь до другой ячейки, которая находится в $ endcaps (используя in_array ($ endcaps)), все время записывая номера ячеек, проходящих через нее, в $ paths [$ path ] [$ шаг]. Каждый новый $ endcap I $ path ++ и каждая новая ячейка между $ endcaps I $ step ++.
Вот пример того, как выглядит $ paths после того, как он выходит из цикла:
[Примечание: карта на изображении - это то, откуда появился этот 2D-массив]
Array
(
[0] => Array
(
[0] => 4
[1] => 9
[2] => 14
)
[1] => Array
(
[0] => 6
[1] => 5
[2] => 10
[3] => 11
)
[2] => Array
(
[0] => 6
[1] => 1
[2] => 2
[3] => 7
)
[3] => Array
(
[0] => 6
[1] => 7
)
[4] => Array
(
[0] => 6
[1] => 11
)
[5] => Array
(
[0] => 7
[1] => 6
)
[6] => Array
(
[0] => 7
[1] => 2
[2] => 1
[3] => 6
)
[7] => Array
(
[0] => 7
[1] => 12
[2] => 11
)
[8] => Array
(
[0] => 8
[1] => 13
)
[9] => Array
(
[0] => 11
[1] => 10
[2] => 5
[3] => 6
)
[10] => Array
(
[0] => 11
[1] => 6
)
[11] => Array
(
[0] => 11
[1] => 12
[2] => 7
)
[12] => Array
(
[0] => 13
[1] => 8
)
[13] => Array
(
[0] => 13
[1] => 14
)
[14] => Array
(
[0] => 13
[1] => 18
[2] => 19
[3] => 14
)
[15] => Array
(
[0] => 14
[1] => 13
)
[16] => Array
(
[0] => 14
[1] => 9
[2] => 4
)
[17] => Array
(
[0] => 14
[1] => 19
[2] => 18
[3] => 13
)
[18] => Array
(
[0] => 16
[1] => 17
[2] => 22
[3] => 23
)
[19] => Array
(
[0] => 23
[1] => 22
[2] => 17
[3] => 16
)
)
Я хочу сравнить одинаковые значения в под-массивах с другими под-массивами в $ paths. Если найдено совпадение 1+, я хочу объединить два массива вместе и продолжить поиск подмассивов с хотя бы одним общим значением, НО мне нужно разрешить добавление любых новых дополнений в сравнение.
Так что в идеале это должно объединиться в двумерный массив только с 3 подмассивами после того, как все сказано и сделано. требуемый результат вышеприведенного примера должен выглядеть следующим образом:
array (
array(1,2,5,6,7,10,11,12)
array(4,9,14,8,13,18,19)
array(16,17,22,23)
)
Вышеуказанное будет отличным представлением путей, которые я затем смогу использовать, чтобы убедиться, что вход и выход соединены, и игрок не попадет в ловушку!
Итак, мой вопрос: как я могу уточнить пути $ (в первом блоке кода) до массива во 2-м блоке кода? Помните, что эти карты генерируются случайным образом, поэтому $ paths может иметь любое количество под-массивов, а под-массивы могут иметь любое количество элементов, которые могут быть любым числом ячеек (в зависимости от того, как система генерировала пути)
Надеюсь, этого достаточно, чтобы вы, ребята, помогли мне, в прошлый раз, когда я спросил, как это сделать, они сказали, что я слишком расплывчатый (и после некоторого размышления над этим я согласен). Если его недостаточно, хорошо ...
ОБНОВЛЕНИЕ То, что я пробовал до сих пор
$set=0;
foreach($paths as $loop1key=>$loop1) {
foreach($paths as $loop2key=>$loop2) {
if(count(array_intersect($loop1,$loop2)) > 0) {
$consolidated = array_merge($loop1,$loop2);
unset($paths[$loop2key],$paths[$loop1key]);
$loop1 = $consolidated;
}
}
$after[$set]=$consolidated;
$set++;
}
И (предложено @hackerartist):
$after = array();
foreach($paths as $numArray) {
$addedKey = -1;
foreach ($after as $key=>$conArray) {
if ($addedKey<0&&count(array_intersect($conArray,$numArray))){
$after[$key]=array_unique(array_merge($after[$key],$numArray));
$addedKey = $key;
}
if ($addedKey>=0 && count(array_intersect($after[$addedKey],$numArray))) {
$after[$addedKey] = array_unique(array_merge($after[$addedKey],$after[$key]));
unset($after[$key]);
}
}
if ($addedKey<0) {
$after[] = $numArray;
}
}
ОБНОВЛЕНИЕ # 2 Я подправил свою вторую попытку (та, что прямо здесь ^^^), и она, кажется, работает 99% времени, однако все еще не удается объединить некоторые участки пути в их правильную группировку. Весь мой исходный код ниже с твиком, окруженным комментариями. (Строки 141-158 в соответствии с PHP Expert Editor)
<?php
$rows = 5;//Set statically to test, will be random in final version
$cols = 5;//Same as rows, will eventually be a random value
$gridsize = $rows * $cols;
for($r=0;$r<$rows;$r++){//Loop as many times as $rows
for($c=0;$c<$cols;$c++){//Loop as many times as $cols
$cell = ($r * $cols) + $c;//Current cell ((Current row * Total Columns) + Current Column)
if($r == 0 && $c > 0 && $c < ($cols - 1)){//North edge cell
$west = $cells[$cell - 1][2];
$east = rand(0,1);
$south = rand(0,1);
$string = $west."0".$east.$south;
} elseif ($r > 0 && $r < ($rows - 1) && $c == 0){//West Edge
$north = $cells[$cell - $cols][3];
$east = rand(0,1);
$south = rand(0,1);
$string = "0".$north.$east.$south;
} elseif ($c == ($cols - 1) && $r > 0 && $r < ($rows - 1)){//East Edge
$west = $cells[$cell - 1][2];
$north = $cells[$cell - $cols][3];
$south = rand(0,1);
$string = $west.$north."0".$south;
} elseif ($r == ($rows - 1) && $c > 0 && $c < ($cols - 1)){//South Edge
$west = $cells[$cell - 1][2];
$north = $cells[$cell - $cols][3];
$east = rand(0,1);
$string = $west.$north.$east."0";
} else {//Either a Corner or Core Cell
switch($cell){
case '0'://NW Corner
$east = rand(0,1);
$south = rand(0,1);
$string = "00".$east.$south;
break;
case ($cols - 1)://NE Corner
$west = $cells[$cell - 1][2];
$south = rand(0,1);
$string = $west."00".$south;
break;
case ($gridsize - $cols)://SW Corner
$north = $cells[$cell - $cols][3];
$east = rand(0,1);
$string = "0".$north.$east."0";
break;
case ($gridsize - 1)://SE Corner
$west = $cells[$cell - 1][2];
$north = $cells[$cell - $cols][3];
$string = $west.$north."00";
break;
default://Core cell
$west = $cells[$cell - 1][2];
$north = $cells[$cell - $cols][3];
$east = rand(0,1);
$south = rand(0,1);
$string = $west.$north.$east.$south;
break;
}
}
for($x=0;$x<4;$x++){
if($string[$x]==1){
$totalnav++;
$dirs[]=$x;
}
}
if($totalnav == 1 || $totalnav > 2){
$endcaps[$cell]=$dirs;
}
unset($totalnav);
unset($dirs);
$cells[] = $string;
}
}
//Determine center
foreach($cells as $cellnum=>$cell){
$center = $cell[0]+$cell[1]+$cell[2]+$cell[3];
if($center > 0){$cell .= "10000";}
else{$cell.="00000";}
$blocks[]=$cell;
}
//Refine rooms
for($r=0;$r<$rows-1;$r++){
for($c=0;$c<$cols-1;$c++){
$nw = ($r * $cols) + $c;//Current Cell Number
$ne = $nw + 1;
$sw = $nw + $cols;
$se = $ne + $cols;
$loop = 0;
if($blocks[$nw][2]==1&&$blocks[$nw][3]==1){$loop++;}
if($blocks[$ne][0]==1&&$blocks[$ne][3]==1){$loop++;}
if($blocks[$sw][1]==1&&$blocks[$sw][2]==1){$loop++;}
if($blocks[$se][0]==1&&$blocks[$se][1]==1){$loop++;}
if($loop == 4){//Loop detected, creating room
$blocks[$nw][8]=1;
$blocks[$ne][7]=1;
$blocks[$sw][6]=1;
$blocks[$se][5]=1;
$loop=0;
}
}
}
$path=0;
$oppnodes = array(0=>array(2,-1),1=>array(3,($cols*-1)),2=>array(0,1),3=>array(1,$cols));
foreach($endcaps as $cellnumber=>$directions){
foreach($directions as $direction){
$step=0;
$paths[$path][$step++]=$cellnumber;
$nextcell = $cellnumber + $oppnodes[$direction][1];
$nextnode = $oppnodes[$direction][0];
$end=0;
while($end==0){
if(!isset($endcaps[$nextcell])){
//Pass the torch from last to current
$currentcell = $nextcell;
$currentnode = $nextnode;
$nav = substr($cells[$currentcell],0,4);//Grab nav string from current cell.
$nav[$currentnode]=0;//Disable opposite node from direction last traveled
for($x=0;$x<4;$x++){
if($nav[$x]=="1"){
$nextnode = $oppnodes[$x][0];
$nextcell = $currentcell + $oppnodes[$x][1];
}
}
$paths[$path][$step]=$currentcell;
} else {
$paths[$path][$step]=$nextcell;
$end=1;
}
$step++;
}
$path++;
}
}
//Problem area start ===================================================
$after = array();
foreach($paths as $arrayOfNumbers) {
$addedKey = -1;
foreach($after as $key=>$newArrayOfNumbers){
if($addedKey < 0 && count(array_intersect($arrayOfNumbers,$newArrayOfNumbers))){
$after[$key] = array_unique(array_merge($arrayOfNumbers,$newArrayOfNumbers));
$addedKey = $key;
} elseif($addedKey >= 0 && count(array_intersect($after[$key],$newArrayOfNumbers))){
$after[$key] = array_unique(array_merge($after[$key],$newArrayOfNumbers));
unset($paths[$key]);
}
}
if($addedKey<0){
$after[] = $arrayOfNumbers;
}
}
//Problem area end ===================================
echo"<table>Array Representation of Paths In Map
";print_r($after);echo"
";
echo "
";
echo "";
следующие ($ блоки);
foreach ($ directions как $ direction) {unset ($$ direction);}
}
echo "";
}
echo "";
переменные не установлены ($ блоки);
echo "";
снята с охраны ($ после);
?>
Я не прошу вас проверить весь мой код, а просто проблемную область, чтобы узнать, сможете ли вы выяснить, почему он так часто пропускает консолидацию. Размещение всего источника кажется наиболее логичным способом, позволяющим вам увидеть реальные результаты, которые я получаю. Источник не требует никаких внешних источников и не требует специального имени файла. Я просто не могу понять, почему он работает в 99% случаев без каких-либо проблем, но в 1/100 раза он не сможет объединить раздел пути в свою правильную группу. Конечно, я продолжу исследовать самостоятельно, но любой совет будет признателен. Спасибо!
ОБНОВЛЕНИЕ № 3 Так близко!
Я возился с некоторым кодом, предложенным хакерартистом здесь, в StackOverflow, который с некоторыми изменениями работает так, как я хочу, в 99% случаев. К сожалению, 99% не приемлемо. Предполагается, что код объединяет подмассивы с любыми общими элементами с любыми другими подмассивами в многомерном массиве, например так:
$array = array(
array(6,5,0,1,6),
array(6,11),
array(11,10,15,16,17,12),
array(11,12),
array(12,13),
array(18,19,14),
array(7,8,3,4)
);
В такой массив:
$array = array(
array(0,1,5,6,11,10,15,16,17,12,13),
array(18,19,14),
array(7,8,3,4)
);
Вот код, который я использую, чтобы попытаться выполнить это:
$ paths будет $ массивом выше.
for($x=0;$x<count($paths);$x++){//Loop through paths
$paths = array_values($paths);//Reset keys
for($y=0;$y<count($paths);$y++){//Loop through again
if($x != $y){//If we arent on the same array
if(count(array_intersect($paths[$x],$paths[$y]))){//If there is even 1 matching element
$paths[$x] = array_unique(array_merge($paths[$x],$paths[$y]));//Merge arrays
unset($paths[$y]);//Remove array just merged
}
}
}
}
Существует также измененная версия предложенного хакерартистом решения:
$ paths2 будет массивом, подобным $ array выше
foreach($paths2 as $arrayOfNumbers) {
$addedKey = -1;
foreach($after as $key=>$newArrayOfNumbers){
if($addedKey < 0 && count(array_intersect($arrayOfNumbers,$newArrayOfNumbers))){
$after[$key] = array_unique(array_merge($arrayOfNumbers,$newArrayOfNumbers));
$addedKey = $key;
} elseif($addedKey >= 0 && count(array_intersect($after[$key],$newArrayOfNumbers))){
$after[$key] = array_unique(array_merge($after[$key],$newArrayOfNumbers));
unset($paths2[$key]);
}
}
if($addedKey<0){
$after[] = $arrayOfNumbers;
}
}
Теперь они могут работать для приведенного мною примера, но когда вы используете систему, которую я создал, для генерации массивов, с которыми должны работать эти коды, как я уже сказал, они пропускают один или два массива, которые должны быть объединены в еще один с общим элементом (ами) каждые 1 из 100 раз (оценка !!!) Я передаю другой массив с разными элементами в каждом подмассиве через код.
Кто-нибудь знает, что я делаю неправильно и как исправить этот недостаток?