Массив, таблица, данные (Любителям поломать голову посвящается)

#1 12 сентября 2015 в 16:19
Есть код
  1. <?php
  2. $tab = round(sqrt(count($result)));
  3. foreach($result as $result) {
  4. $i++; ?>
  5. <div style="background: #ccc; width: 32px; height: 32px; display: inline-block; margin-bottom: 4px;"><?php echo $result['id']; ?></div>
  6. <?php if ($i==$tab) { echo '<div style="clear: both;"></div>'; unset($i); } ?>
  7.  
  8. <?php } ?>
Данный код выведет следующее на экран:

То есть сколько бы значений в массиве не было — будет строиться такая (квадратная схема).
Не будем утрировать вопрос, что если будет 1000 значений в строке, как поместится в экране и т.д.

Вопрос в следующем. Как по id заданной клетки получить значения соседних клеток (тех что слева, справа, сверху, снизу и по диагоналям ближайшие)?

То есть например у клетки 1 соседи 2, 5 и 6, у клетки 8 соседи 3, 4, 7, 11 и 12, у клетки 10 соседи 5, 6, 7, 9, 11, 13, 14 и 15

Может быть для этого логическое решение?
#2 12 сентября 2015 в 16:26

Как по id заданной клетки получить значения соседних клеток (тех что слева, справа, сверху, снизу и по диагоналям ближайшие)?

kreator
Может как то так?
  1.  
  2. $a = 7; //заданная клетка
  3. $b = $a-5; //первый сосед
  4. $c = $a+5; //последний сосед
  5. $val = array(); //все соседи
  6. for($i=$b;$i<=$c;$i++){
  7. if($i != $a){
  8. $val[] = $i;
  9. }
  10. }
  11.  
Первое что в голову пришло)

P.S. У меня все соседи получились
P.S.P.S только надо продумать тот случай, если клетки будут крайними
#3 12 сентября 2015 в 16:29

Может как то так?

Rossoman
И в этом что-то есть, только надо учесть что этот вариант подойдет, только если заданная клетка расположена так, что вокруг нее полностью есть соседи.
Заданная клетка может быть в углу, или у стенки, например клетка 1, 3 или 12
#4 12 сентября 2015 в 16:30

Заданная клетка может быть в углу, или у стенки

kreator
да, точно, в пспс уже добавил эту мысль)
#5 12 сентября 2015 в 16:34

только надо продумать тот случай, если клетки будут крайними

Rossoman
неужели 8 сценариев развития собитий писать:
1. Если клетка первая
2. К верху в первом ряду
3. В правом углу первого ряда
4. К левой стенке промежуточных рядов
5. К правой стенке промежуточных рядов
6. В левом нижнем углу
7. К нижней стенке
8. В правом нижнем углу
#6 12 сентября 2015 в 16:36
И так не столь легкую задачу, делает не легче то, что таблица может выглядеть и так

то есть она может быть не квадратной

а если предположить, что клеток будет 17 то вариантов развития событий будет еще больше ....
так как клетка 17, она же последняя и она же в левом нижнем углу
#7 12 сентября 2015 в 16:44
$p — порядок матрицы (ее размер) на данном примере $p=4;
$n — id заданной клетки.
Теперь:
$top = $n-$p; // id верхней клетки
$botton = $n+$p; // id нижней клетки
$left = $n-1; // id левой клетки
$right = $n+1; // id правой клетки
$top_left = $top-1; // id диагональной клетки вверху слева… и т.д.

Думаю, теперь уже понятно.

После каждого вычисления надо следить, чтобы id не вылетели за пределы таблицы: например, у ячейки с $n==12 нет правых соседей. Это тоже просто: если номер правой ячейки получился больше номера последней ячейки в ряду, ее не существует. Для левой, верхней, нижней — аналогично.

В случае неквадратной (прямоугольной) матрицы порядок следует заменить на размеры матрицы по горизонтали (при вычислении верхних и нижних элементов) и на размер по вертикали(при вычислении последнего элемента в ряду и первого в следующем).

Если матрица "с хвостиком" — дополнительно проверяется — есть ли вычисленный id. Например, для 18 номера правый id == 19 но его не существует, поскольку вычисленный id больше максимального id таблицы.
#8 12 сентября 2015 в 20:13
Всем спасибо за наводки. Раз сам создал тему — мне и делиться решением.

Не знаю зачем вам это пригодится. А вдруг.
Сделал такую вот небольшую функцию выводящую соседей по вышеуказанным условиям.

В $item передаем кол-во элементов, $pos — текущий элемент соседей которого нужно получить

  1. public function getSosed($item, $pos){
  2.  
  3. $tab = floor(sqrt($item));
  4. $row = ceil($item/$tab);
  5.  
  6. $res_row = ceil($pos/$tab);
  7. $res_col = $pos-(($res_row-1)*$tab);
  8.  
  9. $s = array();
  10.  
  11. if($res_row>1) {
  12.  
  13. $s['top'] = $pos-$tab;
  14. if($res_col>1) $s['top-left'] = $pos-$tab-1;
  15. if($res_col<$tab) $s['top-right'] = $pos-$tab+1;
  16.  
  17. }
  18.  
  19. if($res_row<$row) {
  20.  
  21. if($pos+$tab<=$item) $s['bottom'] = $pos+$tab;
  22. if($res_col>1 && $pos+$tab-1<=$item) $s['bottom-left'] = $pos+$tab-1;
  23. if($res_col<$tab && $pos+$tab+1<=$item) $s['bottom-right'] = $pos+$tab+1;
  24.  
  25. }
  26.  
  27. if($res_col>1) $s['left'] = $pos-1;
  28. if($res_col<$tab && $pos<$item) $s['right'] = $pos+1;
  29.  
  30. return $s;
  31.  
  32. }
Вы не можете отвечать в этой теме.
Войдите или зарегистрируйтесь, чтобы писать на форуме.
Используя этот сайт, вы соглашаетесь с тем, что мы используем файлы cookie.