flatCube: solver – algoritmus

No, akkor ideje elgondolkodni azon, hogy ezt a végtelenül egyszerű flatCube-ot milyen apróságokkal lehetne feldobni. Mit lehetne kitalálni a megjelenésen kívül, ami vonzóvá teheti a mi kis idióta tanulópéldánkat.

Nos talán nem rossz ötlet, ha kihívás elé állítjuk a felhasználót. Folyamatosan megmutatjuk neki, hogy az adott állapotból a végállapotba hány lépéssel lehet eljutni. Had gondolkozzon. :-D

További lehetőség, hogy a solver által előállított lépéslistát felhasználva segítséget tudunk adni, a teljesen reményvesztett felhasználóknak.

Áttekintés

Maga a solver egy végtelenül egyszerű brute force algoritmus, amely mindössze két funkcióból áll. Az első funkció a felhasználó program által hívható belépési pont, amely a megadott maximális keresési mélység figyelembe vételével hívja meg a tényleges keresést végző rekurzív algoritmust.

Szerkezet

A solver két cube-ot használ, egyrészt a jelenlegi másrészt a célállapotot reprezentáló változatot. A megoldás kereséséhez paraméterként kapja még a maximális keresési mélységet is.

Funkciók

Első körben arra gondolta, hogy az algoritmusokat valamiféle pszeudó kód segítségével próbálom meg közreadni, mivel így mindenki könnyen ki tudja hámozni a lényeget. Aztán hirtelen eszembe jutott, hogy a C# ma már szinte általános műveltségnek számít, így talán van olyan jó mint valamilyen általam hirtelen improvizált pszeudó kód.

Színek

public enum Color
{
    Nothing,
    Red,
    Green,
    Yellow,
    Blue,
    Magenta
}

Mozgatási irányok

public enum Direction
{
    Left,
    Right,
    Up,
    Down
}

Kocka komponens

using System;

namespace fcSolver
{
    public class Cube
    {
        // number of rows in cube
        public int Dimension { get { return _dimension; } }

        // move tiles left in the specified row
        public void MoveLeft(int rowIndex)
        {
        }

        // move tiles right in the specified row
        public void MoveRight(int rowIndex)
        {
        }

        // move tiles up in the specified column
        public void MoveUp(int columnIndex)
        {
        }

        // move tiles down in the specified column
        public void MoveDown(int columnIndex)
        {
        }

        // compare cube with another
        public bool Compare(Cube cube)
        {
        }

        // check the specified row homogenity (is there only one color in it)
        public bool IsHomogenRow(int rowIndex)
        {
        }

        // check the specified row homogenity (is there only one color in it)
        public bool IsHomogenColumn(int columnIndex)
        {
        }
    }
}

Lépés leíró

namespace fcSolver
{
    public class Move
    {
        // moving direction
        public Direction Direction { get; set; }

        // moved row or column index
        public int Index { get; set; }
    }
}

Megoldás útkereső

Igyekeztem érthetően kikommentelni a kódot. Az útkeresőben csak az első helyen szereplő irányt részleteztem, de a másik három azzal hajszálra megegyezik, így azokhoz senki nem írna úgysem semmit. :-D

using System. Collections. Generic;

namespace fcSolver
{
    public class Solver
    {
        private Cube _target;
        private Cube _source;

        // megoldás kereső belépési pont
        public List<<Move>> Solve(Cube source, Cube target, int maximumDepth)
        {
            _target = target;
            _source = source;

            // lényegében a megadott mélységig valamennyi mélység
            // értékkel meghívjuk az útkereső algoritmust, így biztosan
            // a legkisebb lépésszámű megoldás kerül visszaadásra
            for (int i = 0; i < maximumDepth; i++)
            {
                var result = FindWay(i);
                if (result != null)
                {
                    return result;
                }
            }
            return new List<<Move>>();
        }

