/// <summary> /// Metoda MiniMaxu /// </summary> /// <param name="hloubka"></param> /// <returns></returns> private int MiniMax(int hloubka) { if (rules.IsGameFinished()) //pokud je hra u konce tj., cerne figurku = 0 nebo bile = 0 { int minePesak, mineDama, enemyPesak, enemyDama; CountStones(out minePesak, out mineDama, out enemyPesak, out enemyDama); if (minePesak + mineDama > enemyPesak + enemyDama) //Výhra { return(MAX); //vrátí největší 99 } if (minePesak + mineDama < enemyPesak + enemyDama) //Prohra { return(-MAX); //vrátí nejmenší -99 } if (minePesak + mineDama == enemyPesak + enemyDama) //Remíza { return(0); //0 } } if (hloubka == 0) //dosaženo požadované hloubky koncová pozice, ohodnocení pozic { int hodnota = 0; int minePesak, mineDama, enemyPesak, enemyDama; CountStones(out minePesak, out mineDama, out enemyPesak, out enemyDama); //tabulka ohodnocení figurek //příklad 1 cerna a 1 bíla, na tahu bílý hodnota = hodnota + minePesak * 2; //vlastní pěšák, 0 + 1 * 2 = 2 hodnota = hodnota + mineDama * 4; //vlastní dáma, 0 hodnota = hodnota - enemyPesak * 3; //nepřátelský pěšák, 0 - 1 * 3 = -3 hodnota = hodnota - enemyDama * 6; //nepřátelská dáma, 0 return(hodnota); } int ohodnoceni = -MAX; // -99 List <int[]> tahy = new List <int[]>(); //pro generování tahů foreach (int[] tah in rules.GetMovesList()) //smyčka, pro každý tah, vygenerovaný ze všech tahů GetMoveList { tahy.Add(tah.Clone() as int[]); //přidá se to našeho Listu "tahy" } foreach (int[] tah in tahy) //smyčka, tah z kolekce "tahy" { board.Move(tah, false, false); //provedou se všechny možné tahy rules.ChangePlayer(); //změní se hráč rules.MovesGenerate(); //vygenerují se jeho tahy ohodnoceni = Math.Max(ohodnoceni, -MiniMax(hloubka - 1)); //ohodnocení se vybere z Max(ohodnocení, -(rekurzivní volání MiniMaxu(hloubka-1)) board.Move(tah, false, true); //tahy se provedou zpět at máme výchozí desku rules.ChangePlayer(); //změní se hráč na tahu } //oddálení prohry a preferování výhry if (ohodnoceni > MNOHO) { ohodnoceni = ohodnoceni - 1; } if (ohodnoceni < -MNOHO) { ohodnoceni = ohodnoceni + 1; } return(ohodnoceni); }
/// <summary> /// Hlavní herní smyčka /// </summary> public void Game() { rules.InitBoard(); //inicializace desky ui.SelectPlayer(out player1, out player2); //výběr hráče na tahu rules.InitPlayer(); //inicializace hráče na tahu rules.MovesGenerate(); //vygenerování všech tahů pro aktuálního hráče tj. 1-bílý board.tahuBezSkoku = 0; int kolo = 0; //počítadlo kol int ptrTah = board.HistoryMove.Count; //ukazatel na poslední tah v historii tahů int[] posledniTah = null; //uložen poslední tah while (!rules.IsGameFinished()) //cyklus dokud platí že oba hráči mají figurky, jinak konec { Console.Clear(); ui.PocetKol(kolo); ui.PocetTahuBezSkoku(board.tahuBezSkoku); ui.PrintBoard(board); //Tahy počítače if (rules.PlayerOnMove() == 1 && player1 > 0 || rules.PlayerOnMove() == -1 && player2 > 0) //pokud hráč na tahu je 1 a player1 > 0 tak true, provede tah a continue na dalšího hráče { ui.PcInfo(); int[] move = null; Brain brain = new Brain(board, rules); Thread pc = new Thread(() => move = brain.GetBestMove(rules.PlayerOnMove() == 1 ? player1 : player2)); pc.IsBackground = true; pc.Start(); ConsoleKey pressKey = ConsoleKey.A; while (pc.IsAlive && pressKey != ConsoleKey.Escape && pressKey != ConsoleKey.Z) { if (Console.KeyAvailable) { pressKey = Console.ReadKey().Key; } } if (pressKey == ConsoleKey.Escape) { pc.Abort(); Start(); //zobrazení menu Game(); //start hry continue; } if (pressKey == ConsoleKey.Z) { pc.Abort(); ui.SelectPlayer(out player1, out player2); continue; } else { board.Move(move, true, false); } //pokud tah není skok tak se navýší počítadlo TahuBezSkoku if (move.Length == 8) { board.tahuBezSkoku++; } else { board.tahuBezSkoku = 0; } kolo = board.HistoryMove.Count / 2; //přičtení do počítadla kol rules.ChangePlayer(); rules.MovesGenerate(); //Thread.Sleep(1500); continue; } //Tahy Hráče int[] vstup = null; int[] plnyVstup = null; bool platnyVstup = false; while (!platnyVstup) //Dokud je vstup !playtnyVstup tak pokračuje { vstup = ui.InputUser(rules.PlayerOnMove(), board); //pokud -1 tak se podmínka neprovede protože -1 >= 0, pokud 0 tak se provede 0=0 a zkontroluje se platnost tahu //Výpis historie tahu if (vstup[0] == -4) { ui.PrintHelpMove(board.HistoryMove, board); } //Možnost tahu zpět/undo if (vstup[0] == -3) { if (ptrTah > 0) { ptrTah--; posledniTah = board.HistoryMove[ptrTah]; moveServices.TahZpet(board, rules, ui, ptrTah, posledniTah, kolo); //ptrTah--; //posledniTah = board.HistoryMove[ptrTah]; //board.Move(posledniTah, false, true); //rules.ChangePlayer(); //Console.Clear(); //kolo = board.HistoryMove.Count / 2; //ui.PocetKol(kolo); //board.VypocitejTahyBezSkoku(ptrTah); //ui.PocetTahuBezSkoku(board.tahuBezSkoku); //ui.PrintBoard(board); //rules.MovesGenerate(); } } //Možnost tahu vpřed/redo if (vstup[0] == -6) { if (ptrTah < board.HistoryMove.Count && board.HistoryMove.Count > 0) { posledniTah = board.HistoryMove[ptrTah]; moveServices.TahVpred(board, rules, ui, ptrTah, posledniTah, kolo); //board.Move(posledniTah, false, false); //ptrTah++; //rules.ChangePlayer(); //Console.Clear(); //kolo = board.HistoryMove.Count / 2; //ui.PocetKol(kolo); //board.VypocitejTahyBezSkoku(ptrTah); //ui.PocetTahuBezSkoku(board.tahuBezSkoku); //ui.PrintBoard(board); //rules.MovesGenerate(); } } //Pokud hráč do konzole zadá HELP if (vstup[0] == -2) { if (vstup.Length > 1) //Pokud ještě zadá pro jakou figurku chce help { ui.PrintHelpMove(rules.GetMovesList(vstup[1], vstup[2]), board); //pro zadanou figurku } else //Vypíše všechny možné tahy hráče na tahu { ui.PrintHelpMove(rules.GetMovesList(), board); //všechny možné tahy hráče //ui.PrintHelpMove(board.HistoryMove); //všechny možné tahy hráče } } //SPRÁVNĚ if (vstup[0] >= 0) //pokud je zadán správný pohyb tj A2-B3 { plnyVstup = rules.FullMove(vstup); //převedení na kompletní pohyb který se skládá ze 4 souřadnic X,Y, stav před, stav po platnyVstup = plnyVstup[0] != -1; //ověření zda je táhnuto dle pravidel, typ bool ve while cyklu ClearHistoryFromToEnd(ptrTah); if (!platnyVstup) //pokud není vypíše uživately chybu { ui.Mistake(); //chyba } } //Uložení hry if (vstup[0] == -8) { data.SaveGame(player1, player2, ptrTah, board.HistoryMove); } //Načítání hry if (vstup[0] == -9) { Board loadBoard; Rules loadRules; int loadPlayer1, loadPlayer2; if (data.LoadGame(out loadBoard, out loadRules, out loadPlayer1, out loadPlayer2, out int loadUkazatel, out int loadTahuBezSkoku)) { board = loadBoard; rules = loadRules; player1 = loadPlayer1; player2 = loadPlayer2; ptrTah = board.HistoryMove.Count; board.tahuBezSkoku = loadTahuBezSkoku; while (ptrTah > loadUkazatel) //pokud aktuální ukazatel je větší než načtený { ptrTah--; //aktualní se zmenší board.Move(board.HistoryMove[ptrTah], false, true); rules.ChangePlayer(); } Console.Clear(); kolo = board.HistoryMove.Count / 2; ui.PocetKol(kolo); ui.PocetTahuBezSkoku(board.tahuBezSkoku); ui.PrintBoard(board); rules.MovesGenerate(); } else { ui.Mistake(); } } //Zpět do menu if (vstup[0] == -5) { Console.Clear(); Start(); Game(); } } board.Move(plnyVstup, true, false); //pokud je zadáno správně, metoda nastaví pohyb na desce ptrTah = board.HistoryMove.Count; //počítání kol kolo = board.HistoryMove.Count / 2; if (plnyVstup.Length == 8) { board.tahuBezSkoku++; } else { board.tahuBezSkoku = 0; } if (rules.ListMove.Count == 0) //pokud je ListMove prázdnej tak se změní hráč na tahu a vygenerují se pro něj nové možné tahy { rules.ChangePlayer(); rules.MovesGenerate(); } else //pokud v listu stále je možnost, tak pokračuje hráč, vícenásobné skoky { continue; } }