В общем такого характера проблемка. Все условно, не важно что это будет - юнит, integer, real, то есть от этого можно целиком абстрагироваться. Суть такая - есть 3 (4.5.6.7.8) условных боевых единиц и у каждой есть копия. Нужно чтобы копии пошли атаковать основных героев, но так, чтобы условная копия под номером 6 не пошла атаковать основного героя под номером 6 ни в коем случае. Для примера попытался изобразить на картинке.
У кого какие мысли?

respect_gg, можно вобще вот так
  1. записываем в массив номера от 0 до N, где N это число игроков минус один, в ячейки с соответствующими номерами
  2. проходим циклом от N до 0, пусть номер итерации будет i
  3. на каждой итерации получаем случайное число R от 0 до N, Если оно совпало с i, то берем R= i+1 или R=i-1, с учетом границ
  4. меняем местами ячейки R и i
  5. если в ячейку i в результате обмена опять попало число с номером этой ячейки, делаем еще один случайный обмен (тут можно не делать дополнительную проверку на коллизию т.к. коллизия не может на этом этапе возникнуть повторно для этой ячейки)
Если я ничего не напутал - получаем на выходе массив чисел в котором числа не повторяются и не находятся в ячейках совпадающих со своим номером.
Использовать это потом - номер ячейки это один игрок, число в ячейке - другой.
Если нужен учет того что игроки могут иметь номера не идущие подряд (ливеры, компьютеры, просто игроки не использующиеся в этой системе) - нам понадобится дополнительный массив с номерами игроков, чтобы превратить номер ячейки и число в ячейке в реальный номер игрока.
`
ОЖИДАНИЕ РЕКЛАМЫ...
18
На картинке у вас каждого героя может атаковать только один другой герой, это тоже учитывается?
11
Vlod:
На картинке у вас каждого героя может атаковать только один другой герой, это тоже учитывается?
В этом и смысл. Грубо говоря они должны драться 1х1, но так, чтобы условный Горный король не стал жертвой своей же копии (то бишь другого Горного короля)
27
Создаем 3 переменные отряд. ТЕСТ_А, ТЕСТ_B, ТЕСТ_С
Предварительно в группу ТЕСТ_А включаем всех основных героев, в группу ТЕСТ_B включаем все копии.
Далее, триггер:
Hero_mechanic - это просто переменная юнита из моей карты) Можно сделать любую другую.
Загруженные файлы
11
Lord_Teo:
Создаем 3 переменные отряд. ТЕСТ_А, ТЕСТ_B, ТЕСТ_С
Предварительно в группу ТЕСТ_А включаем всех основных героев, в группу ТЕСТ_B включаем все копии.
Далее, триггер:
Hero_mechanic - это просто переменная юнита из моей карты) Можно сделать любую другую.
Я то же думал сначала, что будет просто.
Только ты не учел одного но - Кель пошел атаковать Архимага, а Архимаг Келя. А Горный король стоит и не понимает че ему делать, ведь выставлено условие - свою же копию атаковать нельзя
15
Создаём 2 группы, одна для верхней линии героев, вторая для нижней. Заносим в группы каждой линии противоположный список героев, как цели потенциальной атаки. Проверяем условия для каждого юнита и работам с его группой. Выбрать случайного героя противоположной группы, если тип юнита = типу проверяемого юнита, повторяем действие. Нашли не похожего юнита, теперь это его цель атаки. Удалили найденную цель атаки из группы. Повторяем алгоритм для всех героев.
27
respect_gg:
Я то же думал сначала, что будет просто.
Только ты не учел одного но - Кель пошел атаковать Архимага, а Архимаг Келя. А Горный король стоит и не понимает че ему делать, ведь выставлено условие - свою же копию атаковать нельзя
Не понимаю тебя. Почему он будет стоять? Проверь сам. Триггер небольшой, чтобы его повторить. Он будет атаковать случайного юнита из группы. Это ты уже позже в комментариях написал про 1 на 1. В начальном вопросе такого не было.
24
DarkLigthing, Lord_Teo, вы оба не учитываете коллизию, которая может возникнуть, если последние двое оставшихся будут одного и того же типа, что нарушает условие согласно которому копии не должны атаковать оригинал.
27
prog:
DarkLigthing, Lord_Teo, вы оба не учитываете коллизию, которая может возникнуть, если последние двое оставшихся будут одного и того же типа, что нарушает условие согласно которому копии не должны атаковать оригинал.
Какая коллизия, вы че?! Там действие: атаковать случайного! Просто будут несколько героев атаковать одного.
24
Lord_Teo, это в любом случае не решает поставленную автором вопроса задачу.
11
Lord_Teo:
prog:
DarkLigthing, Lord_Teo, вы оба не учитываете коллизию, которая может возникнуть, если последние двое оставшихся будут одного и того же типа, что нарушает условие согласно которому копии не должны атаковать оригинал.
Какая коллизия, вы че?! Там действие: атаковать случайного! Просто будут несколько героев атаковать одного.
В этом и проблема, чувак :) Должно быть примерно так же, как на картинке. Юниты были изображены лишь для простоты объяснения проблемы. В целом работа идет с ID игроков
27
prog:
Lord_Teo, это в любом случае не решает поставленную автором вопроса задачу.
Если быть внимательнее, то про 1 на 1 было только в комментарии. В первом вопросе такого условия не было

respect_gg:
В этом и проблема, чувак :) Должно быть примерно так же, как на картинке. Юниты были изображены лишь для простоты объяснения проблемы. В целом работа идет с ID игроков
Ну, надо было яснее выражаться сразу) Тогда я сдаюсь)))
11
Lord_Teo:
prog:
Lord_Teo, это в любом случае не решает поставленную автором вопроса задачу.
Если быть внимательнее, то про 1 на 1 было только в комментарии. В первом вопросе такого условия не было

respect_gg:
В этом и проблема, чувак :) Должно быть примерно так же, как на картинке. Юниты были изображены лишь для простоты объяснения проблемы. В целом работа идет с ID игроков
Ну, надо было яснее выражаться сразу) Тогда я сдаюсь)))
Я на картинке примерно это отобразил (стрелочками) и примерно описал "Нужно чтобы копии пошли атаковать основных героев, но так, чтобы условная копия под номером 6 не пошла атаковать основного героя под номером 6 ни в коем случае."
27
respect_gg:
Я на картинке примерно это отобразил (стрелочками) и примерно описал "Нужно чтобы копии пошли атаковать основных героев, но так, чтобы условная копия под номером 6 не пошла атаковать основного героя под номером 6 ни в коем случае."
Ну, так как раз это условие выполняется)) в моем триггере основа не будет атаковать свою копию ни в коем случае)
18
respect_gg:
В этом и смысл. Грубо говоря они должны драться 1х1, но так, чтобы условный Горный король не стал жертвой своей же копии (то бишь другого Горного короля)
Понятно, тогда в два этапа:
  1. Два массива длиной N - количество одинаковых пар. Идем циклом изымая пары до тех пор, пока общее количество свободных юнитов не станет 4.
  2. Далее нужно проверить, нет ли одинаковых. Если есть, тo выбираем их. Иначе просто продолжаем.
photo
Загруженные файлы
24
Понятно, тогда в два этапа:
Можно даже проще - просто ресолвить ситуацию когда в конце осталось два одинаковых, если она возникла, через обмен с другой случайной парой.

А если коллизия не возникла - то ничего и не делать.
18
Согласен с prog, проще сравнить только последнюю пару и поменять в случае совпадения
11
Vlod:
Согласен с prog, проще сравнить только последнюю пару и поменять в случае совпадения
Все делается не в пределах одного вызова функции, а через цикл. А перебираются id игроков (GetPlayerId). Возможно с юнитами было бы и проще. Но тут вроде все нормально, а потом бац, минуя все условия - и 1 игрок остается без пары
24
respect_gg, ну так кто тебе мешает сперва циклом пройтись по массиву то, а не сразу действия делать?

Еще раз повторю суть своей идеи.
  1. Сперва тасуем массив индексов так чтобы они заняли случайные позиции отличные от своих собственных. Алгоритм выстраивается так, чтобы только последняя оставшаяся пара могла быть коллизией.
  2. В конце - проверяем последнюю пару, если она является коллизией, то выбираем случайную другую пару и меняем местами.
  3. Проходим по массиву еще раз, в этот раз уже выполняя нужные действия.
11
prog:
respect_gg, ну так кто тебе мешает сперва циклом пройтись по массиву то, а не сразу действия делать?

Еще раз повторю суть своей идеи.
  1. Сперва тасуем массив индексов так чтобы они заняли случайные позиции отличные от своих собственных. Алгоритм выстраивается так, чтобы только последняя оставшаяся пара могла быть коллизией.
  2. В конце - проверяем последнюю пару, если она является коллизией, то выбираем случайную другую пару и меняем местами.
  3. Проходим по массиву еще раз, в этот раз уже выполняя нужные действия.
То то и оно, никогда не приходилось с таким дела иметь. Как грамотно составить этот самый алгоритм. Просто через рандом? - не вариант опять же. Уже тестил. Первые 2 игрока могу сразу нарваться друг на друга, а 3 не приделах окажется. То есть вот какая ситуация - Игрок (Красный) получает в соперники Игрока (Синий), а Игрок (Синий) получает в соперники Игрока (Красный). То есть уже на первых двух "прогонах" цикла возникает эта проблема. Я пробовал записывать в глобалку/хэш ID самого первого игрока, чтобы на следующем вызове функции его обойти стороной. Но все равно все "не ладно"
24
respect_gg, можно вобще вот так
  1. записываем в массив номера от 0 до N, где N это число игроков минус один, в ячейки с соответствующими номерами
  2. проходим циклом от N до 0, пусть номер итерации будет i
  3. на каждой итерации получаем случайное число R от 0 до N, Если оно совпало с i, то берем R= i+1 или R=i-1, с учетом границ
  4. меняем местами ячейки R и i
  5. если в ячейку i в результате обмена опять попало число с номером этой ячейки, делаем еще один случайный обмен (тут можно не делать дополнительную проверку на коллизию т.к. коллизия не может на этом этапе возникнуть повторно для этой ячейки)
Если я ничего не напутал - получаем на выходе массив чисел в котором числа не повторяются и не находятся в ячейках совпадающих со своим номером.
Использовать это потом - номер ячейки это один игрок, число в ячейке - другой.
Если нужен учет того что игроки могут иметь номера не идущие подряд (ливеры, компьютеры, просто игроки не использующиеся в этой системе) - нам понадобится дополнительный массив с номерами игроков, чтобы превратить номер ячейки и число в ячейке в реальный номер игрока.
Принятый ответ
11
prog:
respect_gg, можно вобще вот так
  1. записываем в массив номера от 0 до N где N это число игроков минус один в ячейки с соответствующими номерами
  2. проходим циклом от N до 0, пусть номер итерации будет i
  3. на каждой итерации получаем случайное число R от 0 до N, Если оно совпало с i, то берем i+1 или i-1, с учетом границ
  4. меняем местами ячейки R и i
  5. если в ячейку i в результате обмена опять попало число с номером этой ячейки, делаем еще один случайный обмен (тут можно не делать дополнительную проверку на коллизию т.к. коллизия не может на этом этапе возникнуть повторно для этой ячейки)
Если я ничего не напутал - получаем на выходе массив чисел в котором числа не повторяются и не находятся в ячейках совпадающих со своим номером.
Использовать это потом - номер ячейки это один игрок, число в ячейке - другой.
Если нужен учет того что игроки могут иметь номера не идущие подряд (ливеры, компьютеры, просто игроки не использующиеся в этой системе) - нам понадобится дополнительный массив с номерами игроков, чтобы превратить номер ячейки и число в ячейке в реальный номер игрока.
Вот в том то и дело - ливеры и т.д. Я хочу это организовать изначально отталкиваясь от кол-ва активных игроков на момент вызова функции и прогоняю всех этих игроков циклом, подбирая им пару. Но не могу понять как конкретно сопоставлять какие либо данные. Я пытался хранить в глобалке последний полученный id, я пробовал на полученный id записывать значение в хэш-таблицу, где ключом являлся опять же этот id (все для дальнейших проверок внутри цикла).
Я помню поднималась подобная тема здесь (еще на старом форуме), но я 2 вечера пытался найти эту тему, но так и не нашел. Но там был способ намного проще и реализован был именно так же.
Я думал возможно кто то вспомнит эту ситуацию.
24
respect_gg, я уже описал как решить проблему ливеров...
Нам всего-то надо знать сколько живых игроков, это будет N.
Пусть массив с номерами будет Numbers. Пока оставим его пустым.
Берем второй массив, назовем его Index. В Index записываем айдишники живых игроков, сколько бы их ни было, заодно в процессе вычисляем N и заполняем массив Numbers порядковыми номерами от 0 до N.
Выполняем алгоритм из поста выше.
Результат выполнения алгоритма используем так - проходим циклом от 0 до N, с номером итерации j
Index[Number[j]] - один игрок
Index[j] - второй игрок
11
prog:
respect_gg, я уже описал как решить проблему ливеров...
Нам всего-то надо знать сколько живых игроков, это будет N.
Пусть массив с номерами будет Numbers. Пока оставим его пустым.
Берем второй массив, назовем его Index. В Index записываем айдишники живых игроков, сколько бы их ни было, заодно в процессе вычисляем N и заполняем массив Numbers порядковыми номерами от 0 до N.
Выполняем алгоритм из поста выше.
Результат выполнения алгоритма используем так - проходим циклом от 0 до N, с номером итерации j
Index[Number[j]] - один игрок
Index[j] - второй игрок
скинул чуваку, который в с++ шарит, он сказал, что нужен 2 мерный массив, а в идеале якобы 3 мерный, типа даже если изначально, как ты выше писал, сместить N на минус 1 шаг, то получится ровно так же, то есть типа коллизия произойдет, но просто на другой ячейке.
Уже фиг знает, 2 вечер подряд голову ломаю :))))
24
respect_gg, алгоритм рабочий, хоть и требует одной маленькой доработки перед финальным использованием, а твой чувак не шарит и, похоже, ничерта не понял в алгоритме, начиная с того, зачем в нем нужны смещения. Первое "смещение" - N = кол-во игроков -1 нужно потому как нумерация от 0 до N включительно. Второе смещение +1 или -1 на некоторых итерациях нужно чтобы рандом не выдал ту-же ячейку в которой алгоритм находится в текущей итерации, это не более чем дешевое исключение ячейки из диапазона рандома.
Впрочем, поскольку ты даже не попытался реализовать этот алгоритм на практике или разобраться в принципах его работы, а сразу заклеймил его не рабочим - я умываю руки. Это будет мое последнее сообщение в этой теме.
Вот тебе алгоритм для твоего уровня, если нормальный не получается осилить:
Вместо перемешивания сдвигай всех на одно и то же случайное число один раз, с сохранением порядка. Это не так круто как полное перемешивание, но никто и не заметит если сдвиг будет рандомный каждый раз. Естественно, с использованием двух массивов, как я описал выше, чтобы исключить ливеров. Если и до этого не допрешь сам - спроси своего друга якобы шарящего в C++, может хоть с этим он справится.
На всякий случай даже подробно разжую:
Перебираешь игроков, тех кто жив записываешь в массив Index. В результате на выходе получаешь массив, в котором в первой ячейке номер первого живого игрока, во второй - номер второго живого игрока - не и важно какие это игроки по номеру - первый живой может быть пятым, а второй восьмым, тогда первая ячейка будет равна пяти, вторая восьми. Так-же нужно посчитать сколько всего их, живых игроков, это тоже удобно сделать тут, пусть это будет число P. А N, как и раньше, будет P-1.
Каким-угодно способом заполняешь массив Numbers числами от 0 и до N, так чтобы в каждой ячейке изначально был её номер.
Потом один раз берешь случайное число R, оно может быть любым, но важно чтобы оно не было кратным P.
Потом прибавляешь к каждой ячейке Numbers это число - R. Еще раз подчеркиваю - R для всех ячеек одинаковое.
Если в результате число в ячейке больше или равно P, то вычитаешь из него P пока оно не станет меньше P.
На этом заканчиваешь работу с массивом Numbers.
Теперь можно как-то использовать полученный массив, а именно:
Циклом от 0 до N проходим с индексом j
в цикле переменной k присваиваем Number[j]
и получаем номера для двух игроков из массива Index
Index[k] и Index[j]
Этот алгоритм тоже с подвохом, просьба тем кто его заметил не раскрывать карты раньше времени
11
prog:
respect_gg, алгоритм рабочий, хоть и требует одной маленькой доработки перед финальным использованием, а твой чувак не шарит и, похоже, ничерта не понял в алгоритме, начиная с того, зачем в нем нужны смещения. Первое "смещение" - N = кол-во игроков -1 нужно потому как нумерация от 0 до N включительно. Второе смещение +1 или -1 на некоторых итерациях нужно чтобы рандом не выдал ту-же ячейку в которой алгоритм находится в текущей итерации, это не более чем дешевое исключение ячейки из диапазона рандома.
Впрочем, поскольку ты даже не попытался реализовать этот алгоритм на практике или разобраться в принципах его работы, а сразу заклеймил его не рабочим - я умываю руки. Это будет мое последнее сообщение в этой теме.
Вот тебе алгоритм для твоего уровня, если нормальный не получается осилить:
Вместо перемешивания сдвигай всех на одно и то же случайное число один раз, с сохранением порядка. Это не так круто как полное перемешивание, но никто и не заметит если сдвиг будет рандомный каждый раз. Естественно, с использованием двух массивов, как я описал выше, чтобы исключить ливеров. Если и до этого не допрешь сам - спроси своего друга якобы шарящего в C++, может хоть с этим он справится.
На всякий случай даже подробно разжую:
Перебираешь игроков, тех кто жив записываешь в массив Index. В результате на выходе получаешь массив, в котором в первой ячейке номер первого живого игрока, во второй - номер второго живого игрока - не и важно какие это игроки по номеру - первый живой может быть пятым, а второй восьмым, тогда первая ячейка будет равна пяти, вторая восьми. Так-же нужно посчитать сколько всего их, живых игроков, это тоже удобно сделать тут, пусть это будет число P. А N, как и раньше, будет P-1.
Каким-угодно способом заполняешь массив Numbers числами от 0 и до N, так чтобы в каждой ячейке изначально был её номер.
Потом один раз берешь случайное число R, оно может быть любым, но важно чтобы оно не было кратным P.
Потом прибавляешь к каждой ячейке Numbers это число - R. Еще раз подчеркиваю - R для всех ячеек одинаковое.
Если в результате число в ячейке больше или равно P, то вычитаешь из него P пока оно не станет меньше P.
На этом заканчиваешь работу с массивом Numbers.
Теперь можно как-то использовать полученный массив, а именно:
Циклом от 0 до N проходим с индексом j
в цикле переменной k присваиваем Number[j]
и получаем номера для двух игроков из массива Index
Index[k] и Index[j]
Этот алгоритм тоже с подвохом, просьба тем кто его заметил не раскрывать карты раньше времени
я не в коем случае никого не хочу принизить, я лишь пытаюсь понять как это должно работать. Потому что в целом у меня получается то, что я задумал (через цикл), но в один прекрасный (непонятный) момент он может повести себя странно. Он может до 37 раз (вручную считал) выдавать пары идеально, а на 38 раз весь цикл рушится и приходится заново его запускать. Причем цикл рушится на случайном id, уже проверял - было и 1, и 6, и 4, и 2. То есть как будто хаотично. Хотя до этого все проходит идеально.
Вот ссылка на видео, специально записал, дабы не говорили, что я ничего не пытаюсь сам делать :) youtu.be/KT26LWMI_LY
ПС ESC (то что на видео) это по сути генерация всего, чтобы без лишних вопросов :)

Вроде получилось - 500 (ровно) нажатий и все четко и ровно youtu.be/ZikqrDRgNYs
А нужно было всего лишь в GetRandomInt(0, MaxPlayers) поменять местами MaxPlayers и 0 и хрен пойми в чем разница :)
Чтобы оставить комментарий, пожалуйста, войдите на сайт.