        // Adott maximális lépésszámú megoldás keresése
        private List<<Move>> FindWay(int maximumDepth)
        {
            List<<Move>> result = null;
            // próbáljuk jobbra és balra
            for (int row = 0; row < _source. Dimension; row++)
            {
                // csak akkor van értelme próbálkozni ha a sor nem homogén
                // azaz egynél több szín található benne, egyébként tekerhetjük
                // reggelig, akkor sem változik semmi. :-) 
                if (!_source. IsHomogenRow(row))
                {
                    // mozgatás balra
                    _source. Die direkte durchreise wurde den <a href="https://hausarbeit-agentur.com">https://hausarbeit-agentur.com</a> kaufleuten außerdem von islamischen arabern verwehrt. MoveLeft(row);
                    // ellenőrizzük, hogy elértük-e a célállapotot
                    if (_source. Compare(_target))
                    {
                        // ha megvan amit kerestünk, akkor létrehozunk egy listát
                        // és mindjárt feltöltjük a megtalált utolsó lépéssel
                        result = new List<<Move>>() { (new Move() { Direction = Direction. Left, Index = row }) };
                    }
                    else if (maximumDepth != 0)
                    {
                        // ha ez a lépés nem hozott eredményt
                        // de még mehetünk mélyebbre, akkor megyünk
                        result = FindWay(maximumDepth - 1);
                        // ha a érkezik válasz a mélyből, az azt jeleni, hogy
                        // a hívás előtt megtalált lépés része a helyes útnak
                        if (result != null)
                        {
                            // beszúrjuk a helyes út részét képező lépésünket
                            // a lista elejére
                            result. Insert(0, new Move() { Direction = Direction. Left, Index = row });
                        }
                    }
                    // ha ebben a lépésben megtaláltuk a helyes út egy darabját
                    // nincs értelme tovább keresni, mehetünk visszafelé
                    if (result != null)
                    {
                        // megyünk visszafelé, összeszedjük a helyes út többi lépését
                        return result;
                    }
                    // ha ez az irány semmire nem volt jó
                    // visszaállítjuk a kockát és próbálkozunk másik irányban
                    _source. MoveRight(row);

                    _source. MoveRight(row);
                    if (_source. Compare(_target))
                    {
                        result = new List<<Move>>() { (new Move() { Direction = Direction. Right, Index = row }) };
                    }
                    else if (maximumDepth != 0)
                    {
                        result = FindWay(maximumDepth - 1);
                        if (result != null)
                        {
                            result. Insert(0, new Move() { Direction = Direction. Right, Index = row });
                        }
                    }
                    if (result != null)
                    {
                        return result;
                    }
                    _source. MoveLeft(row);

                }
            }
            // try to move up and down
            for (int column = 0; column < _source. Dimension; column++)
            {
                if (!_source. IsHomogenColumn(column))
                {
                    _source. MoveUp(column);
                    if (_source. Compare(_target))
                    {
                        result = new List<<Move>>() { (new Move() { Direction = Direction. Up, Index = column }) };
                    }
                    else if (maximumDepth != 0)
                    {
                        result = FindWay(maximumDepth - 1);
                        if (result != null)
                        {
                            result. Insert(0, new Move() { Direction = Direction. Up, Index = column });
                        }
                    }
                    if (result != null)
                    {
                        return result;
                    }
                    _source. MoveDown(column);

                    _source. MoveDown(column);
                    if (_source. Compare(_target))
                    {
                        result = new List<<Move>>() { (new Move() { Direction = Direction. Down, Index = column }) };
                    }
                    else if (maximumDepth != 0)
                    {
                        result = FindWay(maximumDepth - 1);
                        if (result != null)
                        {
                            result. Insert(0, new Move() { Direction = Direction. Down, Index = column });
                        }
                    }
                    if (result != null)
                    {
                        return result;
                    }
                    _source. MoveUp(column);
                }
            }
            return result;
        }
    }
}

.

Kategória: Általános | A közvetlen link.