Jezcova procházka
Jezcova procházka

Jezdcova procházka (Knight's tour) je šachová úloha, jejímž cílem je pomocí šachové figury jezdce navštívit všechna pole šachovnice právě jednou. Tento hlavolam je znám již od středověku – byl popsán kolem roku 840 arabským učencem Al-Ádlím v díle Kitáb aš-Šatrandž (Kniha o šachu).

Jezdcova procházka má překvapivě obrovské množství řešení, pro běžnou šachovnici 8x8 polí existuje 33 439 123 484 294 neorientovaných cest, kterými se může kůň vydat.

Strojové řešení problému

Nejjednodušším způsobem řešením problému je backtracking. Naivní algoritmus má ovšem tendenci být velmi pomalý, protože se dostává snadno do do slepých uliček, v nichž musí přehodnotit velké množství rozhodnutí. Jeho optimalizací je Warnsdorffův algoritmus, ve kterém se kůň vždy vydá přednostně na to pole, ze kterého může pokračovat nejméně způsoby. V této heuristice jsou tedy přednostně obsazována špatně dostupá pole, zatímco ta snadno dostupná jsou odložena na později.

Počet řešení problému

Velikost šachovnice 3x1 3x2 3x3 3x4 3x5 3x6 3x7 3x8 3x9 3x10 3x11 3x12 3x13
Počet neorientovaných řešení 0 0 0 16 0 0 104 792 1 120 6 096 21 344 114 496 257 728

Kód

001./**
002. * Resicka jezdcovy prochazky backtrackingem
003. * @author Pavel Micka
004. */
005.public class KnightsTour {
006. 
007.    /**
008.     * Priznak nenavstivenosti policka
009.     */
010.    private static int NOT_VISITED = -1;
011.    /**
012.     * Velikost sachovnice na ose x
013.     */
014.    private int xSize;
015.    /**
016.     * Velikost sachovnice na ose y
017.     */
018.    private int ySize;
019.    /**
020.     * Pocet reseni
021.     */
022.    private int solutionsCount;
023.    /**
024.     * Pole pro reseni
025.     * 0 -> pocatecni pozice kone
026.     * 1 -> prvni tah
027.     * 2 -> druhy tah
028.     * .
029.     * .
030.     * .
031.     * n -> n-ty tah
032.     */
033.    private int[][] solutionBoard;
034. 
035.    public static void main(String[] args) {
036.        for (int i = 1; i < 20; i++) {
037.            KnightsTour kt = new KnightsTour(3, i);
038.            kt.solve();
039.            System.out.println("<td>"+kt.solutionsCount+"</td>");
040.        }
041.    }
042. 
043.    /**
044.     * Konstruktor resitele jezdcovy prochazky
045.     * @param xSize velikost sachovnice na ose x
046.     * @param ySize velikost sachovnice na ose y
047.     */
048.    public KnightsTour(int xSize, int ySize) {
049.        solutionsCount = 0;
050. 
051.        this.xSize = xSize;
052.        this.ySize = ySize;
053. 
054.        solutionBoard = new int[ySize][xSize];
055.        for (int i = 0; i < ySize; i++) {
056.            for (int j = 0; j < xSize; j++) {
057.                solutionBoard[i][j] = NOT_VISITED;
058.            }
059.        }
060.    }
061. 
062.    /**
063.     * Resi jezdcovu prochazku
064.     */
065.    public void solve() {
066.        for (int i = 0; i < ySize; i++) {
067.            for (int j = 0; j < xSize; j++) {
068.                takeTurn(j, i, 0);
069.                solutionBoard[i][j] = NOT_VISITED; //reset pole
070.            }
071.        }
072.    }
073. 
074.    /**
075.     * Vrati policka, na ktera muze kun skocit
076.     * @param x souradnice kone x
077.     * @param y souradnice kone y
078.     * @return souradnice, na ktere muze kun skocit
079.     */
080.    private List<Coords> getFields(int x, int y) {
081.        List<Coords> l = new ArrayList<Coords>();
082.        if (x + 2 < xSize && y - 1 >= 0)
083.            l.add(new Coords(x + 2, y - 1)); //doprava nahoru
084.        if (x + 1 < xSize && y - 2 >= 0)
085.            l.add(new Coords(x + 1, y - 2)); //nahoru doprava
086.        if (x - 1 >= 0 && y - 2 >= 0)
087.            l.add(new Coords(x - 1, y - 2)); //nahoru doleva
088.        if (x - 2 >= 0 && y - 1 >= 0)
089.            l.add(new Coords(x - 2, y - 1)); //doleva nahoru
090.        if (x - 2 >= 0 && y + 1 < ySize)
091.            l.add(new Coords(x - 2, y + 1)); //doleva dolu
092.        if (x - 1 >= 0 && y + 2 < ySize)
093.            l.add(new Coords(x - 1, y + 2)); //dolu doleva
094.        if (x + 1 < xSize && y + 2 < ySize)
095.            l.add(new Coords(x + 1, y + 2)); //dolu doprava
096.        if (x + 2 < xSize && y + 1 < ySize)
097.            l.add(new Coords(x + 2, y + 1)); //doprava dolu
098.        return l;
099.    }
100. 
101.    /**
102.     * Provede tah konem
103.     * @param x cilova souradnice x
104.     * @param y cilova souradnice y
105.     * @param turnNr cislo tahu
106.     */
107.    private void takeTurn(int x, int y, int turnNr) {
108.        solutionBoard[y][x] = turnNr;
109.        if (turnNr == (xSize * ySize) - 1) {
110.            solutionsCount++;
111.            printSolution();
112.            return;
113.        } else {
114.            for (Coords c : getFields(x, y)) {
115.                if (solutionBoard[c.getY()][c.getX()] == NOT_VISITED) {
116.                    takeTurn(c.getX(), c.getY(), turnNr + 1);
117.                    solutionBoard[c.getY()][c.getX()] = NOT_VISITED; //reset policka
118.                }
119.            }
120.        }
121.    }
122. 
123.    /**
124.     * Vypise reseni
125.     */
126.    private void printSolution() {
127.        System.out.println("Reseni #" + solutionsCount);
128.        for (int i = 0; i < solutionBoard.length; i++) {
129.            for (int j = 0; j < solutionBoard[i].length; j++) {
130.                System.out.print(solutionBoard[i][j] + " ");
131.            }
132.            System.out.println("");
133.        }
134.        System.out.println("");
135.    }
136.     
137.    /**
138.     * @return the solutionsCount
139.     */
140.    public int getSolutionsCount() {
141.        return solutionsCount;
142.    }   
143.     
144.    /**
145.     * Reprezentuje souradnici
146.     */
147.    private class Coords {
148.        private int x;
149.        private int y;
150. 
151.        public Coords(int x, int y) {
152.            this.x = x;
153.            this.y = y;
154.        }
155. 
156.        /**
157.         * @return the x
158.         */
159.        public int getX() {
160.            return x;
161.        }
162. 
163.        /**
164.         * @param x the x to set
165.         */
166.        public void setX(int x) {
167.            this.x = x;
168.        }
169. 
170.        /**
171.         * @return the y
172.         */
173.        public int getY() {
174.            return y;
175.        }
176. 
177.        /**
178.         * @param y the y to set
179.         */
180.        public void setY(int y) {
181.            this.y = y;
182.        }
183.    }
184.}
001.#include <iostream>
002.#include <vector>
003. 
004.using namespace std;
005./**
006. * Resicka jezdcovy prochazky backtrackingem
007. * @author Pavel Micka
008. */
009.class KnightsTour {
010.private:
011.    /**
012.     * Priznak nenavstivenosti policka
013.     */
014.    static const int NOT_VISITED = -1;
015.    /**
016.     * Velikost sachovnice na ose x
017.     */
018.    int xSize;
019.    /**
020.     * Velikost sachovnice na ose y
021.     */
022.    int ySize;
023.    /**
024.     * Pocet reseni
025.     */
026.    int solutionsCount;
027.    /**
028.     * Pole pro reseni
029.     * 0 -> pocatecni pozice kone
030.     * 1 -> prvni tah
031.     * 2 -> druhy tah
032.     * .
033.     * .
034.     * .
035.     * n -> n-ty tah
036.     */
037.    int ** solutionBoard;
038. 
039. 
040.    /**
041.     * Reprezentuje souradnici
042.     */
043.    class Coords {
044.    private:
045.        int x;
046.        int y;
047.    public:
048.        Coords(int x, int y) {
049.            this->x = x;
050.            this->y = y;
051.        }
052. 
053.        /**
054.         * @return the x
055.         */
056.        int getX() {
057.            return x;
058.        }
059. 
060.        /**
061.         * @param x the x to set
062.         */
063.        void setX(int x) {
064.            this->x = x;
065.        }
066. 
067.        /**
068.         * @return the y
069.         */
070.        int getY() {
071.            return y;
072.        }
073. 
074.        /**
075.         * @param y the y to set
076.         */
077.        void setY(int y) {
078.            this->y = y;
079.        }
080.    };
081. 
082.    /**
083.     * Vrati policka, na ktera muze kun skocit
084.     * @param x souradnice kone x
085.     * @param y souradnice kone y
086.     * @param v reference na vector, do ktereho budou ulozeny souradnice
087.     */
088.    void getFields(int x, int y, vector<Coords> &v) {
089.        if (x + 2 < xSize && y - 1 >= 0)
090.            v.push_back(Coords(x + 2, y - 1)); //doprava nahoru
091.        if (x + 1 < xSize && y - 2 >= 0)
092.            v.push_back(Coords(x + 1, y - 2)); //nahoru doprava
093.        if (x - 1 >= 0 && y - 2 >= 0)
094.            v.push_back(Coords(x - 1, y - 2)); //nahoru doleva
095.        if (x - 2 >= 0 && y - 1 >= 0)
096.            v.push_back(Coords(x - 2, y - 1)); //doleva nahoru
097.        if (x - 2 >= 0 && y + 1 < ySize)
098.            v.push_back(Coords(x - 2, y + 1)); //doleva dolu
099.        if (x - 1 >= 0 && y + 2 < ySize)
100.            v.push_back(Coords(x - 1, y + 2)); //dolu doleva
101.        if (x + 1 < xSize && y + 2 < ySize)
102.            v.push_back(Coords(x + 1, y + 2)); //dolu doprava
103.        if (x + 2 < xSize && y + 1 < ySize)
104.            v.push_back(Coords(x + 2, y + 1)); //doprava dolu
105.    }
106. 
107.    /**
108.     * Provede tah konem
109.     * @param x cilova souradnice x
110.     * @param y cilova souradnice y
111.     * @param turnNr cislo tahu
112.     */
113.    void takeTurn(int x, int y, int turnNr) {
114.        solutionBoard[y][x] = turnNr;
115.        if (turnNr == (xSize * ySize) - 1) {
116.            solutionsCount++;
117.            printSolution();
118.            return;
119.        } else {
120.            vector<Coords> v;
121.            getFields(x, y, v);
122.            for(unsigned i = 0; i < v.size(); i++){
123.                if (solutionBoard[v.at(i).getY()][v.at(i).getX()] == NOT_VISITED) {
124.                    takeTurn(v.at(i).getX(), v.at(i).getY(), turnNr + 1);
125.                    solutionBoard[v.at(i).getY()][v.at(i).getX()] = NOT_VISITED; //reset policka
126.                }
127.            }
128.        }
129.    }
130. 
131.    /**
132.     * Vypise reseni
133.     */
134.    void printSolution() {
135.        cout << "Reseni #" << solutionsCount << "\\n" ;
136.        for (int i = 0; i < ySize; i++) {
137.            for (int j = 0; j < xSize; j++) {
138.                cout << solutionBoard[i][j] << " ";
139.            }
140.            cout << "\\n";
141.        }
142.        cout << "\\n";
143.    }
144. 
145.public:
146.    /**
147.     * Konstruktor resitele jezdcovy prochazky
148.     * @param xSize velikost sachovnice na ose y
149.     * @param ySize velikost sachovnice na ose y
150.     */
151.    KnightsTour(int xSize, int ySize) {
152.        solutionsCount = 0;
153. 
154.        this->xSize = xSize;
155.        this->ySize = ySize;
156. 
157.        solutionBoard = new int*[ySize];
158.        for(int i = 0; i < ySize; i++){
159.            solutionBoard[i] = new int[xSize];
160.            for (int j = 0; j < xSize; j++) {
161.                solutionBoard[i][j] = NOT_VISITED;
162.            }
163.        }
164.    }
165.    ~KnightsTour(){
166.        for(int i = 0; i < ySize; i++) delete[] solutionBoard[i];
167.        delete[] solutionBoard;
168.    }
169. 
170.    /**
171.     * Resi jezdcovu prochazku
172.     */
173.    void solve() {
174.        for (int i = 0; i < ySize; i++) {
175.            for (int j = 0; j < xSize; j++) {
176.                takeTurn(j, i, 0);
177.                solutionBoard[i][j] = NOT_VISITED; //reset pole
178.            }
179.        }
180.    }
181. 
182.    /**
183.     * @return the solutionsCount
184.     */
185.    int getSolutionsCount() {
186.        return solutionsCount;
187.    }
188.};
189. 
190. 
191. 
192. 
193.int main(int argc, char* argv[]) {
194.    KnightsTour t(3, 14);
195.    t.solve();
196.    system("pause");
197.    return 0;
198.}

Literatura


SEO od společnosti Digital Pylon


Online casino s algoritmem

České casino online online slot-vegas.cz

Hrajte nejlepší hry jako je GoodGame Empire.





Zajímavé články: Jak najít práci snů? Zvolte kariéru v IT!, Češi mají rádi hrací automaty online, Jak funguje algoritmické obchodování Casino, Online výuka Algoritmus a online marketing mají svá pravidla, Automaty, Matematický vliv, Ratings, Jak fungují algoritmy hazardních her online: více znalostí, více peněz, SYPWAI - nástroj pro vědecký vývoj, Vynikají na globálním trhu: Nejlepší vývojáři softwaru pro online výherní automaty, Jak si vybrat nejlepší české online casino, Proč byste měli hrát online casino VPN revoluce, Kde najdeme algoritmy v každodenním životě?, Čeká vás pracovní pohovor mimo město? Podívejte se, jak dokonale zvládnout včasný příchod, 5 úžasných technologií ze světa hazardních her, Mirror and access to Mostbet, Svou kancelář můžete mít stále po ruce, Jaké výhody má digitalizovaná firma oproti off-line konkurenci?, Jaký systém vybrat pro snadné řízení výroby?, Nahradí umělá inteligence ajťáky?, Důvody, proč používat SnapTik ke stahování videí TikTok, Dokonalý den na pláži: Co si vzít s sebou, aby byl výlet zábavný a bezpečný?, Jak přežít dlouhý let?, Go pay GoodGame Empire, Blockchain, Rozhovor, Umělá inteligence, Ochranná známka pre softvér: Prečo ju registrovať?, Role kryptografických algoritmů v zabezpečení online kasin, Jaké jsou náklady na nákup 3D tiskárny?, Jak algoritmy vylepšují online zážitky v roce 2025,


Doporučujeme

Internet pro vaši firmu na míru

https://www.algoritmy.net