Что нового

[Массивы] Работа с двумерным массивом, и его преобразования

Strog

Новичок
Сообщения
22
Репутация
0
Что у нас есть
1 Flash игра с полем 6*6
2 Массив в котором хранятся значения , поля игры Скрин ↓↓↓
http://img-fotki.yandex.ru/get/5808/38920702.0/0_78f37_99378b4a_L.jpg" width="" />

Задача состоит в том что бы воссоздать алгоритм игры , или написать (ниже описанные)алгоритмы что на мой взгляд намного проще.
Видео с игрой (алгоритм)
http://www.youtube.com/watch?v=y49usxUMEno

Общая задача такая Функция (Подсчет,Удаление) → Функция(Всплытие) →Функция (Поиск,[list type=decimal]
[*]ДА → Функция (Подсчет,Удаление) → Функция(Всплытие)
[*]НЕТ → Стоп, следующий вариант
[/list]

ПУНКТ 1 Исходный массив
[box title=TitleBox]
|5|3|2|5|1|4
|5|4|1|5|3|5
|4|1|2|1|5|4
|4|5|3|5|2|4
|2|3|4|4|3|3
|5|5|4|2|5|1[/box]

ПУНКТ 2 Выделяем удаляемую область (в донном случае крест)
Есть идеи как сделать чтобы для каждого варианта (всего 30) писать не от руки, а функция которая выделяла крест и потом просто подставить значение центрального квадрата

[box title=TitleBox]|5|3|2|5|1|4
|5|4|1|5|3|5
|4|1|2|1|5|4
|4|5|3|5|2|4
|2|3|4|4|3|3
|5|5|4|2|5|1
[/box]
ПУНКТ 3 Здесь надо записать значения выделенной области таким образом
Все 1 сложить и записать в переменную допустим $Summa_1
Все 2 сложить и записать в переменную допустим $Summa_2
И так далее до 5.

ПУНКТ 4 Заменить (удаление) ранее выделенную область на 0 (ну тут всё просто)

[box title=TitleBox]|5|3|0|5|1|4
|5|4|0|5|3|5
|0|0|0|0|0|4
|4|5|0|5|2|4
|2|3|0|4|3|3
|5|5|4|2|5|1[/box]

ПУНКТ 5 Следующий шаг в том что 0 "всплывают" ну или значения "падают"

[box title=Было]|5|3|0|5|1|4
|5|4|0|5|3|5
|0|0|0|0|0|4
|4|5|0|5|2|4
|2|3|0|4|3|3
|5|5|4|2|5|1[/box]
[box title=Стало]|0|0|0|0|0|4
|5|3|0|5|1|5
|5|4|0|5|3|4
|4|5|0|5|2|4
|2|3|0|4|3|3
|5|5|4|2|5|1[/box]

ПУНКТ 6 Ну вот мы подошли к самому трудному (по моему мнению)
Поиск по вертикали И по горизонтали (Одновременно*, опишу это чуть ниже) в ряд одинаковых значений
в нашем случае это 5 добавление этих значений в $Summa_5 И самое главное ради этого прога надо подсчитать сколько в ряд (горизонтали) удаляем и записать максимальное значение в $переменную
$переменную = наш вариант 1
Здесь момент как в ПУНКТе 4 только удаляем 5
[box title=TitleBox]|0|0|0|0|0|4
|5|3|0|5|1|5
|5|4|0|5|3|4
|4|5|0|5|2|4
|2|3|0|4|3|3
|5|5|4|2|5|1[/box]

ну а дальше начиная с ПУНКТа 5
Если в ПУНКТе 6 не нашлось 3 и более в ряд (до 6)
Делаем следующий вариант

*Одновременно потому что могут быть такие варианты (пример от руки)

|5 4 1 5 6 4|
|4 8 8 8 2 1|
|6 8 2 5 6 7|
|3 8 5 8 7 9|

Взял лопату , куда ↨↔ копать?
Поделитесь основными идеями.
 

Redline

AutoIT Гуру
Сообщения
506
Репутация
375
Ну давай потихоньку начнем:
Strog [?]
ПУНКТ 2 Выделяем удаляемую область (в донном случае крест)Есть идеи как сделать чтобы для каждого варианта (всего 30) писать не от руки, а функция которая выделяла крест и потом просто подставить значение центрального квадратаTitleBox|5|3|2|5|1|4|5|4|1|5|3|5|4|1|2|1|5|4|4|5|3|5|2|4|2|3|4|4|3|3|5|5|4|2|5|1ПУНКТ 3 Здесь надо записать значения выделенной области таким образомВсе 1 сложить и записать в переменную допустим $Summa_1Все 2 сложить и записать в переменную допустим $Summa_2И так далее до 5.ПУНКТ 4 Заменить (удаление) ранее выделенную область на 0 (ну тут всё просто) TitleBox|5|3|0|5|1|4|5|4|0|5|3|5|0|0|0|0|0|4|4|5|0|5|2|4|2|3|0|4|3|3|5|5|4|2|5|1

1. Клик по центру креста должен дать тебе индексы ячейки (будем считать, что они у нас уже есть)
2. Определяем другие ячейки, входящие в крест.
2. Считываем данные всех ячеек и подсчитываем очки.
3. Обнуляем "крест".
4. Жмем "смыв".

Код:
#include <Array.au3>
Global $aArr[6][6]

For $i = 0 To UBound($aArr) - 1 ; заполняем массив
	For $j = 0 To UBound($aArr, 2) - 1
		$aArr[$i][$j] = Random(1, 5, 1)
	Next
Next

_ArrayDisplay($aArr) ; стартовый массив

$x = 2 ; координаты центра креста
$y = 3

; проверка на полноценность креста
If ($x - 2) >= 0 And ($x + 2) <= (UBound($aArr) -1) And ($y - 2) >= 0 And ($y + 2) <= (UBound($aArr, 2) -1) Then
	_CrossBlow($x, $y)
Else
	MsgBox(0, 'Error', 'Данная ячейка не может образовать крест')
EndIf

Func _CrossBlow($iX, $iY)
	Local $aScore[9], $iCounter = 0
	For $i = ($iX - 2) To $iX + 2 ; считываем значения с горизонтали креста и обнуляем их
		$aScore[$iCounter] = $aArr[$iY][$i]
		$aArr[$iY][$i] = '0'
		$iCounter += 1
	Next

	For $i = ($iY - 2) To $iY + 2 ; считываем значения с вертикали креста и обнуляем их
		If $i <> 3 Then ; пропускаем центральную ячейку чтобы не считать ее дважды
			$aScore[$iCounter] = $aArr[$i][$iX]
			$aArr[$i][$iX] = '0'
			$iCounter += 1
		EndIf
	Next
	Local $sScore = _ArrayToString($aScore)
	ConsoleWrite($sScore & @CRLF)

	Local $aScoreNumbers[6] = ['x', '1', '2', '3', '4', '5'] ; массив количества цифр в кресте (X просто для удобства восприятия)
	For $i = 1 To 5
		If StringReplace($sScore, $aScoreNumbers[$i], '') Then $aScoreNumbers[$i] = @extended
	Next
	ConsoleWrite(_ArrayToString($aScoreNumbers) & @CRLF) ; выдаст массив с количеством повторений каждой из цифр
	_ArrayDisplay($aArr)

	For $i = 0 To UBound($aArr) - 1 ; смыв креста, с одновременным заполнение рандомными числами "сверху"
		For $j = 0 To UBound($aArr, 2) - 1
			If $aArr[$i][$j] = '0' Then
				For $n = $i To 1 Step -1
					$aArr[$n][$j] = $aArr[$n - 1][$j]
				Next
				$aArr[0][$j] = Random(1, 5, 1)
			EndIf
		Next
	Next
	_ArrayDisplay($aArr)
	Return 0
EndFunc

Дальше просто ищи закономерности в построении цепочек. Дерзай сам!
 
Автор
S

Strog

Новичок
Сообщения
22
Репутация
0
Redline Большое спасибо , понял как "собрать" крест и ему подобные, считать значения суммировать их,обнулить и преобразовать массив.
Только вот загвоздка , все функции "крест" должны работать с НЕ исходным массивом - решение $a_pole = $a_pole2 где поле исходный массив (без всяких преобразований) а поле2 массив для преобразований , это всё для того чтобы можно было запускать зразу несколько функций и каждая работала со значениями исходного массива. Этого решения достаточно?
Так дальше , рылся на форумах c++ но так не чего не нашёл , задача в том чтобы найти в массиве $a_pole (исходный) ВСЕ значения допустим 3 , если плохо объяснил то вот наглядно
[box title=TitleBox]|5|3|2|5|1|4
|5|4|1|5|3|5
|4|1|2|1|5|4
|4|5|3|5|2|4
|2|3|4|4|3|3
|5|5|4|2|5|1
здесь их 6 [/box]

Из этого вытекает более сложная задача найти повторяющиеся элементы (помимо 0) (от 3-x)
по вертикали и горизонтали
[box title=TitleBox]|0|0|0|0|0|4
|5|3|0|5|1|5
|5|4|0|5|3|4
|4|5|0|5|2|4
|2|3|0|4|3|3
|5|5|4|2|5|1
[/box]
Ну и совсем верх для меня поиск таких повторов
[box title=TitleBox]|5|4|1|5|6|4
|4|8|8|8|2|1
|6|8|2|5|6|7
|3|8|5|8|7|9
|5|5|4|2|5|1
|2|3|1|4|3|3[/box]
 

Redline

AutoIT Гуру
Сообщения
506
Репутация
375
Strog [?]
Только вот загвоздка , все функции "крест" должны работать с НЕ исходным массивом - решение $a_pole = $a_pole2 где поле исходный массив (без всяких преобразований) а поле2 массив для преобразований , это всё для того чтобы можно было запускать зразу несколько функций и каждая работала со значениями исходного массива. Этого решения достаточно?
:wacko:
Из ролика я понял, что крест это что-то вроде бомбы, которую игрок кидает на центр и тогда все ячейки вокруг (крестом) исчезают, при том не важно что в них было.

Функция _CrossBlow обрабатывает массив $aArr.
Вот переделал - теперь в неё нужно передавать массив для обработки и координаты центра креста, а на выходе будет другой массив (какой присвоишь при вызове функции, у меня это $aNewArrayOut) этот массив сам состоит из двух массивов (один массив содержит всю матрицу с преобразованиями, а второй подсчет очков), и теперь крест может ставиться в любом место массива хоть в углу - просто некоторые "плечи" будут обрублены.
Массив массивов наверное сложен для понимания новичку, но данный пример должен возвращать два массива поэтому и решение такое.
Код:
#include <Array.au3>
Global $aArr[6][6]

For $i = 0 To UBound($aArr) - 1 ; заполняем массив
    For $j = 0 To UBound($aArr, 2) - 1
        $aArr[$i][$j] = Random(1, 5, 1)
    Next
Next

_ArrayDisplay($aArr) ; стартовый массив

$x = 0 ; координаты центра креста
$y = 1

$aNewArrayOut = _CrossBlow($aArr, $x, $y)
$aNewArray = $aNewArrayOut[0]
_ArrayDisplay($aNewArray)
$aScore = $aNewArrayOut[1]
_ArrayDisplay($aScore)

Func _CrossBlow($aInput, $iX, $iY)
    Local $sScore = '', $aOut[2]
    For $i = ($iX - 2) To $iX + 2 ; считываем значения с горизонтали креста и обнуляем их
        If $i >= 0 And $i <= (UBound($aInput) -1) Then ; проверка границ массива
            $sScore &= $aInput[$iY][$i]
            $aInput[$iY][$i] = '0'
        EndIf
    Next

    For $i = ($iY - 2) To $iY + 2 ; считываем значения с вертикали креста и обнуляем их
        If $i <> $iY And $i >= 0 And $i <= (UBound($aInput, 2) -1) Then ; пропускаем центральную ячейку и проверяем границы массива
            $sScore &= $aInput[$i][$iX]
            $aInput[$i][$iX] = '0'
        EndIf
    Next

    Local $aScoreNumbers[6] = ['x', '1', '2', '3', '4', '5'] ; массив количества цифр в кресте (X просто для удобства восприятия)
    For $i = 1 To 5
        If StringReplace($sScore, $aScoreNumbers[$i], '') Then $aScoreNumbers[$i] = @extended
    Next

    For $i = 0 To UBound($aInput) - 1 ; смыв креста, с одновременным заполнение рандомными числами "сверху"
        For $j = 0 To UBound($aInput, 2) - 1
            If $aInput[$i][$j] = '0' Then
                For $n = $i To 1 Step -1
                    $aInput[$n][$j] = $aInput[$n - 1][$j]
                Next
                $aInput[0][$j] = Random(1, 5, 1)
            EndIf
        Next
    Next
	$aOut[0] = $aInput
	$aOut[1] = $aScoreNumbers
    Return $aOut
EndFunc

Если я правильно понял вопрос, то да - такое присвоение абсолютно верно, здесь переменной $a_pole присваивается значение переменной $a_pole2.
При том не важно какого типа переменные: хоть оба массива, хоть один массив, а второй не массив - $a_pole станет тем же типом что $a_pole2 и получит его значение.

Теперь по поводу поиска значений:
1. Для чего искать отдельные значения? Может будем сразу искать целые линии или отдельные клетки тоже нужны?
2. Я так понимаю нам надо найти все прямые линии с длиной минимум в 3 ячейки с одинаковыми значениями, и если есть ответвления с такими же значениями, то их тоже нужно включить?
Тогда вопрос - какой длины ответвления учитывать?
[box title=1]
1|5|4|2|1|5
4|5|0|0|0|1
3|2|4|0|3|4
1|2|4|0|4|5
4|1|2|7|4|1
5|4|3|2|2|4
[/box]
[box title=2]
1|5|4|2|1|5
4|5|0|0|0|1
3|2|4|0|3|4
1|2|7|1|4|5
4|1|2|7|4|1
5|4|3|2|2|4
[/box]
[box title=3]
5|4|0|2|2|4
1|5|0|2|1|5
4|5|0|0|0|1
3|2|4|1|0|3
1|2|7|2|0|4
4|1|2|4|4|1
[/box]
3. Как быть с приоритетом поиска (хотя я не уверен что смогу такое реализовать)? Что нужно искать в первую очередь - прямые линии/длинные прямые линии/длинные линии с учетом ветвлений?

Самый главный вопрос - ты хочешь сделать игру или бота который будет играть? :D
 
Автор
S

Strog

Новичок
Сообщения
22
Репутация
0
Из ролика я понял, что крест это что-то вроде бомбы,
Совершенно верно :ok:

этот массив сам состоит из двух массивов
это я так понимаю... , не понимаю , из 2х одинаковых (и по размерам и по в них значениям)
где в нужный момент берётся один или другой.А изначальный мы
теперь в неё нужно передавать массив для обработки
, т.е. я смогу сначала одни координаты проверить а потом другие и все действия с исходными значениями.

должен возвращать два массива
Это у нас получиться что? Просто с возвращением мало знаком , в конце он вернёт начальное значение?

Может будем сразу искать целые линии или отдельные клетки тоже нужны?
Отдельные клетки нужны один раз , и то если стоит чекбокс(сделано), кол-во 2-ек на всём поле.Поиск я не сделал.
Я так понимаю нам надо найти все прямые линии с длиной минимум в 3 ячейки с одинаковыми значениями,
:ok:
и если есть ответвления с такими же значениями, то их тоже нужно включить?
Вот *** об этом я не думал, тогда дела хуже , если есть ответвления то прямые
с такими же значениями не включаем.(прямые выделил 888 и 888) Дописал А в прочем можно искать только прямые , при условии что после всех найденных , эти значения спишутся (без повторов)и обнулятся.
[box title=TitleBox]|5|4|1|5|6|4
|4|8|8|8|2|1
|6|8|2|5|6|7
|3|8|5|8|7|9
|5|5|4|2|5|1
|2|3|1|4|3|3[/box]
Тогда вопрос - какой длины ответвления учитывать?
1-да, 2 и 3 нет
да я тут прикинул всякие расклады и ветвления только как сдесь
[box title=TitleBox]|5|4|1|5|6|4
|4|8|8|8|2|1
|6|8|2|5|6|7
|3|8|5|8|7|9
|5|5|4|2|5|1
|2|3|1|4|3|3[/box]
ну максимум [box title=TitleBox]1|5|4|2|1|5
4|5|0|0|0|1
3|2|4|0|3|4
1|2|4|0|4|5
4|1|2|7|4|1
5|4|3|2|2|4[/box]
[box title=TitleBox]1|5|4|2|1|5
4|5|0|0|0|0
3|2|4|0|3|4
1|2|4|0|4|5
4|1|2|7|4|1
5|4|3|2|2|4[/box]
если что сам додумаюсь
3. Как быть с приоритетом поиска (хотя я не уверен что смогу такое реализовать)
длинные прямые линии (максимум 6 по горизонтали и 4 по вертикали )
прямые линии
Самый главный вопрос - ты хочешь сделать игру или бота который будет играть?
Программа как бы бот но не бот, она ищет все ходы , показывает результат а я решаю что в данной ситуации надо.Интересно? :-[
В игре есть возможность биться на равных, где ставки 1000 человек зависит от того как ты собираешь камни, играю почти год очень много уловок и хитростей

Вот сделал квадрат надеюсь без костылей
Код:
#include <Array.au3>
Global $a_Arr[6][6]

For $i = 0 To UBound($a_Arr) - 1 ; заполняем массив
    For $j = 0 To UBound($a_Arr, 2) - 1
        $a_Arr[$i][$j] = Random(1, 5, 1)
    Next
Next

_ArrayDisplay($a_Arr) ; стартовый массив

$x = 2 ; координаты центра креста
$y = 2
$a_NewArrayOut = _CrossBlow2($a_Arr, $x, $y)
$a_NewArray = $a_NewArrayOut[0]
_ArrayDisplay($a_NewArray)
$a_Score = $a_NewArrayOut[1]
 _gggg()
_ArrayDisplay($a_Score)

  Func _CrossBlow2($a_Input, $iX, $jY)
  
	 Local $s_Score = '', $a_Out[2]
	
    For $i = ($iX - 1) To $iX + 1 Step +1 
		 For $j = ($jY - 1) To $jY + 1 STEP +1 
			 If $i >= 0 And $i <= (UBound($a_Input) -1) And $j >= 0 And $j <= (UBound($a_Input, 2) -1) Then ; проверка границ массива
       $s_Score &=  $a_Input[$j][$i]
        $a_Input[$j][$i] = '0'
		EndIf
    Next
Next


    Local $a_ScoreNumbers[6] = ['x', '1', '2', '3', '4', '5'] ; массив количества цифр в кресте (X просто для удобства восприятия)
    For $i = 1 To 5
        If StringReplace($s_Score, $a_ScoreNumbers[$i], '') Then $a_ScoreNumbers[$i] = @extended
    Next

 For $i = 0 To UBound($a_Input) - 1 ; смыв креста, с одновременным заполнение рандомными числами "сверху"
        For $j = 0 To UBound($a_Input, 2) - 1
            If $a_Input[$i][$j] = '0' Then
                For $n = $i To 1 Step -1
                    $a_Input[$n][$j] = $a_Input[$n - 1][$j]
                Next
                $a_Input[0][$j] = 0
            EndIf
        Next
    Next
    $a_Out[0] = $a_Input
    $a_Out[1] = $a_ScoreNumbers
    Return $a_Out

EndFunc
 Func _gggg()
		
	$i_summaM = 0
	$i_summaL = 0
	$i_summaD = 0

    $i_summaL = $a_Score[4]
	$i_summaD = $a_Score[2]

	$i_summaM = $a_Score[1] + ($a_Score[3]*3) + ($a_Score[5]*5)

	$i_summaM = $i_summaM - 20
	
	$i_PoleSummaCherep = 4 ;yyyyYYYYyyyyYYYYyyyyYYYYyyyyyyyyYYYYyyyyYYYYyyyyYYYYyyyyyyyyYYYYyyyyYYYYyyyyYYYYyyyyyyyyYYYYyyy
	
	$i_Cepochka = 0


 MsgBox (0,"","-" & "|" & "-" & "|" & "["& $x & "-" & $y &"]"  & "|" & $i_Cepochka &"|" & $i_SummaM &"|"& $i_summaD &"|"& $i_summaL)
  
EndFunc
извиняюсь за некоторые неприемлемые названия функций (черновик)
 

Redline

AutoIT Гуру
Сообщения
506
Репутация
375
Strog [?]
это я так понимаю... , не понимаю , из 2х одинаковых (и по размерам и по в них значениям)где в нужный момент берётся один или другой.А изначальный мы
На выходе мы получим массив, состоящий их двух элементов - первый элемент - это преобразованный начальный массив игрового поля (после взрыва), а второй элемент - массив содержащий количество очков для каждой цифры. Это и есть массив массивов, т.е. в таком массиве элементы сами являются массивами :whistle:

т.е. я смогу сначала одни координаты проверить а потом другие и все действия с исходными значениями.
Ты передашь в эту функцию исходные значения, а на выходе получишь новые + массив с очками, при этом данные нового массива будут в переменной $aNewArrayOut, а начальный мы не трогаем - так что всегда можно будет откатиться.


Это у нас получиться что? Просто с возвращением мало знаком , в конце он вернёт начальное значение?
Возвращать от англ. Return - который в функции - это то что выдает функция на выходе (иногда говорят "имеем на выходе функции"). Здесь она вернет новый массив, начальный мы не трогаем, а только используем для вычислений.

Вот еще две функции:
1. Делает подсчет для каждой цифры в массиве
2. Тут я долго думал как организовать поиск пересечений и поглощений (чтобы более длинная цепочка съедала более короткую, если она в нее входит). Сделал в два прохода - первый ищет все цепочки по 3 элемента в ряд (вертикальных и горизонтальных), а второй проход перебирает все эти цепочки в поисках общих точек и если находит - складывает в один. А вывод решил сделать в виде массива с координатами этих цепочек.
В итоге эта функция выдает массив массивов (опять :smile: ) первое значение - цифра, второе - массив с координатами цепочки для этой цифры.

Например:
$aChainsArray[4][0] = 5
$aChainsArray[4][1] будет содержать пары чисел первое - строка, второе - столбец для цифры 5

$aChainsArray[5][0] = 5
$aChainsArray[5][1] будет содержать пары чисел первое - строка, второе - столбец для цифры 5, но это будет уже другая цепочка (пересечение с первой не произошло)

Код:
#include <Array.au3>
Global $aArr[6][6]

Dim $aArr[6][6] = [ _
[2, 2, 2, 1, 3, 1], _
[4, 4, 4, 4, 3, 1], _
[5, 5, 5, 4, 3, 1], _
[1, 5, 1, 4, 1, 1], _
[2, 5, 2, 1, 1, 6], _
[1, 5, 1, 1, 1, 1]]

_ArrayDisplay($aArr) ; стартовый массив

Dim $aNum[7] = ['количество', 1, 2, 3, 4, 5, 6]
For $i = 1 To 6
	$aNum[$i] = _FindNumbers($aArr, $aNum[$i])
Next

_ArrayDisplay($aNum)

Func _FindNumbers($aInput, $iNum) ; поиск и подсчет цифр в массиве
	Local $iCount = 0
	For $i = 0 To UBound($aInput) - 1
		For $j = 0 To UBound($aInput, 2) -1
			If $aInput[$i][$j] = $iNum Then $iCount += 1
		Next
	Next
	Return $iCount
EndFunc

$aChainsArray = _FindChainsInArray($aArr)
For $i = 0 To UBound($aChainsArray) - 1
	If IsArray($aChainsArray[$i][1]) Then _ArrayDisplay($aChainsArray[$i][1], $aChainsArray[$i][0])
Next

Func _FindChainsInArray($aInput) ; поиск цепочек в массиве
	Local $aTotal[1][2] ; массив, в котором будут содержаться все координаты цепочек всех цифр
	Local $iCountTotal = 0
	For $n = 1 To 6 ; цифры которые нужно найти (1-6)
		Local $aSumArray[1], $iMassCounter = 0
		For $i = 0 To UBound($aInput) - 1
			For $j = 0 To UBound($aInput, 2) - 1
				; поиск вертикальных цепочек
				If $aInput[$i][$j] = $n And $i < (UBound($aInput) - 2) Then ; проверка на цифру в ячейке и границу массива
					Local $aVert[2][2], $iCount = 1 ; в массиве будут храниться координаты ячеек
					$aVert[0][0] = $i
					$aVert[0][1] = $j
					For $z = $i + 1 To UBound($aInput) - 1
						If $aInput[$z][$j] = $n Then
							$aVert[$iCount][0] = $z
							$aVert[$iCount][1] = $j
							$iCount += 1
							ReDim $aVert[$iCount + 1][2]
						Else
							ExitLoop
						EndIf
					Next
					If UBound($aVert) > 3 Then
						ReDim $aVert[$iCount][2]
						$aSumArray[$iMassCounter] = $aVert ; запись массива в общий массив по цифре
						$iMassCounter += 1
						ReDim $aSumArray[$iMassCounter + 1]
					EndIf
				EndIf
				; поиск горизонтальных цепочек
				If $aInput[$i][$j] = $n And $j < (UBound($aInput, 2) - 2) Then ; проверка на цифру в ячейке и границу массива
					Local $aHor[2][2], $iCount = 1 ; в массиве будут храниться координаты ячеек
					$aHor[0][0] = $i
					$aHor[0][1] = $j
					For $z = $j + 1 To UBound($aInput, 2) - 1
						If $aInput[$i][$z] = $n Then
							$aHor[$iCount][0] = $i
							$aHor[$iCount][1] = $z
							$iCount += 1
							ReDim $aHor[$iCount + 1][2]
						Else
							ExitLoop
						EndIf
					Next
					If UBound($aHor) > 3 Then
						ReDim $aHor[$iCount][2]
						$aSumArray[$iMassCounter] = $aHor ; запись массива в общий массив по цифре
						$iMassCounter += 1
						ReDim $aSumArray[$iMassCounter + 1]
					EndIf
				EndIf
			Next
		Next
		If UBound($aSumArray) > 1 Then ; поиск пересечений цепочек
			ReDim $aSumArray[UBound($aSumArray) - 1]
			For $f = 0 To UBound($aSumArray) - 2
				$aFirst = $aSumArray[$f]
				For $r = $f + 1 To UBound($aSumArray) - 1
					$aSecond = $aSumArray[$r]
					For $s = 0 To UBound($aFirst) - 1
						For $o = 0 To UBound($aSecond) - 1
							If $aFirst[$s][0] == $aSecond[$o][0] And $aFirst[$s][1] == $aSecond[$o][1] Then ; цепочки имеют общие точки - объединяем координаты
								Local $aTemp = $aFirst ; объединенный массив
								Local $iCount = UBound($aTemp)
								For $v = 0 To UBound($aSecond) - 1
									$hFind = False
									For $w = 0 To UBound($aTemp) - 1
										If $aSecond[$v][0] == $aTemp[$w][0] And $aSecond[$v][1] == $aTemp[$w][1] Then
											$hFind = True
											ExitLoop
										EndIf
									Next
									If Not $hFind Then
										ReDim $aTemp[$iCount + 1][2]
										$aTemp[$iCount][0] = $aSecond[$v][0]
										$aTemp[$iCount][1] = $aSecond[$v][1]
										$iCount += 1
									EndIf
								Next
								$aFirst = $aTemp
								$aSumArray[$f] = $aTemp
								$aSecond = 0
								$aSumArray[$r] = 0
								ExitLoop 2
							EndIf
						Next
					Next
				Next
			Next
		EndIf
		Local $aSumTemp[1], $iCount = 0
		For $x = 0 To UBound($aSumArray) - 1 ; убираем цепочки, которые попали в объединение
			If IsArray($aSumArray[$x]) Then
				ReDim $aSumTemp[$iCount + 1]
				$aSumTemp[$iCount] = $aSumArray[$x]
				$iCount += 1
			EndIf
		Next
		For $x = 0 To UBound($aSumTemp) - 1 ; подготовка выходного массива
			ReDim $aTotal[$iCountTotal + 1][2]
			$aTotal[$iCountTotal][0] = $n
			$aTotal[$iCountTotal][1] = $aSumTemp[$x]
			$iCountTotal += 1
		Next
	Next
	Return $aTotal
EndFunc

С квадратом молодец - разобрался :ok:
 
Верх