Beispiel #1
0
        /// <summary>
        /// Μέθοδος που επιστρέφει το μέτωπο ταξινομημένο. Με χρήση της ευρετικής συνάρτησης,
        /// το μέτωπο αναζήτησης ταξινομείται ώστε να γίνει επίσκεψη πρώτα στον κατάλληλο κόμβο ( βάση αλγορίθμου).
        /// </summary>
        /// <param name="method"> αλγόριθμος </param>
        /// <returns> το μέτωπο </returns>
        public Frontier SortedFrontier(Αuxiliary.methodEnum method)
        {
            Frontier resultFrontier = new Frontier();

            switch (method)
            {
            case Αuxiliary.methodEnum.Breadth:
                resultFrontier = this;
                break;

            case Αuxiliary.methodEnum.Depth:
                resultFrontier = this;
                break;

            case Αuxiliary.methodEnum.Best:
                var test = from state in this orderby state.h select state;
                foreach (State s in test)
                {
                    resultFrontier.AddLast(s);
                }
                break;

            case Αuxiliary.methodEnum.AStar:
                test = from state in this orderby state.f select state;
                foreach (State s in test)
                {
                    resultFrontier.AddLast(s);
                }
                break;
            }
            return(resultFrontier);
        }
Beispiel #2
0
        /// <summary>
        /// Μέθοδος που βρίσκει τα παιδιά της τρέχουσας κατάστασης και τα επιστρέφει.
        /// </summary>
        /// <param name="method"> όνομα μεθόδου για αναζήτηση. </param>
        /// <returns> τα παιδιά τύπου Frontier </returns>
        public Frontier GetChildrenStates(Αuxiliary.methodEnum method)
        {
            Frontier children = new Frontier();
            bool     EmptyFreeCellExamined = false;

            #region loop freecells
            for (int j = 0; j < Αuxiliary.freeCellCount; j++)
            {
                Card freeCellCard = freeCell[j];
                if (freeCellCard != null)
                {
                    #region from freecell to foundation
                    switch (freeCellCard.Symbol)
                    {
                    case SymbolEnum.Clubs:
                        if (freeCellCard.FoundationRule(ClubsFoundation))
                        {
                            State childState = this.Clone();
                            childState.ClubsFoundation++;
                            childState.freeCell[j] = null;
                            childState.Parent      = this;
                            childState.Move        = freeCellCard.ToString();
                            childState.MoveType    = MoveEnum.moveFoundation;
                            children.AddState(childState, method);
                        }
                        break;

                    case SymbolEnum.Diamonds:
                        if (freeCellCard.FoundationRule(DiamondsFoundation))
                        {
                            State childState = this.Clone();
                            childState.DiamondsFoundation++;
                            childState.freeCell[j] = null;
                            childState.Parent      = this;
                            childState.Move        = freeCellCard.ToString();
                            childState.MoveType    = MoveEnum.moveFoundation;
                            children.AddState(childState, method);
                        }
                        break;

                    case SymbolEnum.Hearts:
                        if (freeCellCard.FoundationRule(HeartsFoundation))
                        {
                            State childState = this.Clone();
                            childState.HeartsFoundation++;
                            childState.freeCell[j] = null;
                            childState.Parent      = this;
                            childState.Move        = freeCellCard.ToString();
                            childState.MoveType    = MoveEnum.moveFoundation;
                            children.AddState(childState, method);
                        }
                        break;

                    case SymbolEnum.Spades:
                        if (freeCellCard.FoundationRule(SpadesFoundation))
                        {
                            State childState = this.Clone();
                            childState.SpadesFoundation++;
                            childState.freeCell[j] = null;
                            childState.Parent      = this;
                            childState.Move        = freeCellCard.ToString();
                            childState.MoveType    = MoveEnum.moveFoundation;
                            children.AddState(childState, method);
                        }
                        break;
                    }
                    #endregion from freecell to foundation

                    #region from freecell to stack
                    for (int i = 0; i < Αuxiliary.stacksCount; i++)
                    {
                        if (this.stacks[i] != null && this.stacks[i].Count > 0)
                        {
                            Card sCard = this.stacks[i].Last();
                            if (((sCard != null) & (freeCellCard.StacksRule(sCard) == StacksRuleEnum.RuleBefore)) || //stack αντίθετου χρώματος και μεγαλύτερης κατά 1 τιμής
                                (sCard == null))    //Άδειο stack
                            {
                                {
                                    State childState = this.Clone();
                                    childState.stacks[i].AddLast(freeCellCard);
                                    childState.freeCell[j] = null;
                                    if (!childState.AlreadyInHistory())
                                    {
                                        childState.Parent   = this;
                                        childState.Move     = freeCellCard.ToString();
                                        childState.MoveType = MoveEnum.moveEmtpyStack;
                                        children.AddState(childState, method);
                                    }
                                    //freeCellCard.Show();
                                }
                            }
                        }
                    } // for
                    #endregion from freecell to stack
                }
                else
                {
                    #region from stack to freecell
                    if (!EmptyFreeCellExamined) //μόνο για ένα freecell να γίνει, όλα τα freecells είναι ισοδύναμα
                    {
                        for (int i = 0; i < Αuxiliary.stacksCount; i++)
                        {
                            if (this.stacks[i] != null && this.stacks[i].Count > 0)
                            {
                                if (this.stacks[i].Last != null)
                                {
                                    State childState = this.Clone();
                                    childState.freeCell[j] = childState.stacks[i].Pop();
                                    if (!childState.AlreadyInHistory())
                                    {
                                        childState.Parent   = this;
                                        childState.Move     = childState.freeCell[j].ToString();
                                        childState.MoveType = MoveEnum.moveFreecell;
                                        children.AddState(childState, method);
                                    }
                                }
                            }
                        } // for
                        EmptyFreeCellExamined = true;
                    }
                    #endregion from stack to freecell
                }
            }
            #endregion loop freecells

            #region loop stacks
            for (int i = 0; i < Αuxiliary.stacksCount; i++)
            {
                Card aCard;
                if ((this.stacks[i] == null) || (this.stacks[i].Count == 0))
                {
                    aCard = null;
                }
                else
                {
                    aCard = this.stacks[i].Last();

                    #region from stack to foundation
                    switch (aCard.Symbol)
                    {
                    case SymbolEnum.Clubs:
                        if (aCard.FoundationRule(ClubsFoundation))
                        {
                            State childState = this.Clone();
                            childState.ClubsFoundation++;
                            childState.stacks[i].RemoveLast();
                            childState.Parent   = this;
                            childState.Move     = aCard.ToString();
                            childState.MoveType = MoveEnum.moveFoundation;
                            children.AddState(childState, method);
                        }
                        break;

                    case SymbolEnum.Diamonds:
                        if (aCard.FoundationRule(DiamondsFoundation))
                        {
                            State childState = this.Clone();
                            childState.DiamondsFoundation++;
                            childState.stacks[i].RemoveLast();
                            childState.Parent   = this;
                            childState.Move     = aCard.ToString();
                            childState.MoveType = MoveEnum.moveFoundation;
                            children.AddState(childState, method);
                        }
                        break;

                    case SymbolEnum.Hearts:
                        if (aCard.FoundationRule(HeartsFoundation))
                        {
                            State childState = this.Clone();
                            childState.HeartsFoundation++;
                            childState.stacks[i].RemoveLast();
                            childState.Parent   = this;
                            childState.Move     = aCard.ToString();
                            childState.MoveType = MoveEnum.moveFoundation;
                            children.AddState(childState, method);
                        }
                        break;

                    case SymbolEnum.Spades:
                        if (aCard.FoundationRule(SpadesFoundation))
                        {
                            State childState = this.Clone();
                            childState.SpadesFoundation++;
                            childState.stacks[i].RemoveLast();
                            childState.Parent   = this;
                            childState.Move     = aCard.ToString();
                            childState.MoveType = MoveEnum.moveFoundation;
                            children.AddState(childState, method);
                        }
                        break;
                    }
                    #endregion from stack to foundation
                }

                #region from stack to another stack
                for (int j = Convert.ToByte(i + 1); j < Αuxiliary.stacksCount; j++)
                {
                    Card bCard;
                    if ((this.stacks[j] == null) || (this.stacks[j].Count == 0))
                    {
                        bCard = null;
                    }
                    else
                    {
                        bCard = this.stacks[j].Last();
                    }

                    int SourceStackId = 100;
                    int TargetStackId = 100;

                    if ((aCard == null) & (bCard == null)) //Αν και τα δύο stacks είναι κενά
                    {
                        continue;
                    }
                    else if ((aCard == null) && (bCard != null)) //Αν το 1ο είναι κενό ενώ το 2ο όχι
                    {
                        if (this.stacks[j].Count == 1)
                        {
                            continue;
                        }
                        else
                        {
                            SourceStackId = j;
                            TargetStackId = i;
                        }
                    }
                    //θέλουμε να βρούμε και την περίπτωση όπου ένα stack έχει μόνο μια κάρτα και ένα άλλο είναι κενό
                    //Σε αυτή την περίπτωση δε θέλουμε μετακίνηση
                    else if ((aCard != null) && (bCard == null)) //Αν το 2ο είναι κενό ενώ το 1ο όχι
                    {
                        if (this.stacks[i].Count == 1)
                        {
                            continue;
                        }
                        else
                        {
                            SourceStackId = i;
                            TargetStackId = j;
                        }
                    }
                    else //Αν κανένα δεν είναι κενό
                    {
                        switch (aCard.StacksRule(bCard))
                        {
                        case StacksRuleEnum.RuleBefore:
                            SourceStackId = j;
                            TargetStackId = i;
                            break;

                        case StacksRuleEnum.RuleAfter:
                            SourceStackId = i;
                            TargetStackId = j;
                            break;

                        default:
                            continue;
                            break;
                        }
                    }

                    State childState         = this.Clone();
                    Card  PreviousTargetCard = null;

                    if (childState.stacks[TargetStackId] == null)
                    {
                        childState.stacks[TargetStackId] = new Stacks();
                    }

                    if (childState.stacks[TargetStackId].Count > 0)
                    {
                        PreviousTargetCard = childState.stacks[TargetStackId].Last();
                    }

                    childState.stacks[TargetStackId].AddLast(this.stacks[SourceStackId].Last());
                    childState.stacks[SourceStackId].RemoveLast();

                    if (!childState.AlreadyInHistory())
                    {
                        childState.Parent = this;
                        if (childState.stacks[TargetStackId].Count == 1) //new Stack
                        {
                            childState.Move     = childState.stacks[TargetStackId].Last().ToString();
                            childState.MoveType = MoveEnum.moveEmtpyStack;
                        }
                        else
                        {
                            childState.Move     = childState.stacks[TargetStackId].Last().ToString() + " " + PreviousTargetCard.ToString();
                            childState.MoveType = MoveEnum.moveCascade;
                        }

                        children.AddState(childState, method);
                    }
                }
                #endregion from stack to another stack
            }
            #endregion loop stacks

            return(children);
        }
        /// <summary>
        /// Η μέθοδος αυτή εξετάζει τους κόμβους στο μέτωπο αναζήτησης μέχρι να βρει λύση στο παιχνίδι ή να φτάσει σε timeout.
        /// </summary>
        private static void solveProblem()
        {
            Stopwatch stopWatch = new Stopwatch();

            stopWatch.Start(); // ξεκινάει η χρονομέτρηση.

            Frontier gameFrontier = new Frontier();

            Αuxiliary.gameHistory = new Frontier();

            int step = 0;

            gameFrontier.AddLast(initialState);
            method = getMethod();

            // Επανάληψη που εξετάζει όλους τους κόμβους (καταστάσεις) που υπάρχουν στο μέτωπο αναζήτησης.
            while (gameFrontier.Count > 0)
            {
                State currentState = gameFrontier.Pop();
                Αuxiliary.gameHistory.AddLast(currentState);
                step++;

                if (step % 100 == 0)
                {
                    System.Console.WriteLine("Step " + step);
                }

                // αν έχει βρεθεί λύση.
                if (currentState.Status() == State.stateStatusEnum.SolutionFound)
                {
                    System.Console.WriteLine("Βρέθηκε λύση σε " + Convert.ToString(stopWatch.ElapsedMilliseconds / 1000) + " δευτερόλεπτα");
                    State lastState  = currentState;
                    State t          = lastState.Parent;
                    int   totalSteps = 0;
                    while (t.Parent != initialState)
                    {
                        t.SolutionChild = lastState;
                        lastState       = t;
                        t = lastState.Parent;
                        totalSteps++;
                    }
                    System.Console.WriteLine("Βήματα από την αρχική κατάσταση εως τη λύση " + Convert.ToString(totalSteps));
                    System.Console.WriteLine("Κόμβοι που εξετάστηκαν: " + Convert.ToString(step));
                    t.SolutionChild = lastState;
                    string solutionText = totalSteps.ToString() + Environment.NewLine;

                    // μαζεύω τα βήματα μέχρι την λύση.
                    while (t.SolutionChild != null)
                    {
                        //Stopwatch s = new Stopwatch();
                        //s.Start();

                        solutionText = solutionText + t.TotalMove() + Environment.NewLine;
                        t            = t.SolutionChild;
                    }

                    // εξαγωγή σε αρχείο.
                    solutionText = solutionText + t.TotalMove() + Environment.NewLine;
                    System.IO.File.WriteAllText(outputFileName, solutionText);
                    System.Diagnostics.Process.Start(outputFileName);
                    return;
                } // if

                // αν δεν βρέθηκε λύση εξετάζω τα παιδιά του κόμβου ανάλογα με τον αλγόριθμο πάντα.
                Frontier childrenFrontier = currentState.GetChildrenStates(method);
                switch (method)
                {
                case Αuxiliary.methodEnum.Breadth:     // αν έχει επιλεγεί πρώτα σε πλάτος, τότε προσθέτω στην αρχή (εξετάζεται στο τέλος) του μετώπου το State εκείνο.
                    foreach (State state in childrenFrontier)
                    {
                        gameFrontier.AddFirst(state);
                    }
                    break;

                case Αuxiliary.methodEnum.Depth:     // αν έχει επιλεγεί πρώτα σε βάθος, τότε βάζω το State στο τέλος (άρα θα είναι το επόμενο που θα εξεταστεί).
                    foreach (State state in childrenFrontier)
                    {
                        gameFrontier.AddLast(state);
                    }
                    break;

                case Αuxiliary.methodEnum.AStar:     // Για ευρετικούς αλγορίθμους προσθέτω το Stat στο τέλος και μετά ταξινομώ με βάση την ευρετική συνάρτηση.
                    foreach (State state in childrenFrontier)
                    {
                        gameFrontier.AddLast(state);
                    }
                    gameFrontier = gameFrontier.SortedFrontier(method);
                    break;

                case Αuxiliary.methodEnum.Best:     // Για ευρετικούς αλγορίθμους προσθέτω το State στο τέλος και μετά ταξινομώ με βάση την ευρετική συνάρτηση.
                    foreach (State state in childrenFrontier)
                    {
                        gameFrontier.AddLast(state);
                    }
                    gameFrontier = gameFrontier.SortedFrontier(method);
                    break;

                case Αuxiliary.methodEnum.Empty:
                    break;
                }


                if (stopWatch.ElapsedMilliseconds > Αuxiliary.TIMEOUT * 1000)
                {
                    System.Console.WriteLine("Δεν ήταν δυνατή η επίλυση του προβλήματος σε " + Convert.ToString(Αuxiliary.TIMEOUT) + " δευτερόλεπτα");
                    return;
                }
            } // while
        }     // solveProblem method