/// <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); }
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); } }