Как я могу предотвратить переполнение памяти и повысить производительность в настольной игре с множеством решений - PullRequest
0 голосов
/ 06 ноября 2019

У меня есть следующая матрица:

0XXXX XXXXX XX @ XX XXXXX XXXXX

Это представление настольной игры. 0 - красная пешка. Х - нормальная пешка. @ - это пустое место на доске. Вы можете просто переместить пешку (красную или нормальную), перепрыгивая через другую пешку (не красную). Это можно сделать горизонтально, вертикально в любом направлении.

Игра заканчивается, когда у вас есть только красная пешка посередине и других пешек не осталось.

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

Сначала я сделал состояние доски (свободный, занятый, красный) (перечисления)

Затем я сделал доску с матричным состоянием доски [,] у этого есть два конструктора ... Один с игрой в качестве параметра, другой с доской. Конечно, есть свойство родительской платы.

Итак ... когда игра является параметром, она только начинается, я генерирую матрицу. Когда доска является параметром, я просто пробегаю по матрице и копирую значения в новое.

У меня есть функция 'losOp' (MakeSolution). Я запускаю это с первой созданной доски.

Если эта доска не указана как 'nosolution' (позже), эта генерирует все возможные новые доски (делая каждый возможный шаг с каждой возможной пешкой). Тогда все эти решения отправляются в стек. Оттуда я снова и снова вызываю функцию «losOp», пока в стеке больше нет решений. Или в параметрических решениях в классе Board.

Когда Board не является решением, я звоню родителю, чтобы удалить меня из моих решений. Если у моего родителя больше не осталось решений, он вызывает своего родителя, чтобы удалить его тоже ...

Но каждое решение, которое не является решением, заносится в список игр noSolutions (в виде матрицы), поэтомумы можем проверить, нужно ли нам вычислять эту плату.

Но .... Это просто продолжает работать .... Или у меня переполнение памяти ...

Яautodidact, и впервые я работаю с потоками, пытаясь асинхронно, но это также дает мне переполнение ошибки ...

Я действительно даже не знаю, есть ли у этой вещи решение ...

Класс Bordvakjes - это просто объект с enum vrij, bezet, rood (свободный, занятый, красный)

Я бегу из формы, это просто начало новой игры

public class Game
    {
        public Form1 TheForm;
        public Bord Start;
//Onoplosbaar = no solutions
        public List<Bordvak[,]> Onoplosbaar = new List<Bordvak[,]>();

        public Game(Form1 form)
        {
            Onoplosbaar = new List<Bordvak[,]>();
            Start = new Bord(this, form);

        }
    }
