В общем такого характера проблемка. Все условно, не важно что это будет - юнит, 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 в результате обмена опять попало число с номером этой ячейки, делаем еще один случайный обмен (тут можно не делать дополнительную проверку на коллизию т.к. коллизия не может на этом этапе возникнуть повторно для этой ячейки)
Если я ничего не напутал - получаем на выходе массив чисел в котором числа не повторяются и не находятся в ячейках совпадающих со своим номером.
Использовать это потом - номер ячейки это один игрок, число в ячейке - другой.
Если нужен учет того что игроки могут иметь номера не идущие подряд (ливеры, компьютеры, просто игроки не использующиеся в этой системе) - нам понадобится дополнительный массив с номерами игроков, чтобы превратить номер ячейки и число в ячейке в реальный номер игрока.
`
ОЖИДАНИЕ РЕКЛАМЫ...

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

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

Еще раз повторю суть своей идеи.
  1. Сперва тасуем массив индексов так чтобы они заняли случайные позиции отличные от своих собственных. Алгоритм выстраивается так, чтобы только последняя оставшаяся пара могла быть коллизией.
  2. В конце - проверяем последнюю пару, если она является коллизией, то выбираем случайную другую пару и меняем местами.
  3. Проходим по массиву еще раз, в этот раз уже выполняя нужные действия.
То то и оно, никогда не приходилось с таким дела иметь. Как грамотно составить этот самый алгоритм. Просто через рандом? - не вариант опять же. Уже тестил. Первые 2 игрока могу сразу нарваться друг на друга, а 3 не приделах окажется. То есть вот какая ситуация - Игрок (Красный) получает в соперники Игрока (Синий), а Игрок (Синий) получает в соперники Игрока (Красный). То есть уже на первых двух "прогонах" цикла возникает эта проблема. Я пробовал записывать в глобалку/хэш ID самого первого игрока, чтобы на следующем вызове функции его обойти стороной. Но все равно все "не ладно"
0
24
4 года назад
Отредактирован prog
0
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 в результате обмена опять попало число с номером этой ячейки, делаем еще один случайный обмен (тут можно не делать дополнительную проверку на коллизию т.к. коллизия не может на этом этапе возникнуть повторно для этой ячейки)
Если я ничего не напутал - получаем на выходе массив чисел в котором числа не повторяются и не находятся в ячейках совпадающих со своим номером.
Использовать это потом - номер ячейки это один игрок, число в ячейке - другой.
Если нужен учет того что игроки могут иметь номера не идущие подряд (ливеры, компьютеры, просто игроки не использующиеся в этой системе) - нам понадобится дополнительный массив с номерами игроков, чтобы превратить номер ячейки и число в ячейке в реальный номер игрока.
Принятый ответ
0
11
4 года назад
0
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 вечера пытался найти эту тему, но так и не нашел. Но там был способ намного проще и реализован был именно так же.
Я думал возможно кто то вспомнит эту ситуацию.
0
24
4 года назад
0
respect_gg, я уже описал как решить проблему ливеров...
Нам всего-то надо знать сколько живых игроков, это будет N.
Пусть массив с номерами будет Numbers. Пока оставим его пустым.
Берем второй массив, назовем его Index. В Index записываем айдишники живых игроков, сколько бы их ни было, заодно в процессе вычисляем N и заполняем массив Numbers порядковыми номерами от 0 до N.
Выполняем алгоритм из поста выше.
Результат выполнения алгоритма используем так - проходим циклом от 0 до N, с номером итерации j
Index[Number[j]] - один игрок
Index[j] - второй игрок
0
11
4 года назад
0
prog:
respect_gg, я уже описал как решить проблему ливеров...
Нам всего-то надо знать сколько живых игроков, это будет N.
Пусть массив с номерами будет Numbers. Пока оставим его пустым.
Берем второй массив, назовем его Index. В Index записываем айдишники живых игроков, сколько бы их ни было, заодно в процессе вычисляем N и заполняем массив Numbers порядковыми номерами от 0 до N.
Выполняем алгоритм из поста выше.
Результат выполнения алгоритма используем так - проходим циклом от 0 до N, с номером итерации j
Index[Number[j]] - один игрок
Index[j] - второй игрок
скинул чуваку, который в с++ шарит, он сказал, что нужен 2 мерный массив, а в идеале якобы 3 мерный, типа даже если изначально, как ты выше писал, сместить N на минус 1 шаг, то получится ровно так же, то есть типа коллизия произойдет, но просто на другой ячейке.
Уже фиг знает, 2 вечер подряд голову ломаю :))))
0
24
4 года назад
Отредактирован prog
0
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]
Этот алгоритм тоже с подвохом, просьба тем кто его заметил не раскрывать карты раньше времени
0
11
4 года назад
0
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 и хрен пойми в чем разница :)
0
17
4 года назад
0
Присвой всем число и через логическую переменную с условием, запрети герою с номером атаковать копию или того кого уже атакуют(если это нужно) Можно не число, а любое значение для сканирования героя например - цвет. Описание конечно размыто и условно, но надеюсь мысль была понятна.
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.