рекурсивная обработка списка, кажется, меняет список на более высоких уровнях - PullRequest
0 голосов
/ 08 апреля 2020

Я пытаюсь написать алгоритм парного соревнования, чтобы не играть дважды одного и того же игрока

, поэтому у нас есть список игроков

мы берем первого игрока, затем первого игрока, которого они имеют не воспроизводится

удалить это из списка

отправить оставшийся список для повторной обработки

, если последняя пара не может воспроизвести, рекурсия должна развернуться, и первый игрок получит соответствие против следующего игрока, которого они не сыграли, и мы снова go.

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

Таким образом, когда повторение раскручивается, список игроков уменьшается до 2 пунктов, а не ожидаемых 4 или 6. Это похоже на то, что список передается по ссылке, а не по значению.

есть мысли?

редактировать ***

не столько список, который передается по ссылке, но список (игроков), который меняется каждый раз, когда профи называется cedure, поэтому мы заканчиваем первую итерацию процедуры (в которой должен быть список из 6 игроков), используя список из 2 игроков, когда рекурсия раскручивается ***

Я запихнул весь код в здесь (вместе с кодом настройки списка тестов)

using System;
using System.Collections.Generic;
using System.Runtime.ConstrainedExecution;

namespace CPair
{
    class Program
    {
        static void Main(string[] args)
        {
            //create players
            List<int> alist = new List<int>() { 2 };
            var a = new Player(1, "a", "wk", alist, 10);

            List<int> blist = new List<int>() { 1 };
            var b = new Player(2, "b", "wa", blist, 9);

            List<int> clist = new List<int>() {  };
            var c = new Player(3, "c", "bc", clist, 8);

            List<int> dlist = new List<int>() {  };
            var d = new Player(4, "d", "wk", dlist, 7);

            List<int> elist = new List<int>() {  };
            var e = new Player(5, "e", "bc", elist, 5);

            List<int> flist = new List<int>() {  };
            var f = new Player(6, "f", "ab", flist, 3);

            List<Player> PlayList = new List<Player>();
            PlayList.Add(a);
            PlayList.Add(b);
            PlayList.Add(c);
            PlayList.Add(d);
            PlayList.Add(e);
            PlayList.Add(f);

            PlayList.Sort((p, q) => p.Points.CompareTo(q.Points));

            foreach (Player p in PlayList)
            {
                Console.WriteLine(p.PlayerName);
            }

            List<Player> paired = new List<Player>();
            paired = pairing(PlayList);

            foreach (Player r in paired)
            {
                Console.WriteLine(r.PlayerName);
            }
        }

        static List<Player> pairing(List<Player> players)
        {
            List<Player> pairingList = new List<Player>();
            int n = 1;
            bool failed = true;
            List<Player> returnedList = new List<Player>();

            while ((failed) && n <= players.Count - 1)
            {
                if (PairIsGood(players[0], players[n], 0))
                {
                    Player p1 = new Player();
                    p1 = players[0];
                    Player p2 = new Player();
                    p2 = players[n];

                    if (players.Count <= 2)
                    {
                        returnedList.Add(p1);
                        returnedList.Add(p2);
                        failed = false;
                    }
                    else
                    {
                        List<Player> nextPairs = new List<Player>();
                        nextPairs = players;
                        nextPairs.RemoveAt(0);
                        nextPairs.RemoveAt(n-1);

                        returnedList = pairing(nextPairs);
                        Console.WriteLine(players.Count.ToString());
                        Console.WriteLine(nextPairs.Count.ToString());

                        if (returnedList.Count == 0)
                        {
                            failed = true;
                            n++;
                        }
                        else
                        {
                            returnedList.Add(p1);
                            returnedList.Add(p2);
                            failed = false;
                        }
                    }
                }
                else
                {
                    n++;
                }
            } 

            return returnedList;
        }

       static bool PairIsGood(Player p1, Player p2, int round)
       {
            bool good = true;

            foreach (int op in p1.OpList)
            {
                if (op == p2.PlayerID)
                {
                    good = false;
                }
            }

            return good;
        }
    }
}

1 Ответ

0 голосов
/ 09 апреля 2020

Вот ваша проблема:

List<Player> nextPairs = new List<Player>();
nextPairs = players;
nextPairs.RemoveAt(0);
nextPairs.RemoveAt(n-1);

Вы создаете новый List<Player> и назначаете его на nextPairs

Затем вы фактически выбрасываете этот новый список и вместо этого назначаете * От 1008 * до players.

nextPairs и players теперь оба ссылаются на один и тот же список, а удаление из nextPairs также удалит из players, так как они в одном списке.

Take посмотрите на Array.Copy(), если вам нужна настоящая независимая копия.

В качестве отступления, я вижу, что вы делаете тот же избыточный шаблон создания здесь:

Player p1 = new Player();
p1 = players[0];
Player p2 = new Player();
p2 = players[n];

Это должно быть просто

Player p1 = players[0];
Player p2 = players[n];

Я подозреваю, что вам нужно немного прочитать об объектах и ​​ссылках и о том, как они работают.

...