예제 #1
0
        /// <summary>
        /// metoda Minimax
        /// </summary>
        /// <param name="hloubka"></param>
        /// <returns> Bude se sama volat, dokud nedojde do konce hry, nebo do požadované hloubky</returns>
        private int Minimax(int hloubka)
        {
            if (IsCanceled())           // podmínka  => pokud BYLO žádáno o zrušení výpočtu(= výpočet se přeruší)
            {
                return(0);              // ..... takový požadavek může přijít ve chvíli, kdy bude problémek v nějakém cyklu a nejpravděpodobněji v tom rekurzivním minimax. Návratová hodnota není důležitá, protože se k ničemu nepoužije, tak jsem zvolil "return 0"
            }
            // Ohodnocení, výhra, prohra, remíza
            if (rules.IsGameFinished(nardAI))               // hra končí když: 1.počet tahů bez zajmutí figurky = 30  nebo  2.jeden z hráčů má 1 nebo žádnou figurku
            {
                SpocitejKameny(hracNaTahuAI, out int mojeKameny, out int jehoKameny);

                if (mojeKameny > jehoKameny)                // dokážu rozeznat vítězství od prohry
                {
                    return(MAX);
                }
                if (mojeKameny < jehoKameny)
                {
                    return(-MAX);
                }
                if (mojeKameny == jehoKameny)
                {
                    return(0);
                }
            }

            // Pokud bylo dosaženo maximální hloubky, provede se ohodnocení pozice              /* <------- počítání hodnoty aktuálního rozložení hrací desky */
            if (hloubka == 0)
            {
                int value = 0;      //  value -> se mění podle toho, jestli je to pro hráče výhodné nebo nevýhodné

                SpocitejKameny(hracNaTahuAI, out int mojeKameny, out int jehoKameny);
                value += mojeKameny * 2;                                // pokud bude mít soupeř míň figurek, jsem na tom líp
                value -= jehoKameny * 5;                                // pokud nude mít soupeř víc figurek, jsem na tom hůř
                                                                        // .......... aby byl hráč agresivnější, tak nastavím větší hodnotu nepřátelským figurkám. Tím se bude snažit zabrat figurku i když bude více riskovat
                return(value);
            }

            rules.GenerujPlatneTahy(nardAI, hracNaTahuAI);            // vypočítání platných tahů (protože byl proveden tah a změněn hráč na tahu -> ve VypocitejNejlepsiTahy [začne, třeba, BÍLÝ] a byl změněn hráč na tahu na druhou barvu [ČERNÝ])
            List <int[]> moves = new List <int[]>();                  // <===== seznam TAHů, který je ve formě pole intů

            foreach (int[] oneMove in rules.SeznamPlatnychTahu)
            {
                moves.Add(oneMove.Clone() as int[]);                    // "moves" je seznam polí integerů( = int[] ); metoda Clone() vytváří objekt datového typu "object" => aby to šlo uložit do toho pole, je třeba to přetypovat na int[]
            }

            int oneMoveValue = -MAX;

            foreach (int[] oneMove in moves)
            {
                nardAI.VykonejTah(oneMove);
                hracNaTahuAI *= -1;                                     // v minimaxu prováděny tahy tam a zpět, takže opět změna hráče na tahu
                oneMoveValue  = Math.Max(oneMoveValue, -Minimax(hloubka - 1));
                nardAI.TahZpet();
                hracNaTahuAI *= -1;                                     // v minimaxu prováděny tahy tam a zpět, takže opět změna hráče na tahu
            }
            if (oneMoveValue > MANY)
            {
                oneMoveValue -= 1;
            }
            if (oneMoveValue < MANY)
            {
                oneMoveValue += 1;
            }

            return(oneMoveValue);
        }