public class Bord
    {
        //not needed
        Form1 form;
        //game running
        Game theGame;
        //current board setup
        Bordvak[,] Vakjes;
        //current round
        int Beurt = 0;
        //not needed
        int formBeurt = 0;
        //will list all possible solutions for this board
        public List<Bord> MijnOplossingen;
        //get txt with represent board easily instead of matrix
        public string afbeelding;
        //not needed
        public int FormBeurt { get { return formBeurt; } set { formBeurt = value; if (MyParent != null) { MyParent.FormBeurt = value; MyParent.form.Beurt = value; } else { form.setValue(value); } } }
        //board from where this board occurred
        public Bord MyParent { get; set; }
        /// <summary>
        /// I'm a solution of a previous board
        /// </summary>
        /// <param name="parent"></param>
        /// 
        public Bord(Bord parent)
        {
            theGame = parent.theGame;
            //form in fact is unessecary, is already in game
            form = parent.form;
            Vakjes = new Bordvak[5, 5];
            for (int rij = 0; rij < 5; rij++)
            {
                for (int col = 0; col < 5; col++)
                {
                    Vakjes[rij, col] = new Bordvak(parent.Vakjes[rij, col].MyStatus);
                }
            }
                MyParent = parent;
                Beurt = parent.Beurt + 1;


            //tried for async but still got error overflow
            //that's why now with stack
            //code still ok i presume

                Form1.setPointer pointer = parent.form.setValue;
                pointer.Invoke(Beurt);
                Application.DoEvents();


        }

        /// <summary>
        /// Im the first board to start, put matrix
        /// </summary>
        public Bord(Game game, Form1 _form)
        {
            theGame = game;
            form=_form;
            form.Show();
            Application.DoEvents();
            Vakjes = new Bordvak[5,5];
            for (int rij = 0; rij < 5; rij++)
            {
                for (int col = 0; col < 5; col++)
                {
                    if (rij == 0 && col == 0)
                        Vakjes[0, 0] = new Bordvak(Bordvak.Status.rood);
                    if (rij == 2 && col == 2)
                        Vakjes[2, 2] = new Bordvak(Bordvak.Status.vrij);
                    //is this the best way ????
                    if (!(rij == 0 && col == 0) && !(rij == 2 && col == 2))
                        Vakjes[rij, col] = new Bordvak(Bordvak.Status.bezet);
                }
            }

            LosOp();
        }

        /// <summary>
        /// Returns true if this board is the end solution
        /// it also generates the string to show the board
        /// instead of checking the matrix
        /// </summary>
        /// <param name="afbeelding"></param>
        /// <returns></returns>
        public bool Done(ref string afbeelding)
        {
            bool done = true;

            for (int rij = 0; rij < 5; rij++)
            {
                for (int col = 0; col < 5; col++)
                {

                        if (Vakjes[rij, col].MyStatus == Bordvak.Status.bezet)
                        {

                                done = false;

                            afbeelding += "X";
                        }else
                        {
                            if (Vakjes[rij, col].MyStatus == Bordvak.Status.rood)
                            {
                                afbeelding += "O";

                            }
                            else
                            {
                                afbeelding += "@";
                            }
                        }

                }
                afbeelding += "\n";
            }
            if (done)
                if (Vakjes[2, 2].MyStatus == Bordvak.Status.rood)
                    done = true;
                else
                    done = false;
            return done;
        }

        /// <summary>
        /// Check if this is the end solution
        /// if not, do all possible moves
        /// 
        /// </summary>
        public void LosOp()
        {
            afbeelding = "";
            if (Done(ref afbeelding))
            {
                MessageBox.Show(afbeelding);
                return;
            }

            //do all possible moves
            MijnOplossingen = Oplossingen();
            //if i have solutions
            if (MijnOplossingen.Count>0)
            {

                int start = MijnOplossingen.Count - 1;
                //loop over every solution
                for (int i = start; i > 0; i--)
                {
                    //put solution in stack
                    Stack<Bord> stack = new Stack<Bord>();
                    stack.Push(MijnOplossingen[i]);

                    //loop all solutions in stack
                    while (stack.Count > 0)
                    {
                        Bord current = stack.Pop();
                        //if this board isn't handled yet,handle
                        if (!theGame.Onoplosbaar.Contains(current.Vakjes))
                        { 
                            //check solutions (this fuction)
                            current.LosOp();
                            //put every solution back in stack
                        foreach (Bord bord in current.MijnOplossingen)
                        {
                            stack.Push(bord);
                        }
                        }
                    }
                    //async doesnt work... error overflow
                       // Task.Factory.StartNew(MijnOplossingen[i].LosOp);

                    //we made af move
                        form.Beurt = Beurt;
                    //update form
                        Application.DoEvents();

                }//go back to stack


            }
            else //there are no solutions
            {
                //remove me from my parent's solutions
                MyParent.RemoveMe(this);
            }
        }

        public void RemoveMe(Bord me)
        {
            //i wasn't a solution, put me in memory "unsolved"
            theGame.Onoplosbaar.Add(me.Vakjes);
            //remove move from possible solutions
            MijnOplossingen.Remove(me);
            //if i don't have other solutions,
            //remove me from my parent's parent too..
            if (MijnOplossingen.Count == 0)
                MyParent.RemoveMe(this);
        }
        public List<Bord> Oplossingen()
        {
            //get all solutions,
            //check below, above, left and right
            List<Bord> oplossingen = new List<Bord>();
            for (int rij = 0; rij < 5; rij++)
            {
                for (int col = 0; col < 5; col++)
                {
                    //spring naar beneden
                    if (rij <= 2)
                    {
                        //als ik pion of rood ben
                        if ((Vakjes[rij, col].MyStatus == Bordvak.Status.bezet || Vakjes[rij, col].MyStatus == Bordvak.Status.rood))
                        {
                            if (Vakjes[rij + 1, col].MyStatus == Bordvak.Status.bezet && Vakjes[rij + 2, col].MyStatus == Bordvak.Status.vrij)
                            {
                                Bord bord = new Bord(this);  
                                bord.Vakjes[rij + 1, col].MyStatus = Bordvak.Status.vrij;
                                bord.Vakjes[rij + 2, col].MyStatus = Vakjes[rij, col].MyStatus;
                                bord.Vakjes[rij, col].MyStatus = Bordvak.Status.vrij;
                                oplossingen.Add(bord);
                            }
                        }
                    }

                    //spring naar boven
                    if (rij >= 2)
                    {
                        //als ik pion of rood ben
                        if ((Vakjes[rij, col].MyStatus == Bordvak.Status.bezet || Vakjes[rij, col].MyStatus == Bordvak.Status.rood))
                        {
                            if (Vakjes[rij - 1, col].MyStatus == Bordvak.Status.bezet && Vakjes[rij - 2, col].MyStatus == Bordvak.Status.vrij)
                            {
                                Bord bord = new Bord(this);

                                bord.Vakjes[rij - 1, col].MyStatus = Bordvak.Status.vrij;
                                bord.Vakjes[rij - 2, col].MyStatus = Vakjes[rij, col].MyStatus;
                                bord.Vakjes[rij, col].MyStatus = Bordvak.Status.vrij;
                                oplossingen.Add(bord);
                            }
                        }
                    }
                    //spring naar link
                    if (col >= 2)
                    {
                        //als ik pion of rood ben
                        if ((Vakjes[rij, col].MyStatus == Bordvak.Status.bezet || Vakjes[rij, col].MyStatus == Bordvak.Status.rood))
                        {
                            if (Vakjes[rij, col - 1].MyStatus == Bordvak.Status.bezet && Vakjes[rij, col - 2].MyStatus == Bordvak.Status.vrij)
                            {
                                Bord bord = new Bord(this);

                                bord.Vakjes[rij, col - 1].MyStatus = Bordvak.Status.vrij;
                                bord.Vakjes[rij, col - 2].MyStatus = Vakjes[rij, col].MyStatus;
                                bord.Vakjes[rij, col].MyStatus = Bordvak.Status.vrij;
                                oplossingen.Add(bord);
                            }
                        }
                    }
                    //spring naar rechts
                    if (col <= 2)
                    {
                        //als ik pion of rood ben
                        if ((Vakjes[rij, col].MyStatus == Bordvak.Status.bezet || Vakjes[rij, col].MyStatus == Bordvak.Status.rood))
                        {
                            if (Vakjes[rij, col + 1].MyStatus == Bordvak.Status.bezet && Vakjes[rij, col + 2].MyStatus == Bordvak.Status.vrij)
                            {
                                Bord bord = new Bord(this);

                                bord.Vakjes[rij, col + 1].MyStatus = Bordvak.Status.vrij;
                                bord.Vakjes[rij, col + 2].MyStatus = Vakjes[rij, col].MyStatus;
                                bord.Vakjes[rij, col].MyStatus = Bordvak.Status.vrij;
                                oplossingen.Add(bord);
                            }
                        }
                    }



                }
            }
            return oplossingen;
        }

}

Асинхронизация: ошибка переполнения Синхронизация: ошибка переполнения Стек: очень медленно

Это лучший способ решения моей проблемы ???

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...