Você está na página 1de 23

http://www.daniweb.com/forums/post1077746.

html#post1077746
using System;using System.Collections.Generic;using System.Linq;using System.Tex
t; namespace OXO{ class Program { static int width = 3; stat
ic int height = 3; static char[] OX = new char[width * height]; st
atic string spacer = " | "; static char go; static char computerPl
ayer = 'O'; static int games; static int gameNumber; static
int scoreX; static int scoreO; static char lastWinner; st
atic void Main(string[] args) { bool playing = true;
while (playing) { Initialise(); //Wou
ld you like to play single player or multiplayer? int userChoice
= MenuLevel0(); Console.Clear(); //Multi-Play
er if (userChoice == 1) {
while (gameNumber <= games) {
Initialise(); //If we are into the second roun
d or higher of a tournament, set the starting user to the player who loast last
time: if (gameNumber > 1)
{ go = lastWinner; }
string grid = GridBuilder(
); Console.Write(grid); b
ool inPlay = true; while (inPlay)
{ Update();
inPlay = !GameOver(userChoice); }
gameNumber++; Wait();
} //If it was a tounament, declare the victor!
TourniVictor(); } //Single
-Player else if (userChoice == 2) {
while (gameNumber <= games) {
Initialise(); //If we are into the s
econd round or higher of a tournament, set the starting user to the player who l
oast last time: if (gameNumber > 1)
{ go = lastWinner;
} string grid = GridBuilder();
Console.Write(grid); bool inPlay = true;
while (inPlay) {
SinglePlayerUpdate(); inPl
ay = !GameOver(userChoice); }
gameNumber++; Wait(); }
//If it was a tounament, declare the victor!
TourniVictor(); } else if (userCh
oice == -1) { Console.WriteLine("Thank
you for playing!\nGoodbye!"); playing = false;
} } } static int MenuLevel0() {
string userChoice; //Console.Clear(); Console.Writ
eLine("Welcome to Tic-Tac-Toe!"); Console.WriteLine("1. Play Multi-Pl
ayer \n2. Play Single-Player\nQ. Quit Playing"); do {
Console.Write("Please enter your choice: ");
userChoice = Console.ReadLine(); } while (!(userCho
ice == "1" || userChoice == "2" || userChoice.ToLower() == "q")); //c
onvert to integer value int selection; if (int.TryParse(us
erChoice, out selection)) { } //For values
that are actually letters, assign an equivelent integer value, for simplicity
//KEY: //QUIT q -1 else
{ selection = -1; } //if the user wan
ts to play: if (selection > 0) { MenuLevel1
(); } return selection; } static void MenuL
evel1() { int userInput; Console.Clear();
Console.WriteLine("How many games would you like to play?"); Consol
e.WriteLine("1. Just the one game thanks!"); Console.WriteLine("2. A
mini-tournament please!"); do { Console.Wri
te("Enter your selection: "); } while (!(int.TryParse(Cons
ole.ReadLine(), out userInput)) && !(userInput<=2 && userInput>=1));
if (userInput == 2) { do {
Console.Clear(); Console.Write("Enter How Many Games
You'd Like To Play: "); } while (!int.TryParse(Con
sole.ReadLine(), out userInput)); //Set up the tourni values
InitialiseTournament(userInput); } } static
void TourniVictor() { //If we just finished a tournament, dec
lare the victor: if (games > 1) { Console.C
lear(); char winner; //if X won if
(scoreX > scoreO) { winner = 'X';
} //If O won else if (scoreO > scoreX)
{ winner = 'O'; } //If i
t was a draw else { winner = 'd
'; } //If it was a draw: if (winne
r == 'd') { Console.WriteLine("Alas, a draw!")
; } //Else declave the victor: else
{ Console.WriteLine("Congratulations {0}! You
won the Tournament :)", winner); } //reset the va
lues InitialiseTournament(1); Wait(); }
} static void InitialiseTournament(int numberOfGames) {
games = numberOfGames; gameNumber = 1; scoreO = 0
; scoreX = 0; } static void Wait() {
Console.WriteLine("\nPress any key to continue . . ."); Console.ReadK
ey(); Console.Clear(); } static int AI() {
AlternateUsers(); char enemy = go; AlternateUsers(); int[] winP
ossibilityPriority = new int[8]; int k = 0; //Horizontal
Wins: for (int i = 0; i < OX.Length; i+=width, k++) {
//construct a string which contains the char array str
ing contents = ""; for (int j = 0; j < width; j++)
{ contents += OX[i + j]; } //s
earch for an empty cell. If it has one continue checking. Else move on.
if (contents.Contains(" ")) { if (conte
nts.Contains(enemy)) { int numberOfEne
myPositions = 0; int numberOfFriendlyPositions = 0;
//count how many enemies && friendlies are in the 3 cells.
for (int j = 0; j < width; j++) {
if (contents[j] == enemy) {
numberOfEnemyPositions++;
} if (contents[j] == go)
{ numberOfFriendlyPositions++;
} } //Prioritise this 3
cell group (win possibility) winPossibilityPriority[k] =
numberOfEnemyPositions - numberOfFriendlyPositions; }
} else { //we cannot g
o here. winPossibilityPriority[k] = 0; }
} //Vertical Wins: for (int i = 0; i < width; i++,
k++) { //construct a string which contains the char ar
ray string contents = ""; for (int j = 0; j < widt
h; j++) { contents += OX[i + (j*width)];
} //search for an empty cell. If it has one continue ch
ecking. Else move on. if (contents.Contains(" "))
{ if (contents.Contains(enemy)) {
int numberOfEnemyPositions = 0; int number
OfFriendlyPositions = 0; //count how many enemies && frie
ndlies are in the 3 cells. for (int j = 0; j < width; j++
) { if (contents[j] == enemy)
{ numberOfEnemyPositio
ns++; } if (contents[j] ==
go) { numberOfFriendl
yPositions++; } }
//Prioritise this 3 cell group (win possibility)
winPossibilityPriority[k] = numberOfEnemyPositions - numberOfFriendlyPosition
s; } } else {
//we cannot go here. winPossibilityPriority[
k] = 0; } } //Diagonal Wins: //
Top Left to Bottom Right: //construct a string which contains the cha
r array for (int i = 0; i < 1; i++, k++)//C# won't let me use content
s string unless it's inside a child here... C# is great... {
string contents = ""; for (int j = 0; j < width; j++)
{ contents += OX[j * 4]; }
//search for an empty cell. If it has one continue checking. Else move on
. if (contents.Contains(" ")) {
if (contents.Contains(enemy)) { int n
umberOfEnemyPositions = 0; int numberOfFriendlyPositions
= 0; //count how many enemies && friendlies are in the 3
cells. for (int j = 0; j < width; j++)
{ if (contents[j] == enemy)
{ numberOfEnemyPositions++;
} if (contents[j] == go)
{ numberOfFriendlyPositions++;
} } //Priorit
ise this 3 cell group (win possibility) winPossibilityPri
ority[k] = numberOfEnemyPositions - numberOfFriendlyPositions;
} } else { //w
e cannot go here. winPossibilityPriority[k] = 0;
} } //Top Right to Bottom Left: //construct
a string which contains the char array for (int i = 0; i < 1; i++, k
++)//C# won't let me use contents string unless it's inside a child here... C# i
s great... { string contents = ""; for
(int j = 2; j <= 6 ; j+=2) { contents += OX[j]
; } //search for an empty cell. If it has one cont
inue checking. Else move on. if (contents.Contains(" "))
{ if (contents.Contains(enemy)) {
int numberOfEnemyPositions = 0; int
numberOfFriendlyPositions = 0; //count how many enemies
&& friendlies are in the 3 cells. for (int j = 0; j < wid
th; j++) { if (contents[j] ==
enemy) { numberOfEnemy
Positions++; } if (content
s[j] == go) { numberOf
FriendlyPositions++; } }
//Prioritise this 3 cell group (win possibility)
winPossibilityPriority[k] = numberOfEnemyPositions - numberOfFriendlyP
ositions; } } else
{ //we cannot go here. winPossibilityPr
iority[k] = 0; } } //NOW ALL POSSIBLE WAYS
TO WIN HAVE BEEN EVALUATED ONCE. //Everything has been giver a value
of 2, 1, 0, -1 or 2 //WIN OR LOSE EVENTS: //-2 means the
re are 2 allies in this sector. Any sector with this value means that one move w
ill win the game! //2 means there are 2 enemies in this sector and so
is High Priority! One move will stop the enemy winning via this sector.
//NORMAL GAMEPLAY: //-1 means there is one ally in this sector.
Going here will make this -2 for the enemy, during standard gameplay this is the
highest value sector. //1 means there is an enemy in this sector. Lo
w priority event. //0 means there is no value to playing in this sect
or. Either there is one enemy & one ally, or there is neither an ally nor an ene
my. //Rearrange these into more readable priorities: for
(int i = 0; i < winPossibilityPriority.Length; i++) {
if (winPossibilityPriority[i] == -1) { winPoss
ibilityPriority[i] = 2; } else if (winPossibilityP
riority[i] == 2) { winPossibilityPriority[i] =
3; } else if (winPossibilityPriority[i] == -2)
{ winPossibilityPriority[i] = 4;
} } //NEW VALUES: //WIN OR LOSE EVENTS:
//4 means there are 2 allies in this sector. Any sector with this value mea
ns that one move will win the game! //3 means there are 2 enemies in
this sector and so is High Priority! One move will stop the enemy winning via th
is sector. //NORMAL GAMEPLAY: //2 means there is one ally
in this sector. Going here will make this -2 for the enemy, during standard gam
eplay this is the highest value sector. //1 means there is an enemy i
n this sector. Low priority event. //0 means there is no value to pla
ying in this sector. Either there is one enemy & one ally, or there is neither a
n ally nor an enemy. //FIND THE HIGHEST PRIORITY SECTOR:
int highPriorityValue = 0; int highPrioritySector = 0; for
(int i = 0; i < winPossibilityPriority.Length; i++) {
if (highPriorityValue < winPossibilityPriority[i]) {
highPriorityValue = winPossibilityPriority[i]; highPr
ioritySector = i; } } //The highest priori
ty sector is now listed as a location in the array winPosibilityPriority
//FIND THE ACTUAL GRID LOCATIONS: //(relative to the OX array)
int[] gridLocations = new int[3]; //If it's horizontal
if (highPrioritySector < 3) { gridLocations[0]
= highPrioritySector * 3; for (int i = 1; i < 3; i++)
{ gridLocations[i] = gridLocations[0] + i;
} } //If it's vertical else if (highPriority
Sector < 6) { gridLocations[0] = highPrioritySector -
3; for (int i = 1; i < 3; i++) {
gridLocations[i] = gridLocations[0] + (i * width); }
} //If it's diagonal else if (highPrioritySector == 6)
{ gridLocations[0] = 0; gridLocations[1]
= 4; gridLocations[2] = 8; } else if (high
PrioritySector == 7) { gridLocations[0] = 2;
gridLocations[1] = 4; gridLocations[2] = 6; }
//NOW GO THROUGH THE INDIVIDUAL VALUES OF THE HIGH PRIORITY SECTOR AND
TAKE YOUR GO for (int i = 0; i < 3; i++) {
if (OX[gridLocations[i]] == ' ') { return gri
dLocations[i]; } } //IF YOU GET THIS FAR, I
T'S FUBAR //Give an *Important* error warning Console.Beep
(); //Return a value to prevent application hanging return
4; } static void KeepScore() { if (go == 'X')
{ scoreX++; } else {
scoreO++; } } static bool GameOver(int ga
meType) { if (gameType == 1) { if (C
heckWinCriteria() == true) { //Write Out the n
ew GridBuilder, as CheckWinCriteria will have placed hitmarkers on the winning c
ells Console.Clear(); Console.Write(GridBu
ilder()); Console.WriteLine("Well done {0}, you win!", go);
KeepScore(); TournamentUpdate(false);
//Determine the player who starts next time (if its a tourni)
lastWinner = go; return true; }
} else if (gameType == 2) { if
(CheckWinCriteria() == true) { if (go == compu
terPlayer) { //Write Out the new GridB
uilder, as CheckWinCriteria will have placed hitmarkers on the winning cells
Console.Clear(); Console.Write(GridBu
ilder()); Console.WriteLine("The computer won. Bad Luck!"
); } else {
//Write Out the new GridBuilder, as CheckWinCriteria will have place
d hitmarkers on the winning cells Console.Clear();
Console.Write(GridBuilder()); Console.Wr
iteLine("Well done, you win!"); } KeepScor
e(); TournamentUpdate(true); //Determine t
he player who starts next time (if its a tourni) lastWinner =
go; return true; } } if
(CheckDrawCriteria() == true) { Console.WriteLine("St
and down, it's a draw..."); return true; }
return false; } static bool CheckDrawCriteria() {
for (int i = 0; i < OX.Length; i++) { if (OX[i] ==
' ') { return false; }
} return true; } static bool CheckWinCriteria()
{ char winMarker = '*'; //Check left column, and then a
long the rows horizontally for (int j = 0; j < OX.Length; j += 3)
{ //If all cell's on the horizontal row hits. Game over.
if (OX[j] == go && OX[j + 1] == go && OX[j + 2] == go)
{ OX[j] = winMarker; OX[j + 1] = winM
arker; OX[j + 2] = winMarker; return true;
} } //Check 1st row, and then down the col
umns vertically for (int j = 0; j < width; j++) {
if (OX[j] == go && OX[j + width] == go && OX[j + 2 * width] == go)
{ OX[j] = winMarker; OX[j + width
] = winMarker; OX[j + 2 * width] = winMarker;
return true; } } //Check diaganol lines
//check for the diagonal starting in the top left if (OX[
0] == go && OX[width + 1] == go && OX[2 * (width + 1)] == go) {
OX[0] = winMarker; OX[width + 1] = winMarker;
OX[2 * (width + 1)] = winMarker; return true; }
//check for the diagonal starting in the top right if (OX[
width - 1] == go && OX[2 * (width - 1)] == go && OX[3 * (width - 1)] == go)
{ OX[width - 1] = winMarker; OX[2 * (width
- 1)] = winMarker; OX[3 * (width - 1)] = winMarker;
return true; } return false; } static voi
d TournamentUpdate(bool singlePlayer) { //If we are in a 'tour
nament' if (games > 1) { Console.WriteLine(
"Game {0} of {1}", gameNumber, games); Console.WriteLine("Scores:
"); string X = ""; string O = ""; i
f (singlePlayer) { X = (computerPlayer == 'X'
? "Computer" : "You"); O = (computerPlayer == 'O' ? "Computer
" : "You"); } else {
X = "X"; O = "O"; } Consol
e.WriteLine("{0}: {1}", X, scoreX); Console.WriteLine("{0}: {1}",
O, scoreO); } } static void Update() {
TournamentUpdate(false); AlternateUsers(); Console.Writ
eLine("{0}'s go!", go); int i; do {
i = MakeArrayPosition(GetCoOrds()); } while (OX[i] !=
' '); OX[i] = go; Console.Clear();
Console.Write(GridBuilder()); } static void SinglePlayerUpdate()
{ TournamentUpdate(true); AlternateUsers();
if (go != computerPlayer) { Console.Wri
teLine("Your go! You are {0}", go); int i; do
{ i = MakeArrayPosition(GetCoOrds());
} while (OX[i] != ' '); OX[i] = go;
} else { Console.WriteLine(
"The computer is taking it's turn..."); //OX[AI()] = go;
OX[MiniMax()] = go; } Console.Clear(); C
onsole.Write(GridBuilder()); } static void AlternateUsers()
{ if (go == 'O') { go = 'X'; }
else { go = 'O'; } }
static int MakeArrayPosition(int[] coOrds) { int i = 0;
//check first row for (int k = 0; k < coOrds[1]; k++)
{ if (k + 1 == coOrds[1]) {
for (int j = 1; j < coOrds[0]; j++, i++) {
} } else { for
(int j = 0; j < width; j++, i++) { }
} } return i; } static int[] Get
CoOrds() { bool inPlay = true; while (inPlay)
{ int[] coOrds = CheckCoOrdinates(GetCoOrdinates());
if (coOrds[0] != 0) { return coOrds;
} } int[] csDoesntWork = new int[2];
return csDoesntWork; } static int[] CheckCoOrdinates(string r
awInput) { int[] coOrds = new int[2]; //horizontal
co-ordinate if (rawInput.ToLower().Contains("a")) {
coOrds[0] = 1; } else if (rawInput.ToLower().Cont
ains("b")) { coOrds[0] = 2; } el
se if (rawInput.ToLower().Contains("c")) { coOrds[0] =
3; } //when coOrds[0] == 0, this is an error!
else { coOrds[0] = 0; } //Vertic
al co-ordinate if (rawInput.ToLower().Contains("1")) {
coOrds[1] = 1; } else if (rawInput.ToLower().C
ontains("2")) { coOrds[1] = 2; }
else if (rawInput.ToLower().Contains("3")) { coOrds[1
] = 3; } //when coOrds[0] == 0, this is an error!
else { coOrds[0] = 0; } retur
n coOrds; } static string GetCoOrdinates() { str
ing coOrds; Console.Write("Enter the co-ordinates you want to make an
entry in: "); coOrds = Console.ReadLine(); return coOrds;
} static string GridBuilder() { string grid = "
"; for (int i = 0; i < OX.Length; i++) { gr
id += OX[i]; if ((i + 1) % width == 0) {
grid += "\n"; if ((i + 1) != OX.Length)
{ for (int j = 0; j < (spacer.Length * width); j+
+) { grid += "-";
} } grid += "\n";
} else { grid += spacer;
} } return grid; } static void In
itialise() { for (int i = 0; i < OX.Length; i++) {
OX[i] = ' '; } go = 'O'; } st
atic int MiniMax() { int bestGo = 0; int[] terminal
Values = new int[OX.Length]; //determine the terminal value of going
in each cell: for (int i = 0; i < terminalValues.Length; i++)
{ terminalValues[i] = ValueCell(i, OX, go); }
//FIND & RETURN THE BEST GO: for (int i = 0; i < terminalValue
s.Length; i++) { bestGo = Math.Max(bestGo, terminalVal
ues[i]); } return bestGo; } static int Value
Cell(int cell, char[] currentGrid, char whosGo) { //pass OX as
the current grid if it's the first time, else make ammendments to the 'current
grid' where OX is left as the actual inPlay values int cellValue = -2
; //If this would be an illegal move: if (currentGrid[cell
] != ' ') { return -2; } //Else
if it's a legal move: currentGrid[cell] = whosGo; /
/If the currentGrid is full (we are at the last fork of the process)
if (!GridSpace(currentGrid)) { //If in the
boards current state teh computer wins, return a value of 1
if (CheckCurrentWin(currentGrid, computerPlayer)) {
return 1; } //If in the boar
ds current state, the human wins, return a value of -1 else i
f (CheckCurrentWin(currentGrid, RotateGo(computerPlayer))) {
return -1; } //Else
we drew, return 0 else {
return 0; } } //dec
lare an array of cell values for each possible move & make them 'impossible'
int[] goValue = new int[9]; for (int i = 0; i
< goValue.Length; i++) { goValue[i] =
-2; } //now set those that are possible t
o their actual values for (int i = 0; i < currentGrid.Length;
i++) { if (currentGrid[i] == ' ')
{ goValue[i] = ValueCell(i, curre
ntGrid, RotateGo(whosGo)); } }
//Now find the highest possible outcome by making this move:
for (int i = 0; i < goValue.Length; i++) {
cellValue = Math.Max(cellValue, goValue[i]);
} //return trhe cell's value to the parent fork.
return cellValue; } static bool GridSpace(char[] currentGr
id) { foreach (char cell in currentGrid) {
if (cell == ' ') { return true;
} } return false; } static char Rota
teGo(char currentGo) { if (currentGo == 'X') {
currentGo = 'O'; } else {
currentGo = 'X'; } return currentGo; }
static bool CheckCurrentWin(char[] currentGrid, char whosGo) {
//Check left column, and then along the rows horizontally for (int j
= 0; j < currentGrid.Length; j += 3) { //If all cell'
s on the horizontal row hits. Game over. if (currentGrid[j] == wh
osGo && currentGrid[j + 1] == whosGo && currentGrid[j + 2] == whosGo)
{ return true; } }
//Check 1st row, and then down the columns vertically for (int j = 0;
j < width; j++) { if (currentGrid[j] == whosGo && cur
rentGrid[j + width] == whosGo && currentGrid[j + 2 * width] == whosGo)
{ return true; } }
//Check diaganol lines //check for the diagonal starting in the top
left if (currentGrid[0] == whosGo && currentGrid[width + 1] == whosGo
&& currentGrid[2 * (width + 1)] == whosGo) { return t
rue; } //check for the diagonal starting in the top right
if (currentGrid[width - 1] == whosGo && currentGrid[2 * (width - 1)]
== whosGo && currentGrid[3 * (width - 1)] == whosGo) {
return true; } return false; } }}/*
* Tic-Tac-Toe
* J Keegan
* 10/12/09
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OXO
{
class Program
{
static int width = 3;
static int height = 3;
static char[] OX = new char[width * height];
static string spacer = " | ";
static char go;
static char computerPlayer = 'O';
static int games;
static int gameNumber;
static int scoreX;
static int scoreO;
static char lastWinner;
static void Main(string[] args)
{
bool playing = true;
while (playing)
{
Initialise();
//Would you like to play single player or multiplayer?
int userChoice = MenuLevel0();
Console.Clear();
//Multi-Player
if (userChoice == 1)
{
while (gameNumber <= games)
{
Initialise();
//If we are into the second round or higher of a tou
rnament, set the starting user to the player who loast last time:
if (gameNumber > 1)
{
go = lastWinner;
}
string grid = GridBuilder();
Console.Write(grid);
bool inPlay = true;
while (inPlay)
{
Update();
inPlay = !GameOver(userChoice);
}
gameNumber++;
Wait();
}
//If it was a tounament, declare the victor!
TourniVictor();
}
//Single-Player
else if (userChoice == 2)
{
while (gameNumber <= games)
{
Initialise();
//If we are into the second round or higher of a tou
rnament, set the starting user to the player who loast last time:
if (gameNumber > 1)
{
go = lastWinner;
}
string grid = GridBuilder();
Console.Write(grid);
bool inPlay = true;
while (inPlay)
{
SinglePlayerUpdate();
inPlay = !GameOver(userChoice);
}
gameNumber++;
Wait();
}
//If it was a tounament, declare the victor!
TourniVictor();
}
else if (userChoice == -1)
{
Console.WriteLine("Thankyou for playing!\nGoodbye!");
playing = false;
}
}
}
static int MenuLevel0()
{
string userChoice;
//Console.Clear();
Console.WriteLine("Welcome to Tic-Tac-Toe!");
Console.WriteLine("1. Play Multi-Player \n2. Play Single-Player\nQ.
Quit Playing");
do
{
Console.Write("Please enter your choice: ");
userChoice = Console.ReadLine();
}
while (!(userChoice == "1" || userChoice == "2" || userChoice.ToLowe
r() == "q"));
//convert to integer value
int selection;
if (int.TryParse(userChoice, out selection))
{
}
//For values that are actually letters, assign an equivelent int
eger value, for simplicity
//KEY:
//QUIT q -1
else
{
selection = -1;
}
//if the user wants to play:
if (selection > 0)
{
MenuLevel1();
}
return selection;
}
static void MenuLevel1()
{
int userInput;
Console.Clear();
Console.WriteLine("How many games would you like to play?");
Console.WriteLine("1. Just the one game thanks!");
Console.WriteLine("2. A mini-tournament please!");
do
{
Console.Write("Enter your selection: ");
}
while (!(int.TryParse(Console.ReadLine(), out userInput)) && !(userI
nput<=2 && userInput>=1));
if (userInput == 2)
{
do
{
Console.Clear();
Console.Write("Enter How Many Games You'd Like To Play: ");
}
while (!int.TryParse(Console.ReadLine(), out userInput));
//Set up the tourni values
InitialiseTournament(userInput);
}
}
static void TourniVictor()
{
//If we just finished a tournament, declare the victor:
if (games > 1)
{
Console.Clear();
char winner;
//if X won
if (scoreX > scoreO)
{
winner = 'X';
}
//If O won
else if (scoreO > scoreX)
{
winner = 'O';
}
//If it was a draw
else
{
winner = 'd';
}
//If it was a draw:
if (winner == 'd')
{
Console.WriteLine("Alas, a draw!");
}
//Else declave the victor:
else
{
Console.WriteLine("Congratulations {0}! You won the Tourname
nt :)", winner);
}
//reset the values
InitialiseTournament(1);
Wait();
}
}
static void InitialiseTournament(int numberOfGames)
{
games = numberOfGames;
gameNumber = 1;
scoreO = 0;
scoreX = 0;
}
static void Wait()
{
Console.WriteLine("\nPress any key to continue . . .");
Console.ReadKey();
Console.Clear();
}
static int AI()
{
AlternateUsers(); char enemy = go; AlternateUsers();
int[] winPossibilityPriority = new int[8];
int k = 0;
//Horizontal Wins:
for (int i = 0; i < OX.Length; i+=width, k++)
{
//construct a string which contains the char array
string contents = "";
for (int j = 0; j < width; j++)
{
contents += OX[i + j];
}
//search for an empty cell. If it has one continue checking. Els
e move on.
if (contents.Contains(" "))
{
if (contents.Contains(enemy))
{
int numberOfEnemyPositions = 0;
int numberOfFriendlyPositions = 0;
//count how many enemies && friendlies are in the 3 cell
s.
for (int j = 0; j < width; j++)
{
if (contents[j] == enemy)
{
numberOfEnemyPositions++;
}
if (contents[j] == go)
{
numberOfFriendlyPositions++;
}
}
//Prioritise this 3 cell group (win possibility)
winPossibilityPriority[k] = numberOfEnemyPositions - num
berOfFriendlyPositions;
}
}
else
{
//we cannot go here.
winPossibilityPriority[k] = 0;
}
}
//Vertical Wins:
for (int i = 0; i < width; i++, k++)
{
//construct a string which contains the char array
string contents = "";
for (int j = 0; j < width; j++)
{
contents += OX[i + (j*width)];
}
//search for an empty cell. If it has one continue checking. Els
e move on.
if (contents.Contains(" "))
{
if (contents.Contains(enemy))
{
int numberOfEnemyPositions = 0;
int numberOfFriendlyPositions = 0;
//count how many enemies && friendlies are in the 3 cell
s.
for (int j = 0; j < width; j++)
{
if (contents[j] == enemy)
{
numberOfEnemyPositions++;
}
if (contents[j] == go)
{
numberOfFriendlyPositions++;
}
}
//Prioritise this 3 cell group (win possibility)
winPossibilityPriority[k] = numberOfEnemyPositions - num
berOfFriendlyPositions;
}
}
else
{
//we cannot go here.
winPossibilityPriority[k] = 0;
}
}
//Diagonal Wins:
//Top Left to Bottom Right:
//construct a string which contains the char array
for (int i = 0; i < 1; i++, k++)//C# won't let me use contents strin
g unless it's inside a child here... C# is great...
{
string contents = "";
for (int j = 0; j < width; j++)
{
contents += OX[j * 4];
}
//search for an empty cell. If it has one continue checking. Els
e move on.
if (contents.Contains(" "))
{
if (contents.Contains(enemy))
{
int numberOfEnemyPositions = 0;
int numberOfFriendlyPositions = 0;
//count how many enemies && friendlies are in the 3 cell
s.
for (int j = 0; j < width; j++)
{
if (contents[j] == enemy)
{
numberOfEnemyPositions++;
}
if (contents[j] == go)
{
numberOfFriendlyPositions++;
}
}
//Prioritise this 3 cell group (win possibility)
winPossibilityPriority[k] = numberOfEnemyPositions - num
berOfFriendlyPositions;
}
}
else
{
//we cannot go here.
winPossibilityPriority[k] = 0;
}
}
//Top Right to Bottom Left:
//construct a string which contains the char array
for (int i = 0; i < 1; i++, k++)//C# won't let me use contents strin
g unless it's inside a child here... C# is great...
{
string contents = "";
for (int j = 2; j <= 6 ; j+=2)
{
contents += OX[j];
}
//search for an empty cell. If it has one continue checking. Els
e move on.
if (contents.Contains(" "))
{
if (contents.Contains(enemy))
{
int numberOfEnemyPositions = 0;
int numberOfFriendlyPositions = 0;
//count how many enemies && friendlies are in the 3 cell
s.
for (int j = 0; j < width; j++)
{
if (contents[j] == enemy)
{
numberOfEnemyPositions++;
}
if (contents[j] == go)
{
numberOfFriendlyPositions++;
}
}
//Prioritise this 3 cell group (win possibility)
winPossibilityPriority[k] = numberOfEnemyPositions - num
berOfFriendlyPositions;
}
}
else
{
//we cannot go here.
winPossibilityPriority[k] = 0;
}
}
//NOW ALL POSSIBLE WAYS TO WIN HAVE BEEN EVALUATED ONCE.
//Everything has been giver a value of 2, 1, 0, -1 or 2
//WIN OR LOSE EVENTS:
//-2 means there are 2 allies in this sector. Any sector with this v
alue means that one move will win the game!
//2 means there are 2 enemies in this sector and so is High Priority
! One move will stop the enemy winning via this sector.
//NORMAL GAMEPLAY:
//-1 means there is one ally in this sector. Going here will make th
is -2 for the enemy, during standard gameplay this is the highest value sector.
//1 means there is an enemy in this sector. Low priority event.
//0 means there is no value to playing in this sector. Either there
is one enemy & one ally, or there is neither an ally nor an enemy.
//Rearrange these into more readable priorities:
for (int i = 0; i < winPossibilityPriority.Length; i++)
{
if (winPossibilityPriority[i] == -1)
{
winPossibilityPriority[i] = 2;
}
else if (winPossibilityPriority[i] == 2)
{
winPossibilityPriority[i] = 3;
}
else if (winPossibilityPriority[i] == -2)
{
winPossibilityPriority[i] = 4;
}
}
//NEW VALUES:
//WIN OR LOSE EVENTS:
//4 means there are 2 allies in this sector. Any sector with this va
lue means that one move will win the game!
//3 means there are 2 enemies in this sector and so is High Priority
! One move will stop the enemy winning via this sector.
//NORMAL GAMEPLAY:
//2 means there is one ally in this sector. Going here will make thi
s -2 for the enemy, during standard gameplay this is the highest value sector.
//1 means there is an enemy in this sector. Low priority event.
//0 means there is no value to playing in this sector. Either there
is one enemy & one ally, or there is neither an ally nor an enemy.
//FIND THE HIGHEST PRIORITY SECTOR:
int highPriorityValue = 0;
int highPrioritySector = 0;
for (int i = 0; i < winPossibilityPriority.Length; i++)
{
if (highPriorityValue < winPossibilityPriority[i])
{
highPriorityValue = winPossibilityPriority[i];
highPrioritySector = i;
}
}
//The highest priority sector is now listed as a location in the arr
ay winPosibilityPriority
//FIND THE ACTUAL GRID LOCATIONS:
//(relative to the OX array)
int[] gridLocations = new int[3];
//If it's horizontal
if (highPrioritySector < 3)
{
gridLocations[0] = highPrioritySector * 3;
for (int i = 1; i < 3; i++)
{
gridLocations[i] = gridLocations[0] + i;
}
}
//If it's vertical
else if (highPrioritySector < 6)
{
gridLocations[0] = highPrioritySector - 3;
for (int i = 1; i < 3; i++)
{
gridLocations[i] = gridLocations[0] + (i * width);
}
}
//If it's diagonal
else if (highPrioritySector == 6)
{
gridLocations[0] = 0;
gridLocations[1] = 4;
gridLocations[2] = 8;
}
else if (highPrioritySector == 7)
{
gridLocations[0] = 2;
gridLocations[1] = 4;
gridLocations[2] = 6;
}
//NOW GO THROUGH THE INDIVIDUAL VALUES OF THE HIGH PRIORITY SECTOR A
ND TAKE YOUR GO
for (int i = 0; i < 3; i++)
{
if (OX[gridLocations[i]] == ' ')
{
return gridLocations[i];
}
}
//IF YOU GET THIS FAR, IT'S FUBAR
//Give an *Important* error warning
Console.Beep();
//Return a value to prevent application hanging
return 4;
}
static void KeepScore()
{
if (go == 'X')
{
scoreX++;
}
else
{
scoreO++;
}
}
static bool GameOver(int gameType)
{
if (gameType == 1)
{
if (CheckWinCriteria() == true)
{
//Write Out the new GridBuilder, as CheckWinCriteria will ha
ve placed hitmarkers on the winning cells
Console.Clear();
Console.Write(GridBuilder());
Console.WriteLine("Well done {0}, you win!", go);
KeepScore();
TournamentUpdate(false);
//Determine the player who starts next time (if its a tourni
)
lastWinner = go;
return true;
}
}
else if (gameType == 2)
{
if (CheckWinCriteria() == true)
{
if (go == computerPlayer)
{
//Write Out the new GridBuilder, as CheckWinCriteria wil
l have placed hitmarkers on the winning cells
Console.Clear();
Console.Write(GridBuilder());
Console.WriteLine("The computer won. Bad Luck!");
}
else
{
//Write Out the new GridBuilder, as CheckWinCriteria wil
l have placed hitmarkers on the winning cells
Console.Clear();
Console.Write(GridBuilder());
Console.WriteLine("Well done, you win!");
}
KeepScore();
TournamentUpdate(true);
//Determine the player who starts next time (if its a tourni
)
lastWinner = go;
return true;
}
}
if (CheckDrawCriteria() == true)
{
Console.WriteLine("Stand down, it's a draw...");
return true;
}
return false;
}
static bool CheckDrawCriteria()
{
for (int i = 0; i < OX.Length; i++)
{
if (OX[i] == ' ')
{
return false;
}
}
return true;
}
static bool CheckWinCriteria()
{
char winMarker = '*';
//Check left column, and then along the rows horizontally
for (int j = 0; j < OX.Length; j += 3)
{
//If all cell's on the horizontal row hits. Game over.
if (OX[j] == go && OX[j + 1] == go && OX[j + 2] == go)
{
OX[j] = winMarker;
OX[j + 1] = winMarker;
OX[j + 2] = winMarker;
return true;
}
}
//Check 1st row, and then down the columns vertically
for (int j = 0; j < width; j++)
{
if (OX[j] == go && OX[j + width] == go && OX[j + 2 * width] == g
o)
{
OX[j] = winMarker;
OX[j + width] = winMarker;
OX[j + 2 * width] = winMarker;
return true;
}
}
//Check diaganol lines
//check for the diagonal starting in the top left
if (OX[0] == go && OX[width + 1] == go && OX[2 * (width + 1)] == go)
{
OX[0] = winMarker;
OX[width + 1] = winMarker;
OX[2 * (width + 1)] = winMarker;
return true;
}
//check for the diagonal starting in the top right
if (OX[width - 1] == go && OX[2 * (width - 1)] == go && OX[3 * (widt
h - 1)] == go)
{
OX[width - 1] = winMarker;
OX[2 * (width - 1)] = winMarker;
OX[3 * (width - 1)] = winMarker;
return true;
}
return false;
}
static void TournamentUpdate(bool singlePlayer)
{
//If we are in a 'tournament'
if (games > 1)
{
Console.WriteLine("Game {0} of {1}", gameNumber, games);
Console.WriteLine("Scores:");
string X = "";
string O = "";
if (singlePlayer)
{
X = (computerPlayer == 'X' ? "Computer" : "You");
O = (computerPlayer == 'O' ? "Computer" : "You");
}
else
{
X = "X";
O = "O";
}
Console.WriteLine("{0}: {1}", X, scoreX);
Console.WriteLine("{0}: {1}", O, scoreO);
}
}
static void Update()
{
TournamentUpdate(false);
AlternateUsers();
Console.WriteLine("{0}'s go!", go);
int i;
do
{
i = MakeArrayPosition(GetCoOrds());
}
while (OX[i] != ' ');
OX[i] = go;
Console.Clear();
Console.Write(GridBuilder());
}
static void SinglePlayerUpdate()
{
TournamentUpdate(true);
AlternateUsers();
if (go != computerPlayer)
{
Console.WriteLine("Your go! You are {0}", go);
int i;
do
{
i = MakeArrayPosition(GetCoOrds());
}
while (OX[i] != ' ');
OX[i] = go;
}
else
{
Console.WriteLine("The computer is taking it's turn...");
//OX[AI()] = go;
OX[MiniMax()] = go;
}
Console.Clear();
Console.Write(GridBuilder());
}
static void AlternateUsers()
{
if (go == 'O')
{
go = 'X';
}
else
{
go = 'O';
}
}
static int MakeArrayPosition(int[] coOrds)
{
int i = 0;
//check first row
for (int k = 0; k < coOrds[1]; k++)
{
if (k + 1 == coOrds[1])
{
for (int j = 1; j < coOrds[0]; j++, i++)
{
}
}
else
{
for (int j = 0; j < width; j++, i++)
{
}
}
}
return i;
}
static int[] GetCoOrds()
{
bool inPlay = true;
while (inPlay)
{
int[] coOrds = CheckCoOrdinates(GetCoOrdinates());
if (coOrds[0] != 0)
{
return coOrds;
}
}
int[] csDoesntWork = new int[2];
return csDoesntWork;
}
static int[] CheckCoOrdinates(string rawInput)
{
int[] coOrds = new int[2];
//horizontal co-ordinate
if (rawInput.ToLower().Contains("a"))
{
coOrds[0] = 1;
}
else if (rawInput.ToLower().Contains("b"))
{
coOrds[0] = 2;
}
else if (rawInput.ToLower().Contains("c"))
{
coOrds[0] = 3;
}
//when coOrds[0] == 0, this is an error!
else
{
coOrds[0] = 0;
}
//Vertical co-ordinate
if (rawInput.ToLower().Contains("1"))
{
coOrds[1] = 1;
}
else if (rawInput.ToLower().Contains("2"))
{
coOrds[1] = 2;
}
else if (rawInput.ToLower().Contains("3"))
{
coOrds[1] = 3;
}
//when coOrds[0] == 0, this is an error!
else
{
coOrds[0] = 0;
}
return coOrds;
}
static string GetCoOrdinates()
{
string coOrds;
Console.Write("Enter the co-ordinates you want to make an entry in:
");
coOrds = Console.ReadLine();
return coOrds;
}
static string GridBuilder()
{
string grid = "";
for (int i = 0; i < OX.Length; i++)
{
grid += OX[i];
if ((i + 1) % width == 0)
{
grid += "\n";
if ((i + 1) != OX.Length)
{
for (int j = 0; j < (spacer.Length * width); j++)
{
grid += "-";
}
}
grid += "\n";
}
else
{
grid += spacer;
}
}
return grid;
}
static void Initialise()
{
for (int i = 0; i < OX.Length; i++)
{
OX[i] = ' ';
}
go = 'O';
}
static int MiniMax()
{
int bestGo = 0;
int[] terminalValues = new int[OX.Length];
//determine the terminal value of going in each cell:
for (int i = 0; i < terminalValues.Length; i++)
{
terminalValues[i] = ValueCell(i, OX, go);
}
//FIND & RETURN THE BEST GO:
for (int i = 0; i < terminalValues.Length; i++)
{
bestGo = Math.Max(bestGo, terminalValues[i]);
}
return bestGo;
}
static int ValueCell(int cell, char[] currentGrid, char whosGo)
{
//pass OX as the current grid if it's the first time, else make amme
ndments to the 'current grid' where OX is left as the actual inPlay values
int cellValue = -2;
//If this would be an illegal move:
if (currentGrid[cell] != ' ')
{
return -2;
}
//Else if it's a legal move:
currentGrid[cell] = whosGo;
//If the currentGrid is full (we are at the last fork of the process
)
if (!GridSpace(currentGrid))
{
//If in the boards current state teh computer wins, return a
value of 1
if (CheckCurrentWin(currentGrid, computerPlayer))
{
return 1;
}
//If in the boards current state, the human wins, return a v
alue of -1
else if (CheckCurrentWin(currentGrid, RotateGo(computerPlaye
r)))
{
return -1;
}
//Else we drew, return 0
else
{
return 0;
}
}
//declare an array of cell values for each possible move & m
ake them 'impossible'
int[] goValue = new int[9];
for (int i = 0; i < goValue.Length; i++)
{
goValue[i] = -2;
}
//now set those that are possible to their actual values
for (int i = 0; i < currentGrid.Length; i++)
{
if (currentGrid[i] == ' ')
{
goValue[i] = ValueCell(i, currentGrid, RotateGo(whos
Go));
}
}
//Now find the highest possible outcome by making this move:
for (int i = 0; i < goValue.Length; i++)
{
cellValue = Math.Max(cellValue, goValue[i]);
}
//return trhe cell's value to the parent fork.
return cellValue;
}
static bool GridSpace(char[] currentGrid)
{
foreach (char cell in currentGrid)
{
if (cell == ' ')
{
return true;
}
}
return false;
}
static char RotateGo(char currentGo)
{
if (currentGo == 'X')
{
currentGo = 'O';
}
else
{
currentGo = 'X';
}
return currentGo;
}
static bool CheckCurrentWin(char[] currentGrid, char whosGo)
{
//Check left column, and then along the rows horizontally
for (int j = 0; j < currentGrid.Length; j += 3)
{
//If all cell's on the horizontal row hits. Game over.
if (currentGrid[j] == whosGo && currentGrid[j + 1] == whosGo &&
currentGrid[j + 2] == whosGo)
{
return true;
}
}
//Check 1st row, and then down the columns vertically
for (int j = 0; j < width; j++)
{
if (currentGrid[j] == whosGo && currentGrid[j + width] == whosGo
&& currentGrid[j + 2 * width] == whosGo)
{
return true;
}
}
//Check diaganol lines
//check for the diagonal starting in the top left
if (currentGrid[0] == whosGo && currentGrid[width + 1] == whosGo &&
currentGrid[2 * (width + 1)] == whosGo)
{
return true;
}
//check for the diagonal starting in the top right
if (currentGrid[width - 1] == whosGo && currentGrid[2 * (width - 1)]
== whosGo && currentGrid[3 * (width - 1)] == whosGo)
{
return true;
}
return false;
}
}
}

Você também pode gostar