예제 #2
0
        public void Game()
        {
            // volba nastavení hráče na tahu
            usCom.VypisZpravu("Nastavení hráčů. Zadej 0 pro hráče, nebo 1..4 jako hodnotu inteligence PC", false, ConsoleColor.Green);
            inteligenceBileho = -1;
            while (inteligenceBileho == -1)
            {
                inteligenceBileho = usCom.GetPlayerSettings("Nastav bílého hráče \"x\": ");
                if (inteligenceBileho == -1)
                {
                    usCom.VypisZpravu("Nesprávně nastavená hodnota!", false, ConsoleColor.Red);
                }
            }

            inteligenceCerneho = -1;
            while (inteligenceCerneho == -1)
            {
                inteligenceCerneho = usCom.GetPlayerSettings("Nastav černého hráče \"o\": ");
                if (inteligenceCerneho == -1)
                {
                    usCom.VypisZpravu("Nesprávně nastavená hodnota!", false, ConsoleColor.Red);
                }
            }



            while (!gameRules.IsGameFinished(Nard))
            {
                usCom.ConsoleClear();
                usCom.VypisBoard(Nard);
                usCom.VypisZpravu(vypisTahu, false, ConsoleColor.Yellow);                                                                      // "false" -> protože tady není žádoucí čekat na Enter (=UserCommunication-VypisZpravu-bool cekaNaVstup)  +  "vypisTahu -> MainController-ProvedTah-VypisTahu

                if ((hracNaTahu == 1 && inteligenceBileho > 0) || (hracNaTahu == -1 && inteligenceCerneho > 0))                                // inteligence1,2 > 0 ....... hraje PC
                {
                    Thread.Sleep(300);                                                                                                         // časová prodleva před tahem počítače, aby tahy nebyly moc rychlé

                    brain             = new ArtificialIntelligence(Nard, hracNaTahu > 0 ? inteligenceBileho : inteligenceCerneho, hracNaTahu); // <= pokud je na řade s tahem počítač, vytvoří se nová instance "brain", kde se nastaví inteligence podle toho, jak je daný hráč nastaven.....
                    bestMoveCountTask = new Thread(brain.VypocitejNejlepsiTah);                                                                // ..... spustí se výpočet a výsledek se provede a SEPARÁTNÍ VLÁKNO se uloží do proměnné  ->  "bestMoveCountTask"
                    bestMoveCountTask.Start();

                    Console.Write("\n");
                    while (bestMoveCountTask.IsAlive)
                    {
                        Console.Write(".");                                         // během trvání výpočtu se budou vypisovat tečky (do console)
                    }
                    Console.Write("\n");

                    int[] vybranyTah = brain.NejlepsiTah;

                    Nard.VykonejTah(vybranyTah);                                     // vykonam na šachovnici ten ------> vybrany tah

                    vypisTahu = string.Format("{0}{1} → {2}{3}, počet tahů bez zajetí: {4}", (char)(vybranyTah[1] + 'A'), (char)(vybranyTah[0] + '1'), (char)(vybranyTah[5] + 'A'), (char)(vybranyTah[4] + '1'), Nard.PocetTahuBezZajeti());

                    //vypisTahu = Convert.ToChar(vybranyTah[1] + 65) + (vybranyTah[0] + 1).ToString() + " → " + Convert.ToChar(vybranyTah[5] + 65) + (vybranyTah[4] + 1).ToString(); // místo TahOdkud a TahKam musím zadávat indexy "vybranéhoTahu"
                    // tah se vypiše ...... souřadnice reprezentující písmena se převedou na písmena; čísla zůstanou jen se zvětší o +1, aby odpovídala hodnotám sloupců

                    hracNaTahu = -hracNaTahu;       // ....... VÝMĚNA HRÁČE NA TAHU ?????????????
                }
                else
                {
                    bool provedenTah;
                    while (!UzivatelskeVolby(out provedenTah, out bool potlacitChybu))                   // pokud plati NEGACE TRUE, tzn. nastává false, vypíše se zpráva    // ...... DOVYSVĚTLIT !!!!!!!!!!!!
                    {
                        if (!potlacitChybu)
                        {
                            usCom.VypisZpravu("  ------->   Error - Tah neni platny ", false, ConsoleColor.Red);        // "false" -> protože tady není žádoucí čekat na Enter (=UserCommunication-VypisZpravu-bool cekaNaVstup), .....
                            // .....aby se provedl další krok, tady chci rovnou vypsat tu zprávu
                        }
                    }
                    if (provedenTah)
                    {
                        hracNaTahu = -hracNaTahu;
                    }
                }
            }

            Nard.PocetFigur(out int pocetBilych, out int pocetCernych);
            if (pocetBilych > pocetCernych)
            {
                usCom.VypisZpravu("Hra skončila. Vyhrál BÍLÝ hráč.", true, ConsoleColor.Green);
            }
            else if (pocetCernych > pocetBilych)
            {
                usCom.VypisZpravu("Hra skončila. Vyhrál ČERNÝ hráč.", true, ConsoleColor.Green);
            }
            else
            {
                usCom.VypisZpravu("Hra skončila remízou.", true, ConsoleColor.Green);
            }
        }