/// <summary> /// Funkce minimaxu /// </summary> /// <param name="gb">instance tridy hraci desky</param> /// <param name="depth">hloubka minimaxu</param> /// <returns></returns> private double minimax(Gameboard gb, int depth) { // pokud je na tahu bily hrac if (gb.PlayingWhite) { // a vitez je nastaven na bileho hrace vrat MAX if (gb.Winner == status.whitePlayer) { return(-GlobalVariables.MAX); } // a vitez je nastaven na cerneho hrace vrat -MAX if (gb.Winner == status.blackPlayer) { return(GlobalVariables.MAX); } // a je remiza, vrat 0 if (gb.Winner == status.draw) { return(0); } } // pokud je na tahu cerny hrac else { // a je vitez nastaven na cerneho hrace, vrat MAX if (gb.Winner == status.blackPlayer) { return(-GlobalVariables.MAX); } // a je vitez nastaven na bileho hrace, vrat -MAX if (gb.Winner == status.whitePlayer) { return(GlobalVariables.MAX); } // a je remiza, vrat 0 if (gb.Winner == status.draw) { return(0); } } if (depth == 0) { return(evalFunction(gb)); } else { List <Fairway> moves = generateMoves(gb); double rank = -GlobalVariables.MAX; for (int i = 0; i < moves.Count; i += 2) { // potomek <- zahraj(pozice, tah) Gameboard potomek = gb.gameboardCopy(); rules.makeMove(moves[i], moves[i + 1], potomek, true); rank = Math.Max(rank, -minimax(potomek, depth - 1)); } return(rank); } }
/// <summary> /// Funkce generujici pole hracich poli, na ktere jde tahnout /// </summary> /// <param name="gb">Instrance tridy hraci deska</param> /// <param name="fw">Instance tridy hraci pole</param> /// <returns>Vraci List hracich poli, na ktere je mozno figurkou tahnout</returns> private List <Fairway> generateDests(Gameboard gb, Fairway fw) { var dest = new List <Fairway>(); var temp = new List <String>(); if (fw.Jump) { for (int i = 0; i < fw.Dests.Count; i++) { foreach (var jump in fw.Dests) { string[] jumps = jump.Split('-'); temp.Add(jumps[0]); } } } else { temp = fw.Moves; } foreach (var fair in gb.Board) { if (temp.Contains(fair.Name)) { dest.Add(fair); } } return(dest); }
private void genQueMoves(Gameboard gb, Fairway fw) { status playerOnMove = gb.PlayingWhite ? status.whitePlayer : status.blackPlayer; List <string> moves = fw.Moves; int x = Convert.ToInt32(fw.Name.Substring(1)) - 1; int y = Convert.ToInt32(fw.Name[0]) - 'A'; int temp = 0; for (int i = 0; i < 8; i++) { for (int j = 1; x + j * xs[i] < GlobalVariables.size && x + j * xs[i] >= 0 && y + j * ys[i] >= 0 && y + j * ys[i] < GlobalVariables.size && gb.Board[x + j * xs[i], y + j * ys[i]].Player == status.free; j++) { if (gb.Board[x + j * xs[i], y + j * ys[i]].Player == 0) { string move = (char)(y + j * ys[i] + 'A') + "" + (x + j * xs[i] + 1); moves.Add(move); } temp = j + 1; } fw.StoneMove = moves.Count > 0 ? true : false; genQueJumpTree(gb, fw); } }
private void loadGame_Click(object sender, EventArgs e) { var ofd = new OpenFileDialog(); ofd.Filter = "XML soubor (*.xml)|*.xml"; ofd.Title = "Načtení uložené hry"; if (ofd.ShowDialog() == DialogResult.OK) { try { cleanHistory(); var sl = new SaveLoad(); gb = sl.loadGame(ofd.FileName, gb); gb.drawBoard(); gb.colorUp(); pauseGame(); } catch (Exception ex) { MessageBox.Show(String.Format("Hru se nepodařilo načíst!\n{0}", ex.Message)); cleanHistory(); } } else { MessageBox.Show("Hru se nepodařilo načíst!"); } }
/// <summary> /// Fuknce generujici nejlepsi tah /// </summary> /// <param name="gb">instance tridy hraci deska</param> /// <param name="depth">hloubka minimaxu</param> /// <returns>Vraci list dvou hracich poli, kde na 1. miste je tah odkud a na 2. poli kam</returns> public List<Fairway> bestMove(Gameboard gb, int depth) { Gameboard potomek = gb.gameboardCopy(); rules.generateMoves(potomek); List<Fairway> moves = generateMoves(potomek); var bestMove = new List<Fairway>(); double bestRank = -GlobalVariables.MAX; for (int i = 0; i < moves.Count; i += 2) { // potomek <- zahraj(pozice, tah) rules.makeMove(moves[i], moves[i + 1], potomek, true); double rank; if (depth == 0) rank = evalFunction(potomek); else rank = -minimax(potomek, depth - 1); if (rank > bestRank) { bestMove = new List<Fairway>(); bestRank = rank; bestMove.Add(moves[i]); bestMove.Add(moves[i + 1]); } if (rank == bestRank) { bestMove.Add(moves[i]); bestMove.Add(moves[i + 1]); } } return bestMove; }
/* * public Fairway getFairway(string name) * { * for (int i = 0; i < GlobalVariables.size; i++) * { * for (int j = 0; j < GlobalVariables.size; j++) * { * if (this.Board[j, i].Name == name) * return this.Board[j, i]; * } * } * return null; * } * */ #endregion Funkce pro nalezení hracího pole a možných tahů figurky #region Funkce pracující s hrací deskou /// <summary> /// Funkce nevytvari kopii historie (undo a redo), zobrazeni napovedy a slotu Fairway From /// </summary> /// <returns></returns> public Gameboard gameboardCopy() { var result = new Gameboard(); //* result.Board = new Fairway[GlobalVariables.size, GlobalVariables.size]; for (int i = 0; i < GlobalVariables.size; i++) { for (int j = 0; j < GlobalVariables.size; j++) { result.Board[i, j] = Board[i, j].Clone(); } } result.playingWhite = PlayingWhite; result.BlackPlayer = BlackPlayer; result.WhitePlayer = WhitePlayer; result.MovesWithoutJump = MovesWithoutJump; result.ShowMoveHelp = ShowMoveHelp; result.From = From; result.Winner = Winner; //*/ return(result); }
private Fairway randomFrom(Gameboard gb) { rules.generateMoves(gb); List <Fairway> stones = rules.choosableFigures(gb); int position = random.Next(0, stones.Count); return(stones[position]); }
private Fairway randomTo(Gameboard gb, Fairway fw) { List <string> destinations = gb.possibleMoves(fw); int position = random.Next(0, destinations.Count); string name = destinations[position]; return(gb.getFigure(name)); }
public Gameboard playAI(Gameboard gb, BackgroundWorker worker) { if (gb.PlayingWhite) gb = aiSwitcher(gb, gb.WhitePlayer); else gb = aiSwitcher(gb, gb.BlackPlayer); return gb; }
private void randomAI(Gameboard gb) { Fairway from = randomFrom(gb); Fairway to = randomTo(gb, from); gb.addHistory(from, to); rules.makeMove(from, to, gb, true); }
private void disableAllFairways(Gameboard gb) { Action <Fairway> disable = (fw) => fw.Enabled = false; foreach (var fw in gb.Board) { fw.Invoke(disable, fw); } }
public void generateMoves(Gameboard gb) { status playerOnMove = gb.PlayingWhite ? status.whitePlayer : status.blackPlayer; foreach (var fw in gb.Board) { if (fw.Player == playerOnMove) { generateMoves(gb, fw); } } }
public Gameboard playAI(Gameboard gb, BackgroundWorker worker) { if (gb.PlayingWhite) { gb = aiSwitcher(gb, gb.WhitePlayer); } else { gb = aiSwitcher(gb, gb.BlackPlayer); } return(gb); }
private void genWalMoves(Gameboard gb, Fairway fw) { if (!gb.PlayingWhite) { walkersMoves(gb, fw, 1, -1); walkersMoves(gb, fw, 1, 1); } else { walkersMoves(gb, fw, -1, -1); walkersMoves(gb, fw, -1, 1); } }
private void genJumps(Gameboard gb, Fairway fw) { int x, y; TreeNode root = fw.Queen ? genQueJumpTree(gb, fw) : genWalJumpTree(gb, fw); fw.Ranks = new List <int>(); fw.Dests = new List <string>(); fw.Overs = new List <string>(); List <string> routes = root.allRoutes(root); foreach (var route in routes) { var r = new List <string>(route.Split('-')); r.RemoveAll(c => c.Equals("")); int rank = 0; string dest = ""; string over = ""; for (int i = 0; i < r.Count; i += 2) { x = Convert.ToInt32(r[i].Substring(1)) - 1; y = Convert.ToInt32(r[i][0]) - 'A'; rank += gb.Board[x, y].Queen ? 3 : 2; if (over == "") { over = r[i]; } else { over = over + "-" + r[i]; } if (dest == "") { dest = r[i + 1]; } else { dest = dest + "-" + r[i + 1]; } } if (rank > 0 && dest != "" && over != "") { fw.Ranks.Add(rank); fw.Dests.Add(dest); fw.Overs.Add(over); } } fw.Jump = fw.Ranks.Count > 0 ? true : false; }
private void enableallFairways(Gameboard gb) { Action <Fairway> enable = (fw) => fw.Enabled = true; for (int i = 0; i < GlobalVariables.size; i++) { for (int j = 0; j < GlobalVariables.size; j++) { if ((i + j) % 2 == 1) { gb.Board[i, j].Invoke(enable, gb.Board[i, j]); } } } }
/// <summary> /// Funkce kontrolujici, zda uz byla hra dohrana /// </summary> /// <param name="gb">Instance tridy hraci deska</param> /// <returns>status.free pokud nikdo nevyhral, status.draw, pokud 60 tahu nedoslo ke skoku v ostatnich pripadech vraci status.[vyherce]</returns> public status checkWinner(Gameboard gb) { var result = status.free; // pokud se 60 tahu netahlo, remiza if (gb.MovesWithoutJump == GlobalVariables.draw) result = status.draw; // pokud pocet figur, se kterymi muze dany hrac tahnout = 0, vyhrava protihrac if (choosableFigures(gb).Count == 0) { if (gb.PlayingWhite) result = status.blackPlayer; else result = status.whitePlayer; } return result; }
/// <summary> /// Funkce vracejici hracovi vybratelne figury /// </summary> /// <param name="gb">Instance hraci desky</param> /// <returns>pole hracich poli, jemiz je mozne tahnout</returns> public List <Fairway> choosableFigures(Gameboard gb) { var result = new List <Fairway>(); status player = gb.PlayingWhite ? status.whitePlayer : status.blackPlayer; int rank = 0; // projdeme vsechny hraci policka foreach (var fw in gb.Board) { // pokud se jedna o hracovu figurku if (fw.Player == player) { // a pokud muze figurka skakat if (fw.Jump) { // tak pro kazdy mozny skok for (int i = 0; i < fw.Ranks.Count; i++) { // pokud je rank skoku vyssi, nez dosavadni rank, rank nastavime na novou hodnotu // vymazeme dosavadni vysledek a pridame aktualni pole if (fw.Ranks[i] > rank) { rank = fw.Ranks[i]; result = new List <Fairway>(); result.Add(fw); } // pokud je rank stejny, jak nynejsi hodnota, pridame pole mezi vysledky else if (fw.Ranks[i] == rank) { result.Add(fw); } } } // pokud figurka nemuze skakat a rank je na hodnote 0 (neni znam zadny dosavadni skok) // a figurka se muze hybat, pridame ji do vysledku else if (rank == 0 && fw.StoneMove) { if (!result.Contains(fw)) { result.Add(fw); } } } } // vratime vysledek return(result); }
/// <summary> /// Funkce generujici veskere mozne tahy na hraci desce /// </summary> /// <param name="gb">Instance tridy hraci deska</param> /// <returns>Vraci pole hracich poli, kde na lichem miste je ulozeno pole odkud bylo tazeno a na sudem miste pole, kam bylo tazeno</returns> private List <Fairway> generateMoves(Gameboard gb) { List <Fairway> movable = rules.choosableFigures(gb); var moves = new List <Fairway>(); foreach (var fw in movable) { List <string> dests = gb.possibleMoves(fw); foreach (var destination in dests) { moves.Add(fw); moves.Add(gb.getFigure(destination)); } } return(moves); }
/// <summary> /// Funkce vracejici hracovi vybratelne figury /// </summary> /// <param name="gb">Instance hraci desky</param> /// <returns>pole hracich poli, jemiz je mozne tahnout</returns> public List<Fairway> choosableFigures(Gameboard gb) { var result = new List<Fairway>(); status player = gb.PlayingWhite ? status.whitePlayer : status.blackPlayer; int rank = 0; // projdeme vsechny hraci policka foreach (var fw in gb.Board) { // pokud se jedna o hracovu figurku if (fw.Player == player) { // a pokud muze figurka skakat if (fw.Jump) { // tak pro kazdy mozny skok for (int i = 0; i < fw.Ranks.Count; i++) { // pokud je rank skoku vyssi, nez dosavadni rank, rank nastavime na novou hodnotu // vymazeme dosavadni vysledek a pridame aktualni pole if (fw.Ranks[i] > rank) { rank = fw.Ranks[i]; result = new List<Fairway>(); result.Add(fw); } // pokud je rank stejny, jak nynejsi hodnota, pridame pole mezi vysledky else if (fw.Ranks[i] == rank) { result.Add(fw); } } } // pokud figurka nemuze skakat a rank je na hodnote 0 (neni znam zadny dosavadni skok) // a figurka se muze hybat, pridame ji do vysledku else if (rank == 0 && fw.StoneMove) { if (!result.Contains(fw)) result.Add(fw); } } } // vratime vysledek return result; }
private Gameboard aiSwitcher(Gameboard gb, int difficulty) { switch (difficulty) { case 1: randomAI(gb); break; case 2: gb = MiniMaxAI(gb, 2); break; case 3: gb = MiniMaxAI(gb, 3); break; } return gb; }
private void walkersMoves(Gameboard gb, Fairway fw, int dx, int dy) { int x = Convert.ToInt32(fw.Name.Substring(1)) - 1; int y = Convert.ToInt32(fw.Name[0]) - 'A'; if (x + dx >= 0 && x + dx < GlobalVariables.size && y + dy >= 0 && y + dy < GlobalVariables.size && gb.Board[x + dx, y + dy].Player == 0) { List <String> moves = fw.Moves; moves.Add((char)(y + dy + 'A') + "" + (x + dx + 1)); fw.StoneMove = moves.Count > 0 ? true : false; fw.Moves = moves; } fw.StoneMove = fw.Moves.Count > 0 ? true : false; }
private Gameboard aiSwitcher(Gameboard gb, int difficulty) { switch (difficulty) { case 1: randomAI(gb); break; case 2: gb = MiniMaxAI(gb, 2); break; case 3: gb = MiniMaxAI(gb, 3); break; } return(gb); }
/// <summary> /// Funkce kontrolujici, zda v danem smeru je za figurkou volno /// </summary> /// <param name="gb">Instance tridy hraci deska</param> /// <param name="fw">Instance tridy hraci pole reprezentujici odkud kontrolujeme</param> /// <param name="dx">X smer kterym kontrolujeme</param> /// <param name="dy">Y smer kterym kontrolujeme</param> /// <returns>True, pokud je za figurou v danem smeru volno, jinak false</returns> private bool checkPossibleJump(Gameboard gb, Fairway fw, int dx, int dy) { status playerOnMove = gb.PlayingWhite ? status.whitePlayer : status.blackPlayer; int x = Convert.ToInt32(fw.Name.Substring(1)) - 1; int y = Convert.ToInt32(fw.Name[0]) - 'A'; if (x + 2 * dx < GlobalVariables.size && x + 2 * dx >= 0 && y + 2 * dy < GlobalVariables.size && y + 2 * dy >= 0 && (int)gb.Board[x + dx, y + dy].Player == -(int)playerOnMove && gb.Board[x + 2 * dx, y + 2 * dy].Player == 0) { return(true); } else { return(false); } }
private List <Fairway> queAfterJumpDests(Gameboard gb, Fairway fw, int dx, int dy) { var result = new List <Fairway>(); int x = Convert.ToInt32(fw.Name.Substring(1)) - 1; int y = Convert.ToInt32(fw.Name[0]) - 'A'; for (int j = 0; x + dx < GlobalVariables.size && x + dx >= 0 && y + dy < GlobalVariables.size && y + dy >= 0 && (gb.Board[x + dx, y + dy].Player == status.free); j++) { result.Add(gb.Board[x + dx, y + dy]); x += dx; y += dy; } return(result); }
// funkce obarvujici mozne tahy figurkou private void fairwayColorUp(Gameboard gb, Fairway fw) { List <string> moves = fw.Moves; for (int i = 0; i < GlobalVariables.size; i++) { for (int j = 0; j < GlobalVariables.size; j++) { Fairway chosen = gb.Board[i, j]; if (moves.Contains(chosen.Name) && gb.ShowMoveHelp) { chosen.BackgroundImage = Resources.board_dark_active; } else { chosen.BackgroundImage = ((i + j) % 2 == 1) ? Resources.board_dark : Resources.board_light; } } } fw.BackgroundImage = Resources.board_dark_active_figure; }
/// <summary> /// Fuknce generujici nejlepsi tah /// </summary> /// <param name="gb">instance tridy hraci deska</param> /// <param name="depth">hloubka minimaxu</param> /// <returns>Vraci list dvou hracich poli, kde na 1. miste je tah odkud a na 2. poli kam</returns> public List <Fairway> bestMove(Gameboard gb, int depth) { Gameboard potomek = gb.gameboardCopy(); rules.generateMoves(potomek); List <Fairway> moves = generateMoves(potomek); var bestMove = new List <Fairway>(); double bestRank = -GlobalVariables.MAX; for (int i = 0; i < moves.Count; i += 2) { // potomek <- zahraj(pozice, tah) rules.makeMove(moves[i], moves[i + 1], potomek, true); double rank; if (depth == 0) { rank = evalFunction(potomek); } else { rank = -minimax(potomek, depth - 1); } if (rank > bestRank) { bestMove = new List <Fairway>(); bestRank = rank; bestMove.Add(moves[i]); bestMove.Add(moves[i + 1]); } if (rank == bestRank) { bestMove.Add(moves[i]); bestMove.Add(moves[i + 1]); } } return(bestMove); }
private Gameboard MiniMaxAI(Gameboard gb, int depth) { List <Fairway> bMove = bestMove(gb, depth); string f = bMove[0].Name; string t = bMove[1].Name; var from = new Fairway(); var to = new Fairway(); foreach (var fw in gb.Board) { from = fw.Name == f ? fw : from; to = fw.Name == t ? fw : to; } rules.generateMoves(gb, from); gb.addHistory(from, to); rules.makeMove(from, to, gb, true); return(gb); }
private TreeNode genWalJumpTree(Gameboard gb, Fairway fw) { var root = new TreeNode(); int x = Convert.ToInt32(fw.Name.Substring(1)) - 1; int y = Convert.ToInt32(fw.Name[0]) - 'A'; for (int i = 0; i < 8; i++) { if (checkPossibleJump(gb, fw, xs[i], ys[i])) { Gameboard potomek = gb.gameboardCopy(); Fairway from = potomek.Board[x, y]; Fairway over = potomek.Board[x + xs[i], y + ys[i]]; Fairway to = potomek.Board[x + 2 * xs[i], y + 2 * ys[i]]; TreeNode jump; bool bQ = from.Queen; makeJump(from, over, to); bool aQ = to.Queen; if (bQ == aQ) { jump = genWalJumpTree(potomek, to); } else { jump = new TreeNode(); } jump.over = over.Name; jump.dest = to.Name; root.childs.Add(jump); jump.rank = over.Queen ? 3 : 2; } } return(root); }
/// <summary> /// Funkce kontrolujici, zda uz byla hra dohrana /// </summary> /// <param name="gb">Instance tridy hraci deska</param> /// <returns>status.free pokud nikdo nevyhral, status.draw, pokud 60 tahu nedoslo ke skoku v ostatnich pripadech vraci status.[vyherce]</returns> public status checkWinner(Gameboard gb) { var result = status.free; // pokud se 60 tahu netahlo, remiza if (gb.MovesWithoutJump == GlobalVariables.draw) { result = status.draw; } // pokud pocet figur, se kterymi muze dany hrac tahnout = 0, vyhrava protihrac if (choosableFigures(gb).Count == 0) { if (gb.PlayingWhite) { result = status.blackPlayer; } else { result = status.whitePlayer; } } return(result); }
/// <summary> /// Funkce provadejici nacteni hry a zkontrolovani, zda se jedna o korektni ulozeni /// </summary> /// <param name="filePath">cesta k souboru</param> /// <param name="gb">Hraci deska, na niz maji byt zmeny provedeny</param> /// <returns>Hraci desku s odehratou hrou</returns> public Gameboard loadGame(string filePath, Gameboard gb) { string from = ""; string to = ""; Fairway fwFrom; Fairway fwTo; Rules rules = new Rules(); gb.Board = gb.newBoard(); using (XmlReader reader = XmlReader.Create(filePath)) { while (reader.Read()) { if (reader.IsStartElement()) { switch (reader.Name) { // nacteme si obtiznost bileho hrace a nastavime case "WHITE": if (reader.Read()) { int whitePlayer = Convert.ToInt32(reader.Value.Trim()); gb.WhitePlayer = whitePlayer; } break; // nacteme si obtiznost cerneho hrace a nastavime case "BLACK": if (reader.Read()) { int blackPlayer = Convert.ToInt32(reader.Value.Trim()); gb.BlackPlayer = blackPlayer; } break; // nacteme si zacinajiciho hrace a nastavime case "STARTS": if (reader.Read()) { bool startsWhite = Convert.ToBoolean(reader.Value.Trim()); gb.StartsWhite = startsWhite; } break; // case "SHOWHELP": if (reader.Read()) { bool showHelp = Convert.ToBoolean(reader.Value.Trim()); gb.ShowMoveHelp = showHelp; } break; case "FROM": if (reader.Read()) from = (string)reader.Value.Trim(); break; case "TO": if (reader.Read()) to = (string)reader.Value.Trim(); fwFrom = gb.getFigure(from); fwTo = gb.getFigure(to); rules.generateMoves(gb); rules.makeMove(fwFrom, fwTo, gb, false); gb.addHistory(fwFrom, fwTo); break; default: break; } } } } return gb; }
private void enableallFairways(Gameboard gb) { Action<Fairway> enable = (fw) => fw.Enabled = true; for (int i = 0; i < GlobalVariables.size; i++) { for (int j = 0; j < GlobalVariables.size; j++) { if ((i + j) % 2 == 1) gb.Board[i, j].Invoke(enable, gb.Board[i, j]); } } }
// funkce obarvujici mozne tahy figurkou private void fairwayColorUp(Gameboard gb, Fairway fw) { List<string> moves = fw.Moves; for (int i = 0; i < GlobalVariables.size; i++) { for (int j = 0; j < GlobalVariables.size; j++) { Fairway chosen = gb.Board[i, j]; if (moves.Contains(chosen.Name) && gb.ShowMoveHelp) chosen.BackgroundImage = Resources.board_dark_active; else chosen.BackgroundImage = ((i + j)%2 == 1) ? Resources.board_dark : Resources.board_light; } } fw.BackgroundImage = Resources.board_dark_active_figure; }
public GameSettings(Gameboard gb, bool newGame) { InitializeComponent(); this.gb = gb; setSettingsWindow(gb, newGame); }
private Fairway randomTo(Gameboard gb, Fairway fw) { List<string> destinations = gb.possibleMoves(fw); int position = random.Next(0, destinations.Count); string name = destinations[position]; return gb.getFigure(name); }
public void startGame(Gameboard gb) { generateMoves(gb); }
private TreeNode genWalJumpTree(Gameboard gb, Fairway fw) { var root = new TreeNode(); int x = Convert.ToInt32(fw.Name.Substring(1)) - 1; int y = Convert.ToInt32(fw.Name[0]) - 'A'; for (int i = 0; i < 8; i++) { if (checkPossibleJump(gb, fw, xs[i], ys[i])) { Gameboard potomek = gb.gameboardCopy(); Fairway from = potomek.Board[x, y]; Fairway over = potomek.Board[x + xs[i], y + ys[i]]; Fairway to = potomek.Board[x + 2*xs[i], y + 2*ys[i]]; TreeNode jump; bool bQ = from.Queen; makeJump(from, over, to); bool aQ = to.Queen; if (bQ == aQ) jump = genWalJumpTree(potomek, to); else jump = new TreeNode(); jump.over = over.Name; jump.dest = to.Name; root.childs.Add(jump); jump.rank = over.Queen ? 3 : 2; } } return root; }
/// <summary> /// Funkce kontrolujici, zda v danem smeru je za figurkou volno /// </summary> /// <param name="gb">Instance tridy hraci deska</param> /// <param name="fw">Instance tridy hraci pole reprezentujici odkud kontrolujeme</param> /// <param name="dx">X smer kterym kontrolujeme</param> /// <param name="dy">Y smer kterym kontrolujeme</param> /// <returns>True, pokud je za figurou v danem smeru volno, jinak false</returns> private bool checkPossibleJump(Gameboard gb, Fairway fw, int dx, int dy) { status playerOnMove = gb.PlayingWhite ? status.whitePlayer : status.blackPlayer; int x = Convert.ToInt32(fw.Name.Substring(1)) - 1; int y = Convert.ToInt32(fw.Name[0]) - 'A'; if (x + 2*dx < GlobalVariables.size && x + 2*dx >= 0 && y + 2*dy < GlobalVariables.size && y + 2*dy >= 0 && (int) gb.Board[x + dx, y + dy].Player == -(int) playerOnMove && gb.Board[x + 2*dx, y + 2*dy].Player == 0) return true; else return false; }
private void walkersMoves(Gameboard gb, Fairway fw, int dx, int dy) { int x = Convert.ToInt32(fw.Name.Substring(1)) - 1; int y = Convert.ToInt32(fw.Name[0]) - 'A'; if (x + dx >= 0 && x + dx < GlobalVariables.size && y + dy >= 0 && y + dy < GlobalVariables.size && gb.Board[x + dx, y + dy].Player == 0) { List<String> moves = fw.Moves; moves.Add((char) (y + dy + 'A') + "" + (x + dx + 1)); fw.StoneMove = moves.Count > 0 ? true : false; fw.Moves = moves; } fw.StoneMove = fw.Moves.Count > 0 ? true : false; }
private Gameboard MiniMaxAI(Gameboard gb, int depth) { List<Fairway> bMove = bestMove(gb, depth); string f = bMove[0].Name; string t = bMove[1].Name; var from = new Fairway(); var to = new Fairway(); foreach (var fw in gb.Board) { from = fw.Name == f ? fw : from; to = fw.Name == t ? fw : to; } rules.generateMoves(gb, from); gb.addHistory(from, to); rules.makeMove(from, to, gb, true); return gb; }
public void generateMoves(Gameboard gb) { status playerOnMove = gb.PlayingWhite ? status.whitePlayer : status.blackPlayer; foreach (var fw in gb.Board) { if (fw.Player == playerOnMove) generateMoves(gb, fw); } }
private TreeNode genQueJumpTree(Gameboard gb, Fairway fw) { var root = new TreeNode(); var moves = new List<string>(); int x = Convert.ToInt32(fw.Name.Substring(1)) - 1; int y = Convert.ToInt32(fw.Name[0]) - 'A'; status playerOnMove = gb.PlayingWhite ? status.whitePlayer : status.blackPlayer; for (int i = 0; i < 8; i++) { bool jump = false; for (int j = 1; x + j*xs[i] < GlobalVariables.size && x + j*xs[i] >= 0 && y + j*ys[i] < GlobalVariables.size && y + j*ys[i] >= 0; j++) { // pokud je vedle volno, pridej do moves if (gb.Board[x + j*xs[i], y + j*ys[i]].Player == status.free && !jump) { string move = (char) (y + j*ys[i] + 'A') + "" + (x + j*xs[i] + 1); } // pokud je vedle tvoje vlastni figurka, prerus else if (gb.Board[x + j*xs[i], y + j*ys[i]].Player == playerOnMove) { break; } else if ( x + (j + 1)*xs[i] < GlobalVariables.size && x + (j + 1)*xs[i] >= 0 && y + (j + 1)*ys[i] >= 0 && y + (j + 1)*ys[i] < GlobalVariables.size && (int) gb.Board[x + j*xs[i], y + j*ys[i]].Player == -(int) playerOnMove && gb.Board[x + (j + 1)*xs[i], y + (j + 1)*ys[i]].Player == status.free) { jump = true; Gameboard potomek = gb.gameboardCopy(); Fairway from = potomek.Board[x, y]; Fairway over = potomek.Board[x + j*xs[i], y + j*ys[i]]; Fairway to = potomek.Board[x + (j + 1)*xs[i], y + (j + 1)*ys[i]]; makeJump(from, over, to); List<Fairway> destinies = queAfterJumpDests(potomek, to, xs[i], ys[i]); destinies.Insert(0, to); foreach (var des in destinies) { TreeNode node = genQueJumpTree(potomek, des); node.over = over.Name; node.dest = des.Name; node.rank = over.Queen ? 3 : 2; root.childs.Add(node); } } else { break; } } } return root; }
/// <summary> /// Funkce generujici pole hracich poli, na ktere jde tahnout /// </summary> /// <param name="gb">Instrance tridy hraci deska</param> /// <param name="fw">Instance tridy hraci pole</param> /// <returns>Vraci List hracich poli, na ktere je mozno figurkou tahnout</returns> private List<Fairway> generateDests(Gameboard gb, Fairway fw) { var dest = new List<Fairway>(); var temp = new List<String>(); if (fw.Jump) { for (int i = 0; i < fw.Dests.Count; i++) { foreach (var jump in fw.Dests) { string[] jumps = jump.Split('-'); temp.Add(jumps[0]); } } } else temp = fw.Moves; foreach (var fair in gb.Board) { if (temp.Contains(fair.Name)) dest.Add(fair); } return dest; }
private List<Fairway> queAfterJumpDests(Gameboard gb, Fairway fw, int dx, int dy) { var result = new List<Fairway>(); int x = Convert.ToInt32(fw.Name.Substring(1)) - 1; int y = Convert.ToInt32(fw.Name[0]) - 'A'; for (int j = 0; x + dx < GlobalVariables.size && x + dx >= 0 && y + dy < GlobalVariables.size && y + dy >= 0 && (gb.Board[x + dx, y + dy].Player == status.free); j++) { result.Add(gb.Board[x + dx, y + dy]); x += dx; y += dy; } return result; }
/// <summary> /// Metoda starajici se o nastaveni okna s nastavením v závislosti na parametrech hry /// </summary> /// <param name="gb">Instance tridy hraci deska</param> /// <param name="newGame">hodnota reprezentujici, zda bylo okno vyvolano pomoci menu itemu nova hra nebo nastaveni</param> private void setSettingsWindow(Gameboard gb, bool newGame) { var _whitePlayer = new List <RadioButton>(); var _blackPlayer = new List <RadioButton>(); var _moveHelp = new List <RadioButton>(); var _startingPlayer = new List <RadioButton>(); foreach (Control c in whitePlayer.Controls) { _whitePlayer.Add(c as RadioButton); } foreach (Control c in blackPlayer.Controls) { _blackPlayer.Add(c as RadioButton); } foreach (Control c in moveHelp.Controls) { _moveHelp.Add(c as RadioButton); } foreach (Control c in startingPlayer.Controls) { _startingPlayer.Add(c as RadioButton); } startingPlayer.Enabled = newGame ? true : false; // nastaveni hodnoty zacinajiciho hrace if (gb.PlayingWhite) { startingPlayerWhite.Checked = true; } else { startingPlayerBlack.Checked = true; } // nastaveni hodnoty bileho hrace if (gb.WhitePlayer == 0) { whitePlayerHuman.Checked = true; whiteComputerDifficulty.Enabled = false; lWhiteEasy.Enabled = false; lWhiteNormal.Enabled = false; lWhiteHard.Enabled = false; } else { whitePlayerPc.Checked = true; whiteComputerDifficulty.Enabled = true; whiteComputerDifficulty.Value = gb.WhitePlayer; lWhiteEasy.Enabled = true; lWhiteNormal.Enabled = true; lWhiteHard.Enabled = true; } // nastaveni hodnoty cerneho hrace if (gb.BlackPlayer == 0) { blackPlayerHuman.Checked = true; blackComputerDifficulty.Enabled = false; } else { blackPlayerPc.Checked = true; blackComputerDifficulty.Enabled = true; blackComputerDifficulty.Value = gb.BlackPlayer; } // nastaveni zobrazovani napovedy if (gb.ShowMoveHelp) { moveHelpYes.Checked = true; } else { moveHelpNo.Checked = true; } gameSettingsInfo.Text = ""; if (newGame) { settingsSave.Enabled = false; saveSettingsStartNewGame.Enabled = true; Text = "Nová hra - nastavení"; } else { Text = "Nastavení hry"; } AcceptButton = newGame ? saveSettingsStartNewGame : settingsSave; CancelButton = settingsStorno; this.gb = gb; }
/// <summary> /// Funkce minimaxu /// </summary> /// <param name="gb">instance tridy hraci desky</param> /// <param name="depth">hloubka minimaxu</param> /// <returns></returns> private double minimax(Gameboard gb, int depth) { // pokud je na tahu bily hrac if (gb.PlayingWhite) { // a vitez je nastaven na bileho hrace vrat MAX if (gb.Winner == status.whitePlayer) return -GlobalVariables.MAX; // a vitez je nastaven na cerneho hrace vrat -MAX if (gb.Winner == status.blackPlayer) return GlobalVariables.MAX; // a je remiza, vrat 0 if (gb.Winner == status.draw) return 0; } // pokud je na tahu cerny hrac else { // a je vitez nastaven na cerneho hrace, vrat MAX if (gb.Winner == status.blackPlayer) return -GlobalVariables.MAX; // a je vitez nastaven na bileho hrace, vrat -MAX if (gb.Winner == status.whitePlayer) return GlobalVariables.MAX; // a je remiza, vrat 0 if (gb.Winner == status.draw) return 0; } if (depth == 0) return evalFunction(gb); else { List<Fairway> moves = generateMoves(gb); double rank = -GlobalVariables.MAX; for (int i = 0; i < moves.Count; i += 2) { // potomek <- zahraj(pozice, tah) Gameboard potomek = gb.gameboardCopy(); rules.makeMove(moves[i], moves[i + 1], potomek, true); rank = Math.Max(rank, -minimax(potomek, depth - 1)); } return rank; } }
private void genJumps(Gameboard gb, Fairway fw) { int x, y; TreeNode root = fw.Queen ? genQueJumpTree(gb, fw) : genWalJumpTree(gb, fw); fw.Ranks = new List<int>(); fw.Dests = new List<string>(); fw.Overs = new List<string>(); List<string> routes = root.allRoutes(root); foreach (var route in routes) { var r = new List<string>(route.Split('-')); r.RemoveAll(c => c.Equals("")); int rank = 0; string dest = ""; string over = ""; for (int i = 0; i < r.Count; i += 2) { x = Convert.ToInt32(r[i].Substring(1)) - 1; y = Convert.ToInt32(r[i][0]) - 'A'; rank += gb.Board[x, y].Queen ? 3 : 2; if (over == "") over = r[i]; else over = over + "-" + r[i]; if (dest == "") dest = r[i + 1]; else dest = dest + "-" + r[i + 1]; } if (rank > 0 && dest != "" && over != "") { fw.Ranks.Add(rank); fw.Dests.Add(dest); fw.Overs.Add(over); } } fw.Jump = fw.Ranks.Count > 0 ? true : false; }
public void generateMoves(Gameboard gb, Fairway fw) { genJumps(gb, fw); var newDests = new List <string>(); var newOvers = new List <string>(); if (fw.Jump) { int bestRank = fw.Ranks[0]; int rank = fw.Ranks[0]; fw.Moves = new List <string>(); for (int i = 0; i < fw.Ranks.Count; i++) { rank = fw.Ranks[i]; string[] d = fw.Dests[i].Split('-'); string[] o = fw.Overs[i].Split('-'); if (rank == bestRank) { if (!newDests.Contains(d[0])) { newDests.Add(d[0]); newOvers.Add(o[0]); } if (!fw.Moves.Contains(d[0])) { fw.Moves.Add(d[0]); } } else if (rank > bestRank) { bestRank = rank; fw.Moves = new List <string>(); newDests = new List <string>(); newOvers = new List <string>(); if (!newDests.Contains(d[0])) { newDests.Add(d[0]); } if (!newOvers.Contains(o[0])) { newOvers.Add(o[0]); } if (!fw.Moves.Contains(d[0])) { fw.Moves.Add(d[0]); } } } } else if (fw.Queen) { genQueMoves(gb, fw); } else { genWalMoves(gb, fw); } fw.Overs = newOvers; fw.Dests = newDests; }
/// <summary> /// Metoda starajici se o nastaveni okna s nastavením v závislosti na parametrech hry /// </summary> /// <param name="gb">Instance tridy hraci deska</param> /// <param name="newGame">hodnota reprezentujici, zda bylo okno vyvolano pomoci menu itemu nova hra nebo nastaveni</param> private void setSettingsWindow(Gameboard gb, bool newGame) { List<RadioButton> _whitePlayer = new List<RadioButton>(); List<RadioButton> _blackPlayer = new List<RadioButton>(); List<RadioButton> _moveHelp = new List<RadioButton>(); List<RadioButton> _startingPlayer = new List<RadioButton>(); foreach (Control c in this.whitePlayer.Controls) _whitePlayer.Add(c as RadioButton); foreach (Control c in this.blackPlayer.Controls) _blackPlayer.Add(c as RadioButton); foreach (Control c in this.moveHelp.Controls) _moveHelp.Add(c as RadioButton); foreach (Control c in this.startingPlayer.Controls) _startingPlayer.Add(c as RadioButton); this.startingPlayer.Enabled = newGame ? true : false; // nastaveni hodnoty zacinajiciho hrace if (gb.PlayingWhite) this.startingPlayerWhite.Checked = true; else this.startingPlayerBlack.Checked = true; // nastaveni hodnoty bileho hrace if (gb.WhitePlayer == 0) { this.whitePlayerHuman.Checked = true; this.whiteComputerDifficulty.Enabled = false; this.lWhiteEasy.Enabled = false; this.lWhiteNormal.Enabled = false; this.lWhiteHard.Enabled = false; } else { this.whitePlayerPc.Checked = true; this.whiteComputerDifficulty.Enabled = true; this.whiteComputerDifficulty.Value = gb.WhitePlayer; this.lWhiteEasy.Enabled = true; this.lWhiteNormal.Enabled = true; this.lWhiteHard.Enabled = true; } // nastaveni hodnoty cerneho hrace if (gb.BlackPlayer == 0) { this.blackPlayerHuman.Checked = true; this.blackComputerDifficulty.Enabled = false; } else { this.blackPlayerPc.Checked = true; this.blackComputerDifficulty.Enabled = true; this.blackComputerDifficulty.Value = gb.BlackPlayer; } // nastaveni zobrazovani napovedy if (gb.ShowMoveHelp) this.moveHelpYes.Checked = true; else this.moveHelpNo.Checked = true; this.gameSettingsInfo.Text = ""; if (newGame) { this.settingsSave.Enabled = false; this.saveSettingsStartNewGame.Enabled = true; this.Text = "Nová hra - nastavení"; } else { this.Text = "Nastavení hry"; } this.AcceptButton = newGame ? this.saveSettingsStartNewGame : this.settingsSave; this.CancelButton = this.settingsStorno; this.gb = gb; }
private Fairway randomFrom(Gameboard gb) { rules.generateMoves(gb); List<Fairway> stones = rules.choosableFigures(gb); int position = random.Next(0, stones.Count); return stones[position]; }
/// <summary> /// Funkce nevytvari kopii historie (undo a redo), zobrazeni napovedy a slotu Fairway From /// </summary> /// <returns></returns> public Gameboard gameboardCopy() { var result = new Gameboard(); //* result.Board = new Fairway[GlobalVariables.size,GlobalVariables.size]; for (int i = 0; i < GlobalVariables.size; i++) { for (int j = 0; j < GlobalVariables.size; j++) result.Board[i, j] = Board[i, j].Clone(); } result.playingWhite = PlayingWhite; result.BlackPlayer = BlackPlayer; result.WhitePlayer = WhitePlayer; result.MovesWithoutJump = MovesWithoutJump; result.ShowMoveHelp = ShowMoveHelp; result.From = From; result.Winner = Winner; //*/ return result; }
public void makeMove(Fairway from, Fairway to, Gameboard gb, bool minimax) { if (!from.Moves.Contains(to.Name) && !minimax) { throw new Exception("Neplatný tah"); } bool changePlayer = true; if (from.Jump) { gb.MovesWithoutJump = 0; Fairway over = gb.getFigureInBetween(from, to); bool bQ = from.Queen; makeJump(from, over, to); bool aQ = to.Queen; if (to.Jump && bQ == aQ) { foreach (var fw in gb.Board) { fw.Jump = false; fw.StoneMove = false; fw.Moves = new List <string>(); fw.Ranks = new List <int>(); fw.Dests = new List <string>(); fw.Overs = new List <string>(); } generateMoves(gb, to); gb.Winner = checkWinner(gb); if (to.Jump) { changePlayer = false; } else { changePlayer = true; } } if (bQ == aQ) { generateMoves(gb, to); } } else { gb.MovesWithoutJump += 1; makeMove(from, to); setQueen(to); foreach (var fw in gb.Board) { fw.Jump = false; fw.StoneMove = false; fw.Moves = new List <string>(); fw.Ranks = new List <int>(); fw.Dests = new List <string>(); fw.Overs = new List <string>(); } } if (changePlayer) { gb.PlayingWhite = !gb.PlayingWhite; generateMoves(gb); gb.Winner = checkWinner(gb); } }
private void disableAllFairways(Gameboard gb) { Action<Fairway> disable = (fw) => fw.Enabled = false; foreach (Fairway fw in gb.Board) fw.Invoke(disable, fw); }
private void loadGame_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "XML soubor (*.xml)|*.xml"; ofd.Title = "Načtení uložené hry"; if (ofd.ShowDialog() == DialogResult.OK) { try { cleanHistory(); SaveLoad sl = new SaveLoad(); this.gb = sl.loadGame(ofd.FileName, gb); this.gb.drawBoard(); this.gb.colorUp(); pauseGame(); } catch (Exception ex) { MessageBox.Show(String.Format("Hru se nepodařilo načíst!\n{0}", ex.Message.ToString())); cleanHistory(); } } else MessageBox.Show("Hru se nepodařilo načíst!"); }
/// <summary> /// Ohodnocovaci funkce minimaxu /// </summary> /// <param name="gb">instance tridy hraci deska</param> /// <returns>hodnotu typu double predstavujici hodnotu pozice</returns> private double evalFunction(Gameboard gb) { int smallRand = random.Next(-1, 1); int mediumRand = random.Next(-2, 2); int largeRand = random.Next(-3, 3); int xLargeRand = random.Next(-4, 4); double result = 0; status playerOnMove = gb.PlayingWhite ? status.whitePlayer : status.blackPlayer; foreach (var fw in gb.Board) { string name = fw.Name; int x = Convert.ToInt32(name.Substring(1)); char y = name[0]; if (fw.Player != status.free) { // pozice u kraje desky - vodorovne if (x == 1 || x == GlobalVariables.size) { result += fw.Player == playerOnMove ? -5 : 5; result += smallRand; } // pozice u kraje desky - svisle if (y == 'A' || y == (char) ('A' + GlobalVariables.size - 1)) { result += fw.Player == playerOnMove ? -15 : 15; result += largeRand; } // pokud je figurka kralovna if (fw.Queen) { result += fw.Player == playerOnMove ? -20 : 20; result += xLargeRand; } // pokud jde o obycejny kamen else { result += fw.Player == playerOnMove ? -5 : 5; result += smallRand; } //pokud kamen muze skakat if (fw.Jump) { foreach (var jump in fw.Moves) { result += fw.Player == playerOnMove ? -10 : 10; result += mediumRand; } } else if (fw.StoneMove) { foreach (var move in fw.Moves) result += fw.Player == playerOnMove ? -2.5 : 2.5; } // pokud je kamen zablokovany else { result += fw.Player == playerOnMove ? 15 : -15; result += largeRand; } } } return result; }
private void genQueMoves(Gameboard gb, Fairway fw) { status playerOnMove = gb.PlayingWhite ? status.whitePlayer : status.blackPlayer; List<string> moves = fw.Moves; int x = Convert.ToInt32(fw.Name.Substring(1)) - 1; int y = Convert.ToInt32(fw.Name[0]) - 'A'; int temp = 0; for (int i = 0; i < 8; i++) { for (int j = 1; x + j*xs[i] < GlobalVariables.size && x + j*xs[i] >= 0 && y + j*ys[i] >= 0 && y + j*ys[i] < GlobalVariables.size && gb.Board[x + j*xs[i], y + j*ys[i]].Player == status.free; j++) { if (gb.Board[x + j*xs[i], y + j*ys[i]].Player == 0) { string move = (char) (y + j*ys[i] + 'A') + "" + (x + j*xs[i] + 1); moves.Add(move); } temp = j + 1; } fw.StoneMove = moves.Count > 0 ? true : false; genQueJumpTree(gb, fw); } }
/// <summary> /// Funkce generujici veskere mozne tahy na hraci desce /// </summary> /// <param name="gb">Instance tridy hraci deska</param> /// <returns>Vraci pole hracich poli, kde na lichem miste je ulozeno pole odkud bylo tazeno a na sudem miste pole, kam bylo tazeno</returns> private List<Fairway> generateMoves(Gameboard gb) { List<Fairway> movable = rules.choosableFigures(gb); var moves = new List<Fairway>(); foreach (var fw in movable) { List<string> dests = gb.possibleMoves(fw); foreach (var destination in dests) { moves.Add(fw); moves.Add(gb.getFigure(destination)); } } return moves; }