public int AITurn(int[,] boardData, int winReq) // handles AI logic. AI work by assigning weights to possible moves and picks the move with highest weight. parameters are the board state and win condition { int countx = 0; int county = 0; int[] moveWeight = { 1, 3, 9, 18, 9, 3, 1 }; // Each column has 1 move associated. playing toward the center is good, so default weights are increased for middle columns int[,] hypBoard = new int[7, 6]; // this array will parallel boardData, and is used to store theoretical board states. bool[,] possibleMove = new bool[7, 6]; // this array is also parallel, and will store which moves are possible. GameMod gameMod = new GameMod(); for (countx = 0; countx < 7; countx++) // fills hypBoard with element from boardDate { for (county = 0; county < 6; county++) { hypBoard[countx, county] = boardData[countx, county]; } } countx = 0; county = 0; for (countx = 0; countx < 7; countx++) // This algorithm looks at boardData and determines which moves are possible based on the lowest unoccupied space in each column. { for (county = 0; county < 6; county++) { if (boardData[countx, county] == 0) { possibleMove[countx, county] = true; county = county + 10; } } } countx = 0; county = 0; for (countx = 0; countx < 7; countx++) //AI uses the WinCheck() method to find a win. Takes each possible move and it leads to a win, it immediately takes it. { for (county = 0; county < 6; county++) { if (possibleMove[countx, county]) { hypBoard[countx, county] = 2; if (gameMod.WinCheck(hypBoard, winReq, 2) == 2) { return(countx); } else { hypBoard[countx, county] = 0; } } } } countx = 0; county = 0; for (countx = 0; countx < 7; countx++) //AI uses the WinCheck() method block a win. { for (county = 0; county < 6; county++) { if (possibleMove[countx, county]) { hypBoard[countx, county] = 1; if (gameMod.WinCheck(hypBoard, winReq, 1) == 1) { return(countx); } else { hypBoard[countx, county] = 0; } } } } countx = 0; county = 0; for (countx = 0; countx < 7; countx++) // makes sure move does not set up opponent win. Move weight tanks to -1000000, so it will only be picked if there is not other choice { for (county = 0; county < 5; county++) { if (possibleMove[countx, county]) { hypBoard[countx, county] = 2; hypBoard[countx, county + 1] = 1; if (gameMod.WinCheck(hypBoard, winReq, 1) == 1) { moveWeight[countx] = moveWeight[countx] - 1000000; } hypBoard[countx, county] = 0; hypBoard[countx, county + 1] = 0; } } } countx = 0; county = 0; for (countx = 0; countx < 5; countx++) // +200 move weight for blocking humans horizontal { for (county = 0; county < 6; county++) { if (possibleMove[countx, county] && boardData[countx + 1, county] == 1 && boardData[countx + 2, county] == 1) { moveWeight[countx] = moveWeight[countx] + 200; } } } countx = 0; county = 0; for (countx = 6; countx > 1; countx--) // reciporacal { for (county = 0; county < 6; county++) { if (possibleMove[countx, county] && boardData[countx - 1, county] == 1 && boardData[countx - 2, county] == 1) { moveWeight[countx] = moveWeight[countx] + 200; } } } countx = 0; county = 0; for (countx = 0; countx < 5; countx++) // +150 move weight for blocking humans diagonal { for (county = 0; county < 4; county++) { if (possibleMove[countx, county] && boardData[countx + 1, county + 1] == 1 && boardData[countx + 2, county + 2] == 1) { moveWeight[countx] = moveWeight[countx] + 150; } } } countx = 0; county = 0; for (countx = 6; countx > 1; countx--) // reciporacal { for (county = 5; county > 1; county--) { if (possibleMove[countx, county] && boardData[countx - 1, county - 1] == 1 && boardData[countx - 2, county - 2] == 1) { moveWeight[countx] = moveWeight[countx] + 150; } } } countx = 0; county = 0; for (countx = 0; countx < 5; countx++) // +150 move weight for blocking humans diagonal { for (county = 2; county < 6; county++) { if (possibleMove[countx, county] && boardData[countx + 1, county - 1] == 1 && boardData[countx + 2, county - 2] == 1) { moveWeight[countx] = moveWeight[countx] + 150; } } } countx = 0; county = 0; for (countx = 6; countx > 1; countx--) // +150 move weight for blocking humans diagonal { for (county = 0; county < 4; county++) { if (possibleMove[countx, county] && boardData[countx - 1, county + 1] == 1 && boardData[countx - 2, county + 2] == 1) { moveWeight[countx] = moveWeight[countx] + 150; } } } countx = 0; county = 0; for (countx = 0; countx < 5; countx++) // develop diag { for (county = 0; county < 4; county++) { if (possibleMove[countx, county] && boardData[countx + 1, county + 1] == 2 && boardData[countx + 2, county + 2] == 2) { moveWeight[countx] = moveWeight[countx] + 100; } } } countx = 0; county = 0; for (countx = 6; countx > 1; countx--) // develop diag { for (county = 5; county > 1; county--) { if (possibleMove[countx, county] && boardData[countx - 1, county - 1] == 2 && boardData[countx - 2, county - 2] == 2) { moveWeight[countx] = moveWeight[countx] + 100; } } } countx = 0; county = 0; for (countx = 0; countx < 5; countx++) // develop diag { for (county = 2; county < 6; county++) { if (possibleMove[countx, county] && boardData[countx + 1, county - 1] == 2 && boardData[countx + 2, county - 2] == 2) { moveWeight[countx] = moveWeight[countx] + 100; } } } countx = 0; county = 0; for (countx = 6; countx > 1; countx--) // develop diag { for (county = 0; county < 4; county++) { if (possibleMove[countx, county] && boardData[countx - 1, county + 1] == 2 && boardData[countx - 2, county + 2] == 2) { moveWeight[countx] = moveWeight[countx] + 100; } } } countx = 0; county = 0; for (countx = 0; countx < 5; countx++) // +100 to develop it own 3 horizontal { for (county = 0; county < 6; county++) { if (possibleMove[countx, county] && boardData[countx + 1, county] == 2 && boardData[countx + 2, county] == 2) { moveWeight[countx] = moveWeight[countx] + 100; if (countx < 4) { if (boardData[countx + 3, county] == 0) { moveWeight[countx] = moveWeight[countx] + 100; } } } } } countx = 0; county = 0; for (countx = 6; countx > 1; countx--) // recip { for (county = 0; county < 6; county++) { if (possibleMove[countx, county] && boardData[countx - 1, county] == 2 && boardData[countx - 2, county] == 2) { moveWeight[countx] = moveWeight[countx] + 100; if (countx > 2) { if (boardData[countx - 3, county] == 0) { moveWeight[countx] = moveWeight[countx] + 100; } } } } } countx = 0; county = 0; for (countx = 6; countx > 2; countx--) // diagonal down/left develop { for (county = 5; county < 1; county--) { if (possibleMove[countx, county] && boardData[countx - 1, county - 1] == 2 && boardData[countx - 2, county - 2] == 0 && boardData[countx - 3, county - 3] == 2) { moveWeight[countx] = moveWeight[countx] + 100; } if (possibleMove[countx, county] && boardData[countx - 1, county - 1] == 0 && boardData[countx - 2, county - 2] == 2 && boardData[countx - 3, county - 3] == 2) { moveWeight[countx] = moveWeight[countx] + 100; } if (possibleMove[countx, county] && boardData[countx - 1, county - 1] == 2 && boardData[countx - 2, county - 2] == 2 && boardData[countx - 3, county - 3] == 0) { moveWeight[countx] = moveWeight[countx] + 100; } } } countx = 0; county = 0; for (countx = 0; countx < 4; countx++) // diagonal down/right develop { for (county = 5; county < 1; county--) { if (possibleMove[countx, county] && boardData[countx + 1, county - 1] == 2 && boardData[countx + 2, county - 2] == 0 && boardData[countx + 3, county - 3] == 2) { moveWeight[countx] = moveWeight[countx] + 100; } if (possibleMove[countx, county] && boardData[countx + 1, county - 1] == 0 && boardData[countx + 2, county - 2] == 2 && boardData[countx + 3, county - 3] == 2) { moveWeight[countx] = moveWeight[countx] + 100; } if (possibleMove[countx, county] && boardData[countx + 1, county - 1] == 2 && boardData[countx + 2, county - 2] == 2 && boardData[countx + 3, county - 3] == 0) { moveWeight[countx] = moveWeight[countx] + 100; } } } countx = 0; county = 0; for (countx = 0; countx < 7; countx++) // ai will prefer middle rows. { for (county = 2; county < 4; county++) { if (possibleMove[countx, county]) { moveWeight[countx] = moveWeight[countx] + 25; } } } countx = 0; county = 0; Random rand = new Random(); for (countx = 0; countx < 7; countx++) // add random element to possible moves. Impossible moves get -1000000000 { for (county = 0; county < 6; county++) { if (possibleMove[countx, county]) { moveWeight[countx] = moveWeight[countx] + rand.Next(20); } else { moveWeight[countx] = moveWeight[countx] - 1000000000; } } } for (countx = 0; countx < 7; countx++) // this selects move with highest weight. { if (moveWeight[countx] == moveWeight.Max()) { return(countx); } } return(3); }
public int Master(int colorChoice1, int colorChoice2, int gameType, int winReq) { string player2Type = ""; int columnChoice = 0; int count = 0; int countx = 0; int county = 0; int playerWon; bool inGame = true; bool player1Turn = false; bool player2Turn = false; bool firstUnfound = true; bool columnInvalid = false; UI ui = new UI(); GameMod mod = new GameMod(); int[,] boardData = new int[7, 6]; int playerFirst; Random rand = new Random(); boardData = mod.GenBoard(); // game board data is generated if (gameType == 1) { player2Type = "AI"; } if (gameType == 2) { player2Type = "human"; } ui.Who(gameType); // user determines first player ConsoleKeyInfo firstKey = Console.ReadKey(); playerFirst = Convert.ToInt16(firstKey.Key) - 48; do //will take players input, or randomize turn order { if (playerFirst == 1) { player1Turn = true; firstUnfound = false; } if (playerFirst == 2) { player2Turn = true; firstUnfound = false; } if (firstUnfound) { playerFirst = rand.Next(2) + 1; } } while (firstUnfound); ui.GameBoard(); //UI Board generated ui.DropPiece(1, 7, colorChoice1, false); ui.DropPiece(5, 7, colorChoice2, false); while (inGame) { if (player1Turn) { ui.PlayerTurn(player1Turn, player2Turn); // draws arrows indicating turn do // this loop validates players choice so game won't crash { Console.SetCursorPosition(0, 0); columnChoice = mod.HumanTurn(); // humanturn() is called to get player's choice if (columnChoice == -1) // is player presses 0, will forfeit as directed { return(2); } if (columnChoice >= 0 && columnChoice < 7) { if (boardData[columnChoice, 5] != 0) { columnInvalid = true; } else { columnInvalid = false; } } else { columnInvalid = true; } } while (columnInvalid); for (count = 0; count < 6; count++) //once valid column is chosen, if the lowest space is occupied, it will more up until open space is found. boardData will update, and piece is dropped on UI { if (boardData[columnChoice, count] == 0) { Console.Beep(420, 100); boardData[columnChoice, count] = 1; ui.DropPiece(columnChoice, 6 - count, colorChoice1, true); count = count + 10; } } count = 0; playerWon = mod.WinCheck(boardData, winReq, 1); //checks for win if (playerWon == 1) { ui.Exit(playerWon); Console.Beep(523, 200); Console.Beep(392, 200); Console.Beep(330, 200); Console.Beep(262, 500); for (county = 0; county < 6; county++) { for (countx = 0; countx < 7; countx++) { if (player2Type == "AI") { ui.DropPiece(countx, 6 - county, rand.Next(7) + 1, true); } else if (boardData[countx, county] == 2) { Thread.Sleep(100); ui.DropPiece(countx, 6 - county, 9, false); } } } Console.ReadKey(); return(1); } else // if win is not achieved, checks for stalemate. else turn order switches. { if (mod.StaleCheck(boardData)) { for (county = 0; county < 5; county++) { Thread.Sleep(150); ui.DropPiece(3, 6 - county, 9, false); } for (countx = 0; countx < 7; countx++) { Thread.Sleep(150); ui.DropPiece(countx, 1, 9, false); } ui.Exit(0); Console.ReadKey(); inGame = false; } else { player1Turn = false; player2Turn = true; } } } if (player2Turn) { ui.PlayerTurn(player1Turn, player2Turn); if (player2Type == "human") //if p2 is human, same as above { do { Console.SetCursorPosition(0, 0); columnChoice = mod.HumanTurn(); if (columnChoice == -1) { return(1); } if (columnChoice >= 0 && columnChoice < 7) { if (boardData[columnChoice, 5] != 0) { columnInvalid = true; } else { columnInvalid = false; } } else { columnInvalid = true; } } while (columnInvalid); } if (player2Type == "AI") // if p2 is AI, calls AImod to determine move { AIMod AI = new AIMod(); do { columnChoice = AI.AITurn(boardData, winReq); if (boardData[columnChoice, 5] != 0) { columnInvalid = true; } else { columnInvalid = false; } } while (columnInvalid); } for (count = 0; count < 6; count++) { if (boardData[columnChoice, count] == 0) { Console.Beep(380, 100); boardData[columnChoice, count] = 2; ui.DropPiece(columnChoice, 6 - count, colorChoice2, true); count = count + 10; } } count = 0; playerWon = mod.WinCheck(boardData, winReq, 2); if (playerWon == 2) { ui.Exit(playerWon); if (player2Type == "AI") { Console.Beep(392, 400); Console.Beep(330, 400); Console.Beep(262, 1200); } else { Console.Beep(523, 200); Console.Beep(392, 200); Console.Beep(330, 200); Console.Beep(262, 500); } for (county = 0; county < 6; county++) { for (countx = 0; countx < 7; countx++) { if (boardData[countx, county] == 1) { Thread.Sleep(50); ui.DropPiece(countx, 6 - county, 9, false); } } } Console.ReadKey(); return(2); } else { if (mod.StaleCheck(boardData)) { for (county = 0; county < 5; county++) { Thread.Sleep(150); ui.DropPiece(3, 6 - county, 9, false); } for (countx = 0; countx < 7; countx++) { Thread.Sleep(150); ui.DropPiece(countx, 1, 9, false); } ui.Exit(0); Console.ReadKey(); inGame = false; } else { player2Turn = false; player1Turn = true; } } } } return(0); }