Código fuente
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Game
{
/// <summary>
///
/// </summary>
public enum Players
{
Human = 4,
Computer = 7,
NoBody = 0
}
/// <summary>
///
/// </summary>
public class TicTacToe
{
int currentIndex=0;
int[] winnerCells = new int[3] { 0,0,0};
int[] maze = new int[9] { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
/// <summary>
/// Cell for the last move
/// </summary>
public int LastMove
{
get
{
return currentIndex;
}
}
/// <summary>
/// Winner cells
/// </summary>
public int[] WinnerCells {
get {
return winnerCells;
}
}
/// <summary>
/// Game Maze
/// </summary>
public int[] Maze {
get {
return maze;
}
}
/// <summary>
/// Determines if the game it's over
/// </summary>
public bool ItIsOver {
get {
bool r = false;
int c = 0;
for (int i = 0; i < maze.Length; i++) {
if (maze[i] != (int) Players.NoBody ) {
c++;
}
}
r = c == maze.Length;
return r;
}
}
/// <summary>
/// Reset the game
/// </summary>
public void Reset()
{
for (int i = 0; i < maze.Length; i++)
maze[i] = 0;
for (int i = 0; i < winnerCells.Length; i++)
winnerCells[i] = 0;
currentIndex = -1;
}
/// <summary>
/// Default Constructor
/// </summary>
public TicTacToe()
{
Reset();
}
/// <summary>
/// Find who wins
/// </summary>
/// <returns></returns>
public Players WhoWins()
{
Players result = Players.NoBody;
bool win = false;
int winner = 0;
GetWinner(ref win, ref winner, 0, 1, 2, 3, 3, 3, 3);
if (!win)
{
GetWinner(ref win, ref winner, 0, 3, 6, 1, 1, 1, 3);
if (!win)
{
GetWinner(ref win, ref winner, 0, 4, 8, 2, 0, -2, 2);
}
}
if (win)
{
if (winner == (int)Players.Computer)
result = Players.Computer;
else
if (winner == (int)Players.Human)
result = Players.Human;
}
else
{
result = Players.NoBody;
}
return result;
}
/// <summary>
/// Find who wins
/// </summary>
/// <param name="win"></param>
/// <param name="winner"></param>
/// <param name="c1">cell 1</param>
/// <param name="c2">cell 2</param>
/// <param name="c3">cell 3</param>
/// <param name="d1">delta change in cell 1</param>
/// <param name="d2">delta change in cell 2</param>
/// <param name="d3">delta change in cell 3</param>
/// <param name="times">times to do the search this can be done 3 or 2 times</param>
private void GetWinner(ref bool win, ref int winner, int c1, int c2, int c3, int d1, int d2, int d3, int times)
{
for (int i = 0; i < times && !win; i++)
{
if (maze[c1] != (int)Players.NoBody && (maze[c1] == maze[c2]) && (maze[c2] == maze[c3]))
{
winner = maze[c1];
currentIndex = c1;
win = true;
winnerCells[0] = c1;
winnerCells[1] = c2;
winnerCells[2] = c3;
}
else
{
c1 += d1;
c2 += d2;
c3 += d3;
}
}
}
/// <summary>
/// Mark a cell
/// </summary>
/// <param name="number">number of cell to be marked</param>
/// <param name="player">player who marks a cell</param>
/// <returns></returns>
public bool Mark(int index, Players player)
{
bool result = false;
if (index < 0 && index > 8)
throw new Exception("Index out of bounds");
if (maze[index] == (int) Players.NoBody )
{
maze[index] = (int)player;
result = true;
}
return result;
}
/// <summary>
/// Mark a cell
/// </summary>
/// <param name="row">row number</param>
/// <param name="col">column number</param>
/// <param name="player">player who marks a cell</param>
/// <returns></returns>
public bool Mark(int row, int col, Players player)
{
bool result = false;
int index = 0;
if (row < 0 && row > 2)
throw new Exception("Row out of bounds");
if (col < 0 && col > 2)
throw new Exception("Column out of bounds");
index = row * 3 + col;
if (maze[index] == (int)Players.NoBody)
{
maze[index] = (int)player;
result = true;
}
return result;
}
/// <summary>
/// Invokes a move strategy
/// </summary>
public void Move()
{
if (!TryToWin(0, 1, 2, 3, 3, 3, 3))
{
if (!TryToWin(0, 3, 6, 1, 1, 1, 3))
{
if (!TryToWin(0, 4, 8, 2, 0, -2, 2))
{
if (!BlockEnemy(0, 1, 2, 3, 3, 3, 3))
{
if (!BlockEnemy(0, 3, 6, 1, 1, 1, 3))
{
if (!BlockEnemy(0, 4, 8, 2, 0, -2, 2))
{
DoMove();
}
}
}
}
}
}
}
/// <summary>
/// Do a move. This is done when it is not posible to do a winning move or it is not needed to block the enemy .
/// </summary>
/// <param name="c1">cell 1</param>
/// <param name="c2">cell 2</param>
/// <param name="c3">cell 3</param>
/// <param name="d1">delta change in cell 1</param>
/// <param name="d2">delta change in cell 2</param>
/// <param name="d3">delta change in cell 3</param>
/// <param name="times">times to do the search this can be done 3 or 2 times</param>
/// <returns></returns>
private bool DoMove()
{
bool result = false;
if (maze[0] == (int)Players.Computer && maze[1] == (int)Players.NoBody && maze[2] == (int)Players.NoBody)
{
maze[1] = (int)Players.Computer;
currentIndex = 1;
result = true;
}
else
if (maze[0] == (int)Players.Computer && maze[3] == (int)Players.NoBody && maze[6] == (int)Players.NoBody)
{
maze[3] = (int)Players.Computer;
currentIndex = 3;
result = true;
}
else
if (maze[0] == (int)Players.Computer && maze[4] == (int)Players.NoBody && maze[8] == (int)Players.NoBody)
{
maze[4] = (int)Players.Computer;
currentIndex = 4;
result = true;
}
else
if (maze[1] == (int)Players.Computer && maze[0] == (int)Players.NoBody && maze[2] == (int)Players.NoBody)
{
maze[0] = (int)Players.Computer;
currentIndex = 0;
result = true;
}
else
if (maze[1] == (int)Players.Computer && maze[4] == (int)Players.NoBody && maze[7] == (int)Players.NoBody)
{
maze[4] = (int)Players.Computer;
currentIndex = 4;
result = true;
}
else
if (maze[2] == (int)Players.Computer && maze[0] == (int)Players.NoBody && maze[1] == (int)Players.NoBody)
{
maze[0] = (int)Players.Computer;
currentIndex = 0;
result = true;
}
else
if (maze[2] == (int)Players.Computer && maze[4] == (int)Players.NoBody && maze[6] == (int)Players.NoBody)
{
maze[4] = (int)Players.Computer;
currentIndex = 4;
result = true;
}
else
if (maze[2] == (int)Players.Computer && maze[5] == (int)Players.NoBody && maze[8] == (int)Players.NoBody)
{
maze[5] = (int)Players.Computer;
currentIndex = 5;
result = true;
}
else
if (maze[3] == (int)Players.Computer && maze[0] == (int)Players.NoBody && maze[6] == (int)Players.NoBody)
{
maze[0] = (int)Players.Computer;
currentIndex = 0;
result = true;
}
else
if (maze[3] == (int)Players.Computer && maze[4] == (int)Players.NoBody && maze[5] == (int)Players.NoBody)
{
maze[4] = (int)Players.Computer;
currentIndex = 4;
result = true;
}
else
if (maze[5] == (int)Players.Computer && maze[3] == (int)Players.NoBody && maze[4] == (int)Players.NoBody)
{
maze[3] = (int)Players.Computer;
currentIndex = 3;
result = true;
}
else
if (maze[5] == (int)Players.Computer && maze[2] == (int)Players.NoBody && maze[8] == (int)Players.NoBody)
{
maze[2] = (int)Players.Computer;
currentIndex = 2;
result = true;
}
else
if (maze[6] == (int)Players.Computer && maze[7] == (int)Players.NoBody && maze[8] == (int)Players.NoBody)
{
maze[7] = (int)Players.Computer;
currentIndex = 7;
result = true;
}
else
if (maze[6] == (int)Players.Computer && maze[0] == (int)Players.NoBody && maze[3] == (int)Players.NoBody)
{
maze[0] = (int)Players.Computer;
currentIndex = 0;
result = true;
}
else
if (maze[6] == (int)Players.Computer && maze[4] == (int)Players.NoBody && maze[2] == (int)Players.NoBody)
{
maze[4] = (int)Players.Computer;
currentIndex = 4;
result = true;
}
else
if (maze[7] == (int)Players.Computer && maze[6] == (int)Players.NoBody && maze[8] == (int)Players.NoBody)
{
maze[6] = (int)Players.Computer;
currentIndex = 6;
result = true;
}
else
if (maze[7] == (int)Players.Computer && maze[4] == (int)Players.NoBody && maze[1] == (int)Players.NoBody)
{
maze[0] = (int)Players.Computer;
currentIndex = 0;
result = true;
}
else
if (maze[8] == (int)Players.Computer && maze[2] == (int)Players.NoBody && maze[5] == (int)Players.NoBody)
{
maze[2] = (int)Players.Computer;
currentIndex = 2;
result = true;
}
else
if (maze[8] == (int)Players.Computer && maze[4] == (int)Players.NoBody && maze[0] == (int)Players.NoBody)
{
maze[4] = (int)Players.Computer;
currentIndex = 4;
result = true;
}
else
if (maze[8] == (int)Players.Computer && maze[6] == (int)Players.NoBody && maze[7] == (int)Players.NoBody)
{
maze[6] = (int)Players.Computer;
currentIndex = 6;
result = true;
}
if (!result)
{
int[] seq = new int[] { 4, 2, 6, 8, 3, 7, 0, 5, 1 };
for (int i = 0; i < seq.Length && !result; i++)
{
result = maze[seq[i]] == (int)Players.NoBody;
if (result)
{
maze[seq[i]] = (int)Players.Computer;
currentIndex = seq[i];
}
}
}
return result;
}
/// <summary>
/// Try to block the next posible winning move from the human
/// </summary>
/// <param name="c1">cell 1</param>
/// <param name="c2">cell 2</param>
/// <param name="c3">cell 3</param>
/// <param name="d1">delta change in cell 1</param>
/// <param name="d2">delta change in cell 2</param>
/// <param name="d3">delta change in cell 3</param>
/// <param name="times">times to do the search this can be done 3 or 2 times</param>
/// <returns></returns>
private bool BlockEnemy(int c1, int c2, int c3, int d1, int d2, int d3, int times)
{
bool result = false;
for (int i = 0; i < times && !result; i++)
{
if ((maze[c1] == maze[c2] && maze[c1] == (int)Players.Human && maze[c3] == (int)Players.NoBody))
{
maze[c3] = (int)Players.Computer;
currentIndex = c3;
result = true;
}
else
if ((maze[c1] == maze[c3] && maze[c1] == (int)Players.Human && maze[c2] == (int)Players.NoBody))
{
maze[c2] = (int)Players.Computer;
currentIndex = c2;
result = true;
}
else
if ((maze[c2] == maze[c3] && maze[c2] == (int)Players.Human && maze[c1] == (int)Players.NoBody))
{
maze[c1] = (int)Players.Computer;
currentIndex = c1;
result = true;
}
else
{
c1 += d1;
c2 += d2;
c3 += d3;
}
}
return result;
}
/// <summary>
/// Try to do a winning move, finding two cells with the computer player mark
/// and trying to put a winning mark into an empty cell.
///
/// The cells are based, on a linear vector with 9 positions from 0..8
/// </summary>
/// <param name="c1">cell 1</param>
/// <param name="c2">cell 2</param>
/// <param name="c3">cell 3</param>
/// <param name="d1">delta change in cell 1</param>
/// <param name="d2">delta change in cell 2</param>
/// <param name="d3">delta change in cell 3</param>
/// <param name="times">times to do the search this can be done 3 or 2 times</param>
/// <returns></returns>
private bool TryToWin(int c1, int c2, int c3, int d1, int d2, int d3, int times)
{
bool result = false;
for (int i = 0; i < times && !result; i++)
{
if ((maze[c1] == maze[c2] && maze[c1] == (int)Players.Computer && maze[c3] == (int)Players.NoBody))
{
maze[c3] = (int)Players.Computer;
currentIndex = c3;
result = true;
}
else
if ((maze[c1] == maze[c3] && maze[c1] == (int)Players.Computer && maze[c2] == (int)Players.NoBody))
{
maze[c2] = (int)Players.Computer;
currentIndex = c2;
result = true;
}
else
if ((maze[c2] == maze[c3] && maze[c2] == (int)Players.Computer && maze[c1] == (int)Players.NoBody))
{
maze[c1] = (int)Players.Computer;
currentIndex = c1;
result = true;
}
else
{
c1 += d1;
c2 += d2;
c3 += d3;
}
}
return result;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Game;
namespace ElGato
{
public partial class MainPage : PhoneApplicationPage
{
private Line line = null;
private bool ItsOver = false;
private Game.TicTacToe gato = new Game.TicTacToe();
// Constructor
public MainPage()
{
InitializeComponent();
}
private void btn8_Click(object sender, RoutedEventArgs e)
{
if (ItsOver)
{
MessageBox.Show("JUEGO TERMINADO!!!");
return;
}
if (sender is Button) {
string value = Convert.ToString((sender as Button).Content);
if (
value != "X" && value != "O"
)
{
(sender as Button).Content = "X";
int cell = Convert.ToInt32 ((sender as Button).Name.Replace("btn", ""));
gato.Mark(cell, Players.Human);
gato.Move();
switch (gato.LastMove) {
case 0:
btn0.Content = "O";
break;
case 1:
btn1.Content = "O";
break;
case 2:
btn2.Content = "O";
break;
case 3:
btn3.Content = "O";
break;
case 4:
btn4.Content = "O";
break;
case 5:
btn5.Content = "O";
break;
case 6:
btn6.Content = "O";
break;
case 7:
btn7.Content = "O";
break;
case 8:
btn8.Content = "O";
break;
default:
break;
}
switch (gato.WhoWins()) {
case Players.Computer :
ItsOver = true;
ShowLine();
txtMsg.Text = "FIN DEL JUEGO (PERDISTE)";
break;
case Players.Human :
ItsOver = true;
ShowLine();
txtMsg.Text = "FIN DEL JUEGO (GANASTE)";
break;
default:
if (gato.ItIsOver) {
ItsOver = true;
txtMsg.Text = "FIN DEL JUEGO (EMPATE)";
}
break;
}
}
}
}
private void ShowLine() {
switch (gato.WinnerCells[0]) {
case 0:
line.X1 = 107;
line.Y1 =280;
break;
case 1:
line.X1 = 241;
line.Y1 =280;
break;
case 2:
line.X1 = 354;
line.Y1 =280;
break;
case 3:
line.X1 = 107;
line.Y1 =423;
break;
case 4:
line.X1 = 241;
line.Y1 =423;
break;
case 5:
line.X1 = 354;
line.Y1 =423;
break;
case 6:
line.X1 = 107;
line.Y1 =550;
break;
case 7:
line.X1 = 241;
line.Y1 =550;
break;
case 8:
line.X1 = 354;
line.Y1 =550;
break;
default :
break;
}
switch (gato.WinnerCells[2])
{
case 0:
line.X2 = 107;
line.Y2 = 280;
break;
case 1:
line.X2 = 241;
line.Y2 = 280;
break;
case 2:
line.X2 = 354;
line.Y2 = 280;
break;
case 3:
line.X2 = 107;
line.Y2 = 423;
break;
case 4:
line.X2 = 241;
line.Y2 = 423;
break;
case 5:
line.X2 = 354;
line.Y2 = 423;
break;
case 6:
line.X2 = 107;
line.Y2 = 550;
break;
case 7:
line.X2 = 241;
line.Y2 = 550;
break;
case 8:
line.X2 = 354;
line.Y2 = 550;
break;
default:
break;
}
line.Visibility = System.Windows.Visibility.Visible;
}
private void button1_Click(object sender, RoutedEventArgs e)
{
gato.Reset();
ItsOver = false;
btn0.Content = string.Empty ;
btn1.Content = string.Empty;
btn2.Content = string.Empty;
btn3.Content = string.Empty;
btn4.Content = string.Empty;
btn5.Content = string.Empty;
btn6.Content = string.Empty;
btn7.Content = string.Empty;
btn8.Content = string.Empty;
txtMsg.Text = string.Empty;
line.Visibility = System.Windows.Visibility.Collapsed;
}
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
line = new Line();
line.Stroke = new SolidColorBrush(Colors.Red);
line.StrokeThickness = 15;
this.defaultView.Children.Add(line);
}
}
}
<phone:PhoneApplicationPage
x:Class="ElGato.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True" Loaded="PhoneApplicationPage_Loaded">
<Canvas Name="defaultView">
<Button Canvas.Left="37" Canvas.Top="230" Height="150" Name="btn0" Width="150" FontSize="72" Click="btn8_Click" BorderThickness="0,0,3,3" />
<Button Canvas.Left="160" Canvas.Top="230" FontSize="72" Height="150" Name="btn1" Width="150" Click="btn8_Click" BorderThickness="3,0,3,3" />
<Button Canvas.Left="284" Canvas.Top="230" FontSize="72" Height="150" Name="btn2" Width="150" Click="btn8_Click" BorderThickness="3,0,0,3" />
<Button Canvas.Left="37" Canvas.Top="353" FontSize="72" Height="150" Name="btn3" Width="150" Click="btn8_Click" BorderThickness="0,3,3,3" />
<Button Canvas.Left="161" Canvas.Top="353" FontSize="72" Height="150" Name="btn4" Width="150" Click="btn8_Click" />
<Button Canvas.Left="284" Canvas.Top="353" FontSize="72" Height="150" Name="btn5" Width="150" Click="btn8_Click" BorderThickness="3,3,0,3" />
<Button Canvas.Left="37" Canvas.Top="476" FontSize="72" Height="150" Name="btn6" Width="150" Click="btn8_Click" BorderThickness="0,3,3,0" />
<Button Canvas.Left="161" Canvas.Top="476" FontSize="72" Height="150" Name="btn7" Width="150" Click="btn8_Click" BorderThickness="3,3,3,0" />
<Button Canvas.Left="284" Canvas.Top="476" FontSize="72" Height="150" Name="btn8" Width="150" Click="btn8_Click" BorderThickness="3,3,0,0" />
<Button Canvas.Left="26" Canvas.Top="644" Content="JuGar de NueVo" Height="74" Name="button1" Width="413" BorderThickness="2" Background="RoyalBlue" Click="button1_Click" />
<TextBlock Canvas.Left="12" Canvas.Top="36" Height="103" Name="textBlock1" Text="El JuGO Del GaTO" Width="302" FontSize="40" />
<Image Canvas.Left="334" Canvas.Top="36" Height="124" Name="image1" Stretch="Fill" Width="134" Source="/ElGato;component/Images/cat-icon-small.png" />
<TextBlock Canvas.Left="38" Canvas.Top="166" Height="57" Name="txtMsg" Text="" Width="401" Foreground="Red" FontWeight="Bold" />
</Canvas>
</phone:PhoneApplicationPage>