Устраните дублирующиеся проблемы с помощью циклов и словарей - PullRequest
0 голосов
/ 22 октября 2018

У меня есть список предметов, которые определяются тем, что игрок вводит в несколько полей ввода, но для примера рассмотрим, что он содержит «a», «b», «c», «d»и "е".Затем они сортируются в словарь со списком чисел в качестве значений (неважно).Затем я рандомизирую словарь с двумя различными переменными рандомизатора (i и j), чтобы взять два объекта из словаря и отобразить их на экране, чтобы игрок мог нажимать различные связанные кнопки.Это продолжается до тех пор, пока не пройдет x ходов. Основная проблема , с которой я столкнулся, заключается в предотвращении появления полудубликатов, таких как "ab" и "ba".

Я попытался ввести вставив как рандомизированную пару, так и ееполудублировать в другой словарь, а затем использовать операторы цикла while, предотвращая появление пар из этого словаря.К сожалению, это не сработало.

Ниже мой код.

public void Start() {
    finalList = new Dictionary<string, int>();
    for (index = 0; index < allNumbers; index++)
    {
        finalList.Add(itemList[index], valueList[index]);
        Debug.Log(finalList[index.ToString()]);
    }
}
public void Update() {
    choose();
}

public void choose() {
    duplicates = new Dictionary<string, string>();
    duplicates.Clear();
    while (rounds < insertNum) {

        key = "(" + itemList[i].ToString() + " " + itemList[j].ToString() + ")";
        reverseKey = "(" + itemList[j].ToString() + " " + itemList[i].ToString() + ")";

        while (j == i || (duplicates.ContainsKey(key) || duplicates.ContainsKey(reverseKey))) {
            i = UnityEngine.Random.Range(0, allNumbers - 1);
            j = UnityEngine.Random.Range(0, allNumbers - 1);
            key = "(" + itemList[i].ToString() + " " + itemList[j].ToString() + ")";
            reverseKey = "(" + itemList[j].ToString() + " " + itemList[i].ToString() + ")";
            Debug.Log("(new keys " + key + ", " + reverseKey + ")");
            //break;
            } while (j == i || (duplicates.ContainsKey(key) && duplicates.ContainsKey(reverseKey)))
            {
                i = UnityEngine.Random.Range(0, allNumbers - 1);
                j = UnityEngine.Random.Range(0, allNumbers - 1);
                key = "(" + itemList[i].ToString() + " " + itemList[j].ToString() + ")";
                reverseKey = "(" + itemList[j].ToString() + " " + itemList[i].ToString() + ")";
                Debug.Log("(new keys " + key + ", " + reverseKey + ")");
            }while (j == i && (duplicates.ContainsKey(key) || dupes.ContainsKey(reverseKey))) {
            i = UnityEngine.Random.Range(0, allNumbers - 1);
            j = UnityEngine.Random.Range(0, allNumbers - 1);
            key = "(" + itemList[i].ToString() + " " + itemList[j].ToString() + ")";
            reverseKey = "(" + itemList[j].ToString() + " " + itemList[i].ToString() + ")";
            Debug.Log("(new keys " + key + ", " + reverseKey + ")");

        }
        while (j == i && (duplicates.ContainsKey(key) && duplicates.ContainsKey(reverseKey))) {
            i = UnityEngine.Random.Range(0, allNumbers - 1);
            j = UnityEngine.Random.Range(0, allNumbers - 1);
            key = "(" + itemList[i].ToString() + " " + itemList[j].ToString() + ")";
            reverseKey = "(" + itemList[j].ToString() + " " + itemList[i].ToString() + ")";
            Debug.Log("(new keys " + key + ", " + reverseKey + ")");
        }
        duplicates.Add(key, "1"); // the one is just a filler variable
        duplicates.Add(reverseKey, "1");
        if (buttonOneBool) { //this is in another script, ignore
            finalList[itemList[i].ToString()] = valueList[i] += 2;
            finalList[itemList[j].ToString()] = valueList[j] -= 2;
            i = UnityEngine.Random.Range(0, n - 1);
            j = UnityEngine.Random.Range(0, n - 1);
        } else if (buttonTwoBool) {
            finalList[itemList[i].ToString()] = valueList[i] -= 2;
            finalList[itemList[j].ToString()] = valueList[j] += 2;
            i = UnityEngine.Random.Range(0, n - 1);
            j = UnityEngine.Random.Range(0, n - 1);
        } else if (buttonThreeBool) {
            finalList[itemList[i].ToString()] = valueList[i] -= 1;
            finalList[itemList[j].ToString()] = valueList[j] -= 1;
            i = UnityEngine.Random.Range(0, n - 1);
            j = UnityEngine.Random.Range(0, n - 1);
        } else if (buttonFourBool) {
            finalList[itemList[i].ToString()] = valueList[i] += 1;
            finalList[itemList[j].ToString()] = valueList[j] += 1;
            i = UnityEngine.Random.Range(0, n - 1);
            j = UnityEngine.Random.Range(0, n - 1);
        }
        break;
    } 

Ответы [ 2 ]

0 голосов
/ 22 октября 2018

Вы можете получить два случайных индекса в списке, используя код ниже.Код использует целое число в качестве типа списка и будет работать с любым типом.

List<int> randomList = itemList.Select((x, i) => new { index = i, rand = rand.Next() }).OrderBy(x => x.rand).Select(x => x.index).ToList();

Тогда в список попадают два случайных индекса: randomList [0] и randomList [1].Код назначает случайное число каждому индексу i списка.Чтобы получить два элемента из списка, используйте itemList [randomList [0]] и itemList [randomList [1]].Код предполагает, что в исходном списке есть по крайней мере два элемента ItemList [].

Если в исходном списке есть дубликаты, вам нужно использовать Distinct (), как показано в приведенном ниже коде

        List<int> distinctList = itemList.Distinct().ToList();
        List<int> randomList = distinctList.Select((x, i) => new { index = i, rand = rand.Next() }).OrderBy(x => x.rand).Select(x => x.index).ToList();
0 голосов
/ 22 октября 2018

Самый простой способ исправить это - гарантировать i < j.При выборе новых i и j, таких как:

i = UnityEngine.Random.Range(min, max); j = UnityEngine.Random.Range(min, max);

Вместо этого сделайте это:

i = UnityEngine.Random.Range(min, max - 1); j = UnityEngine.Random.Range(i + 1, max);

Это исключает возможностьвыбора «зеркального отображения» предыдущего случая, а также избегая случая «i == j».

После этих модификаций ваша функция choose () должна выглядеть примерно так:

    public void choose()
{
    duplicates = new HashSet<string>();
    while (rounds < insertNum)
    {
        key = "(" + itemList[i].ToString() + " " + itemList[j].ToString() + ")";
        while (duplicates.Contains(key))
        {
            i = UnityEngine.Random.Range(0, allNumbers - 2);
            j = UnityEngine.Random.Range(i + 1, allNumbers - 1);
            key = "(" + itemList[i].ToString() + " " + itemList[j].ToString() + ")";
        }
        duplicates.Add(key); // the one is just a filler variable

        if (buttonOneBool) { //bool definitions are in another script, ignore
            finalList[itemList[i].ToString()] = valueList[i] += 2;
            finalList[itemList[j].ToString()] = valueList[j] -= 2;
            i = UnityEngine.Random.Range(0, n - 1);
            j = UnityEngine.Random.Range(0, n - 1);
        } else if (buttonTwoBool) {
            finalList[itemList[i].ToString()] = valueList[i] -= 2;
            finalList[itemList[j].ToString()] = valueList[j] += 2;
            i = UnityEngine.Random.Range(0, n - 1);
            j = UnityEngine.Random.Range(0, n - 1);
        } else if (buttonThreeBool) {
            finalList[itemList[i].ToString()] = valueList[i] -= 1;
            finalList[itemList[j].ToString()] = valueList[j] -= 1;
            i = UnityEngine.Random.Range(0, n - 1);
            j = UnityEngine.Random.Range(0, n - 1);
        } else if (buttonFourBool) {
            finalList[itemList[i].ToString()] = valueList[i] += 1;
            finalList[itemList[j].ToString()] = valueList[j] += 1;
            i = UnityEngine.Random.Range(0, n - 1);
            j = UnityEngine.Random.Range(0, n - 1);
        }
        break;
    }
}
...