Desarrollo de juegos de Windows Phone 7 Creación de Tic-Tac-Toe con XNA

XNA es un marco de creación de juegos de alto nivel para dispositivos de Microsoft, incluidos PC con Windows, Xbox 360 y el nuevo sistema operativo Windows Phone 7. En un tutorial anterior, cubrimos los aspectos básicos del marco XNA, incluido el manejo de entradas y la visualización de sprites. En este artículo, aprenderá cómo combinar esas habilidades con una idea de juego propia para crear algo divertido de jugar y fácil de aprender..

Descripción del proyecto

En este tutorial, vas a crear un juego simple de Tic-Tac-Toe jugable con amigos. Tic-Tac-Toe es un juego simple en el que dos jugadores alternan turnos colocando personajes en una cuadrícula de tres por tres. El primer jugador usa una O y el segundo usa una X. Para ganar el juego, un jugador debe organizar tres de sus personajes en una fila, columna o diagonal.

Si bien este juego es simple, requiere un par de habilidades diferentes para construir. Primero, usarás XNA y sus capacidades gráficas para construir tu juego. Como tal, necesitas estar familiarizado con la visualización de sprites. En segundo lugar, debe saber cómo manejar los toques en la pantalla táctil del teléfono. Afortunadamente, XNA proporciona una API de alto nivel para acceder a estos toques. Finalmente, debe aplicar un poco de conocimientos de programación y lógica para decidir el ganador. Para este tutorial, mucho de eso te será dado. Cuando construyas juegos en el futuro, tendrás que crear tus propias ideas y lógica..

Creando tu proyecto

Para comenzar, asegúrese de haber instalado las últimas herramientas de desarrollo de Windows Phone 7. Si no ha actualizado sus herramientas desde el último tutorial de WP7 en MobileTuts, debe visitar el Centro de descarga de Microsoft y obtener la versión RTW. Esta última versión viene con el emulador final que muestra cómo funcionarán sus aplicaciones en el hardware del día del lanzamiento..

Después de asegurarse de que sus herramientas estén actualizadas, abra Visual Studio 2010 y haga clic en el enlace "Nuevo proyecto ..." en la barra lateral izquierda. En el cuadro de diálogo que aparece, elija "XNA Game Studio 4" en la columna de la izquierda y asegúrese de que la plantilla "Juego de Windows Phone (4.0)" esté seleccionada a la derecha. Asigne a su proyecto un nombre apropiado como "TicTacToe" y confirme que la casilla de verificación "Crear directorio para la solución" esté seleccionada. Si ha hecho todo esto correctamente, su cuadro de diálogo debe coincidir con la siguiente imagen:

Haga clic en "Aceptar" para crear su nuevo proyecto. Visual Studio 2010 generará los archivos necesarios en su directorio especificado y se abrirá Game1.cs para editar.

Importar contenido multimedia

Ya que usarás sprites para todos los gráficos del juego en este proyecto, necesitas importar los elementos requeridos en tu proyecto. En la descarga que acompaña a este tutorial encontrarás un Medios de comunicación Directorio que contiene una variedad de imágenes. En el explorador de soluciones en el lado derecho de la pantalla, ubique el proyecto de Contenido (llamado TicTacToeContent) y haga clic derecho sobre él. En el menú contextual, seleccione "Agregar> Elemento existente ...". Cuando se abra el cuadro de diálogo, vaya a la Medios de comunicación La carpeta que descomprimiste de la descarga del tutorial y seleccionas todas las imágenes que contiene. Debería poder decir de los nombres de las imágenes exactamente qué contiene cada elemento..

Después de importar sus medios, su explorador de soluciones debería parecerse a lo siguiente:

Cargando y asignando contenido

Ahora que sus medios se han importado en el proyecto de contenido adjunto a su solución, debe cargar cada imagen como una textura separada. Debido a que usarás estas texturas a lo largo de tu juego, las almacenarás en campos dentro de tu clase de juego. Abra el archivo Game1.cs y agregue los siguientes campos al principio de su declaración de clase:

 Texture2D gridTexture; Rectángulo cuadrículaRectangle; Texture2D resetButton; Rectangle resetButtonPosition; Pieza de textura2D; Texture2D xPiece; Texture2D oWinner; Texture2D xWinner; Texture2D noWinner; Textura2D oTurn; Textura2D xTurn; 

Verá que cada una de las imágenes que importó tiene un campo para hacer una copia de seguridad. Además, la cuadrícula de reproducción principal y la textura del botón de reinicio tienen campos de tipo Rectángulo que se utilizará para posicionar esos artículos. Estos se almacenan como campos porque no cambiarán a lo largo del juego.

Ahora que ha creado los campos apropiados, es hora de crear una instancia de Textura2d y Rectángulo Objetos que se asignan a los campos. Desplácese hasta su Game1.cs archivo hasta que llegue a la LoadContent método. Dentro de este método, inserte el siguiente código después de la línea que dice spriteBatch = new SpriteBatch (GraphicsDevice);:

 gridTexture = Content.Load("TicTacToe_Grid"); gridRectangle = nuevo Rectángulo (0, 0, spriteBatch.GraphicsDevice.Viewport.Width, spriteBatch.GraphicsDevice.Viewport.Height); oPiece = Content.Load("TicTacToe_O"); xPiece = Content.Load("TicTacToe_X"); resetButton = Content.Load("TicTacToe_Reset"); resetButtonPosition = new Rectangle (spriteBatch.GraphicsDevice.Viewport.Width / 2 - (resetButton.Width / 2), spriteBatch.GraphicsDevice.Viewport.Height - 95, resetButton.Width, resetButton.Height); oWinner = Content.Load("TicTacToe_O_Winner"); xWinner = Content.Load("TicTacToe_X_Winner"); noWinner = Content.Load("TicTacToe_Draw"); oTurn = Content.Load("TicTacToe_O_Turn"); xTurn = Content.Load("TicTacToe_X_Turn"); 

Definiendo el flujo de trabajo del juego

Después de cargar los sprites que se usarán en el juego, debes crear el flujo de trabajo en el que se ejecutará el juego. Para los propósitos de Tic-Tac-Toe, esto es bastante simple y se parece a lo siguiente:

  1. Dibuja la cuadrícula de juego.
  2. Dibuja las piezas jugadas actualmente.
  3. Dibuja el estado actual del juego (de quién es el turno o si hay un ganador)
  4. Si el juego se ha ganado o ya no se puede ganar, dibuja el botón Restablecer
  5. Si nadie ha ganado y el juego aún se puede ganar, maneja los toques en la cuadrícula y busca un ganador si se hace un toque.
  6. Si el juego se ha ganado o ya no se puede ganar, maneja el botón de reinicio
    • Si se toca el botón de reinicio, reinicia el juego

Como probablemente pueda decir, estos pasos se dividen en una de las dos categorías básicas, Dibujar o Actualizar. Escaneando a través de la Game1.cs archivo verá que tiene dos métodos, Dibujar y Actualizar que son los contenedores perfectos para el código requerido para describir el flujo de trabajo.

Almacenamiento del estado del juego

Al observar el flujo de trabajo, puede discernir que hay cuatro elementos diferentes de los que se debe realizar un seguimiento para administrar el estado del juego. Primero, debes seguir el estado de cada punto de la cuadrícula en el campo de juego. Lo harás usando una enumeración personalizada y una matriz multidimensional. A continuación, debe hacer un seguimiento de si el juego ha sido ganado y por quién. En tercer lugar, debe seguir el turno de quién es. Por último, debes hacer un seguimiento de si el juego se puede ganar. Este artículo se inicializa como cierto y se recalcula después de que cada jugador tenga un turno. Cuando se completan todos los puntos de la cuadrícula, esto cambia a falso.

Comenzarás por definir la enumeración personalizada que describe a un jugador para tu juego. En la parte superior de su archivo de clase, sobre su declaración de clase, agregue el siguiente código:

 enumeración pública TicTacToePlayer Ninguno, PlayerO, PlayerX 

Esta enumeración delinea a tres jugadores (Ninguno, PlayerO y PlayerX) y se utilizará para rastrear tanto el estado de la cuadrícula como el ganador del juego. Ahora, agregue las variables de instancia que le ayudarán a rastrear el estado del juego. Estos elementos deben agregarse en la parte superior de su declaración de clase:

 bool winnable; Ganador de TicTacToePlayer; TicTacToePlayer actual; TicTacToePlayer [,] rejilla; 

Estás almacenando cuatro cosas aquí. Primero, delinee si el juego todavía es ganable. Segundo, declaras el ganador. Si el ganador es Ninguno, el juego continúa. Después de eso, almacenas el jugador actual. Por último, se almacena el estado de la cuadrícula. En este punto, aún necesita inicializar cada una de estas variables. Pensando en el futuro, sabe que tendrá que reinicializarlos cada vez que alguien haga clic en el botón Restablecer y, como tal, podemos crear un nuevo método que maneje esa inicialización. Agregue el nuevo método a su clase debajo del Inicializar método de la siguiente manera:

 privado void Reset () winnable = true; ganador = TicTacToePlayer.None; cuadrícula = nuevo TicTacToePlayer [3, 3]; para (int i = 0; i < 3; i++)  for (int j = 0; j < 3; j++)  grid[i, j] = TicTacToePlayer.None;    

Ahora, llama a este nuevo método desde el Inicializar Método cambiándolo para que lea como sigue:

 anulación protegida void Initialize () Reset (); base.Initialize ();  

En este punto, está almacenando todos los datos que necesita, por lo que debería ser sencillo comenzar a dibujar la interfaz.

Dibujando la interfaz de juego

Antes de comenzar a dibujar, debe configurar el ancho y la altura preferidos para su dispositivo. Harás esto dentro de la Juego1 constructor. Cámbielo para que lea como sigue:

 public Game1 () graphics = new GraphicsDeviceManager (this); Content.RootDirectory = "Contenido"; graphics.PreferredBackBufferWidth = 480; graphics.PreferredBackBufferHeight = 800; // La velocidad de fotogramas es de 30 fps por defecto para Windows Phone. TargetElapsedTime = TimeSpan.FromTicks (333333);  

Ha agregado declaraciones que declaran que desea que el ancho del búfer de respaldo sea de 480 píxeles y que la altura sea de 800 píxeles. Esto simplifica enormemente el dibujo del resto de los componentes para el juego..

Para mantener las cosas simples, vas a realizar cada paso de dibujo dentro de un método separado. Estos métodos serán llamados desde la base. Dibujar Método que ya existe. Comencemos pensando en algunos buenos nombres para cada uno de los pasos del flujo de trabajo del juego, creando métodos con ese nombre y agregando llamadas a esos methos desde Dibujar. En mi opinión, los siguientes nombres de métodos describen adecuadamente lo que harán y los pasos de flujo de trabajo cubiertos:

  • DrawGrid: cubre el primer paso del flujo de trabajo y dibuja la cuadrícula de reproducción
  • DrawPieces: cubre el paso de flujo de trabajo dos y dibuja piezas donde se ha reproducido una pieza
  • DrawStatus: cubre el paso tres del flujo de trabajo y dibuja el estado actual del juego ("Turno de O", "Turno de X", "O Wins!", "X Wins!", O "Draw!")
  • DrawResetButton: cubre el paso 4 del flujo de trabajo y dibuja el botón de reinicio

Cree estos métodos ahora insertando el siguiente código debajo de su Dibujar método:

 private void DrawGrid ()  private void DrawPieces ()  private void DrawStatus ()  private void DrawResetButton ()  

Escribirá el código para estos métodos en un momento, pero por ahora necesita agregarlos a su Dibujar Método cambiándolo para que lea como sigue:

 anular protegido anular dibujar (GameTime gameTime) GraphicsDevice.Clear (Color.Black); spriteBatch.Begin (); DrawGrid (); DrawPieces (); DrawStatus (); DrawResetButton (); spriteBatch.End (); base.Draw (gameTime);  

Notará que ha rodeado las llamadas a sus métodos de ayuda con las llamadas a la SpriteBatch objetos Empezar y Fin metodos Haces esto porque tus métodos de ayuda serán todos sprites de dibujo y es mucho más eficiente llamar al Empezar y Fin emparejar una vez dentro de Dibujar En lugar de dentro de cada método de ayuda.

Ahora, vamos a trabajar para que aparezca la cuadrícula de juego. La cuadrícula de juego es una imagen de 480 píxeles de ancho por 800 píxeles de alto con un fondo transparente y una cuadrícula blanca de cuadrados de 150 píxeles de ancho ubicados en el centro. Lo importaste antes. Dibujarlo en la pantalla del teléfono no podría ser más fácil. Usted toma la textura que cargó y almacenó en el gridTexture variable y dibujarla colocándola usando la instancia previa. cuadrículaRectangle variable, pasando ambos elementos a la SpriteBatch objetos Dibujar método. Cambia tu DrawGrid Método para leer de la siguiente manera:

 privado void DrawGrid () spriteBatch.Draw (gridTexture, gridRectangle, Color.White);  

Guarde el archivo en el que está trabajando y presione F5 para compilar y ejecutar su proyecto. El emulador de Windows Phone 7 debería aparecer y mostrar su cuadrícula de Tic-Tac-Toe en un fondo negro como la siguiente imagen:

Ahora que la cuadrícula está en su lugar, dibujemos las piezas de juego. En este punto, podemos aplicar cierta lógica simple para mostrar las piezas, pero nada se mostrará hasta que agreguemos el código para manejar los toques y jugar el juego. Modifica tu DrawPieces método de la siguiente manera:

 DrawPieces vacíos privados () para (int i = 0; i < 3; i++)  for (int j = 0; j < 3; j++)  if (grid[i, j] != TicTacToePlayer.None)  Texture2D texture = grid[i, j] == TicTacToePlayer.PlayerO ? oPiece : xPiece; Rectangle position = GetGridSpace(i, j, texture.Width, texture.Height); spriteBatch.Draw(texture, position, Color.White);     

Si tiene un ojo agudo (o más probablemente, Visual Studio le muestra líneas onduladas rojas) verá que GetGridSpace Falta el método. GetGridSpace es un método conveniente que ayuda a mantener un poco de código fuera de la DrawPieces método y también será útil cuando intente manejar los toques más adelante. Agréguelo al final de su declaración de clase de la siguiente manera:

 privado Rectangle GetGridSpace (columna int, fila int, ancho int, altura int) int centerX = spriteBatch.GraphicsDevice.Viewport.Width / 2; int centerY = spriteBatch.GraphicsDevice.Viewport.Height / 2; int x = centerX + ((columna - 1) * 150) - (ancho / 2); int y = centerY + ((fila - 1) * 150) - (altura / 2); devolver nuevo rectángulo (x, y, ancho, alto);  

Ahora, veamos el resto de DrawPieces. Este método es un poco más complicado que el DrawGrid pero todavía debería ser bastante fácil de entender. Usted itera sobre cada fila y columna del campo de juego, almacenado en el cuadrícula variable, y compruebe para ver el estado de ese espacio de cuadrícula. Si el espacio de la cuadrícula contiene un jugador distinto de "Ninguno", dibuje la textura adecuada. Utiliza el operador ternario para tomar la textura correcta en función del estado del espacio de la cuadrícula y luego dibujarla utilizando el rectángulo obtenido de GetGridSpace.

El siguiente tema a tratar es dibujar el estado actual. El estado muestra de quién es el turno, quién ganó el juego o si el juego es un empate. Completa el método de la siguiente manera:

 Private void DrawStatus () Texture2D texture; if (winner! = TicTacToePlayer.None) texture = winner == TicTacToePlayer.PlayerO? oWinner: xWinner;  else if (! winnable) texture = noWinner;  else texture = current == TicTacToePlayer.PlayerO? oTurn: xTurn;  Posición del rectángulo = nuevo Rectángulo (spriteBatch.GraphicsDevice.Viewport.Width / 2 - (texture.Width / 2), 15, texture.Width, texture.Height); spriteBatch.Draw (textura, posición, Color.White);  

Este método no difiere mucho de los otros métodos de dibujo que has creado hasta ahora. Tienes una textura y una posición y necesitas dibujar la textura en la pantalla. La parte interesante de este método es determinar qué textura dibujar. Primero verifica si hay un ganador. Si hay, elige la textura ganadora correcta y dibuja eso. Luego, verifica si todos los espacios de la cuadrícula han sido ocupados y el juego ya no se puede ganar. Si ese es el caso, entonces eliges la textura de no ganador y dibujas esa. Si ninguna de esas condiciones es verdadera, entonces verifica cuál es el turno del jugador, elige la textura de giro correcta y roba esa. Si compilas y ejecutas tu proyecto en este punto (presionando F5), verás que la interfaz muestra que es el turno de O:

Finalmente, vas a crear el código que dibuja el botón de reinicio. Esto es bastante sencillo. Si hay un ganador o el juego ya no se puede ganar, dibuja la textura del botón de reinicio. Modificar el DrawResetButton Método por lo que se lee como sigue:

 private void DrawResetButton () if (winner! = TicTacToePlayer.None ||! winnable) spriteBatch.Draw (resetButton, resetButtonPosition, Color.White);  

En este punto, ha creado todo el código que se necesita para dibujar su interfaz y todos sus componentes. Ahora, solo necesita manejar la actualización de su juego en base a los toques de los jugadores.

Manejo de toques y actualización de estado

Si siguió el último tutorial en XNA, gran parte del siguiente código le resultará familiar. El manejo de los toques en la pantalla es algo que es bastante estándar y es solo dentro del código de manejo del toque que tendrá su lógica de juego. Para empezar, pongamos el código básico de manejo táctil en el Actualizar método. Encontrar Actualizar en tus Juego1 Clase y modifíquelo para que lea como sigue:

 anular protegido anular la actualización (GameTime gameTime) if (GamePad.GetState (PlayerIndex.One) .Buttons.Back == ButtonState.Pressed) this.Exit ();  TouchCollection touches = TouchPanel.GetState (); si (! toca && toca.Contar> 0) toca = verdadero; TouchLocation touch = touches.First (); HandleBoardTouch (toque); HandleResetTouch (toque);  else if (toca.Cuento == 0) tocando = falso;  base.Update (gameTime);  

Hay algunas cosas en este método a las que prestar atención. Primero, notarás una nueva. conmovedor Variable que no existe. Esta variable almacena si el jugador estaba o no tocando el tablero en la tabla anterior. Actualizar llama y evita que un dedo persistente juegue varias veces sin soltarlo de la pantalla. Añadir conmovedor como una variable de instancia en la parte superior de su declaración de clase.

 bool tocando; 

También notará que está haciendo dos llamadas de método dentro del Actualizar Método a métodos que no existen todavía. Agregue esos métodos a su declaración de clase directamente debajo del Actualizar método:

 privado void HandleBoardTouch (toque TouchLocation)  private void HandleResetTouch (toque TouchLocation)  

Ahora, caminando por el Actualizar Método que ve que comprueba los toques actuales en la pantalla. Si hay toques y el jugador no tocó la pantalla anteriormente, entonces usted toma el primer toque y lo pasa a los métodos que manejan los toques y reinician los toques. Si el jugador no está tocando la pantalla y estaba anteriormente, entonces actualiza el conmovedor variable a falso.

En este punto, vamos a completar la HandleBoardTouch y HandleResetTouch metodos Estos corresponden a los pasos de flujo de trabajo 5 y 6, respectivamente..

Tablero de manipulación de toques

Cuando un usuario toca la pantalla, el juego tiene que hacer algunas cosas:

  • Compruebe si el toque está dentro del área de juego
  • Si está en el área de juego, verifique si el lugar que se toca está ocupado
  • Si el spot es no ocupado, luego coloca una pieza allí y comprueba si el jugador actual ha ganado
  • Si la pieza jugada fue la ganadora, actualiza el estado del juego como tal. Si la pieza jugada ocupó el último lugar disponible, marca el juego como ininteligible
  • Por último, intercambia el jugador actual.

Actualizar el HandleBoardTouch para leer como sigue, manejando todos los pasos anteriores:

 privado void HandleBoardTouch (TouchLocation touch) if (winner == TicTacToePlayer.None) for (int i = 0; i < 3; i++)  for (int j = 0; j < 3; j++)  Rectangle box = GetGridSpace(i, j, 150, 150); if (grid[i, j] == TicTacToePlayer.None && box.Contains((int)touch.Position.X, (int)touch.Position.Y))  grid[i, j] = current; CheckForWin(current); CheckForWinnable(); current = current == TicTacToePlayer.PlayerO ? TicTacToePlayer.PlayerX : TicTacToePlayer.PlayerO;      

Como puede ver, este método sigue el esquema básico anterior. Si no hay un ganador, itera sobre cada espacio de la cuadrícula, comprueba si el toque está en ese espacio, comprueba si el espacio está abierto y luego coloca una pieza allí. Verificar que haya un ganador y asegurarse de que el juego aún se puede ganar se manejan con otros métodos. Apaguemos esos métodos ahora. Debajo de la HandleBoardTouch Método, agregue el siguiente código:

 vacío privado CheckForWin (jugador de TicTacToePlayer)  privado vacío CheckForWinnable ()  

Por ahora, deja estos métodos en blanco, compila y ejecuta tu juego. Intente tocar el tablero haciendo clic en el emulador y observe cómo cambia el mensaje de estado y las piezas que se reproducen. Estás bien en tu camino hacia un juego completo ahora!

Condiciones de ganar

En este punto llegas a la verdadera carne del juego, la lógica ganadora. Como se mencionó anteriormente, un estado ganador se produce cuando las piezas de un jugador ocupan una de las filas, una de las columnas o una de las dos diagonales. El juego no se puede ganar cuando no hay un ganador declarado y no quedan lugares desocupados. Para este juego, estamos utilizando una matriz multidimensional para almacenar el estado de la cuadrícula y fuera de la caja C # no proporciona métodos para verificar filas, columnas o diagonales. Afortunadamente, el lenguaje admite una característica impresionante llamada métodos de extensión que usarás aquí para hacer que tu código sea un poco más limpio..

Creando los Ayudantes

Para crear los métodos de extensión, primero debe crear una nueva clase. Haga clic en el nombre de su proyecto en el Explorador de soluciones y haga clic en "Agregar> Clase ...". Nombre su clase MultiDimensionalArrayExtensions y haga clic en "Agregar". Cuando su nuevo archivo se abra para editarlo, modifíquelo para que su declaración de clase tenga el siguiente aspecto:

 clase estática pública MultiDimensionalArrayExtensions  

Verás que has añadido los modificadores. público y estático a la declaración de clase. Esto es necesario para crear métodos de extensión. Ahora, vamos a crear un par de métodos que necesitaremos, cada uno de los cuales devuelve un Enumerable para facilitar la consulta:

  • Fila - Devuelve todos los artículos en una fila particular
  • Columna - Devuelve todos los artículos en una columna particular
  • Diagonal - Devuelve todos los elementos en una diagonal
  • Todo: devuelve todos los elementos de la matriz multidimensional.

Modifique su clase de nuevo, agregando los métodos siguientes:

 clase estática pública MultiDimensionalArrayExtensions public static IEnumerable Fila(este T [,] array, int fila) var columnLower = array.GetLowerBound (1); var columnUpper = array.GetUpperBound (1); para (int i = columnLower; i <= columnUpper; i++)  yield return array[row, i];   public static IEnumerable Columna(este T [,] array, int columna) var rowLower = array.GetLowerBound (0); var rowUpper = array.GetUpperBound (0); para (int i = rowLower; i <= rowUpper; i++)  yield return array[i, column];   public static IEnumerable Diagonal(este T [,] array, dirección de DiagonalDirection) var rowLower = array.GetLowerBound (0); var rowUpper = array.GetUpperBound (0); var columnLower = array.GetLowerBound (1); var columnUpper = array.GetUpperBound (1); para (int row = rowLower, column = columnLower; row <= rowUpper && column <= columnUpper; row++, column++)  int realColumn = column; if (direction == DiagonalDirection.DownLeft) realColumn = columnUpper - columnLower - column; yield return array[row, realColumn];   public enum DiagonalDirection  DownRight, DownLeft  public static IEnumerable Todos(esta matriz T [,]) var rowLower = array.GetLowerBound (0); var rowUpper = array.GetUpperBound (0); var columnLower = array.GetLowerBound (1); var columnUpper = array.GetUpperBound (1); para (int row = rowLower; row <= rowUpper; row++)  for (int column = columnLower; column <= columnUpper; column++)  yield return array[row, column];     

Se puede ver que no hay mucho de estos métodos. Para cada uno de ellos, una parte particular de la matriz multidimensional se itera y esa parte de la matriz se devuelve como parte de una matriz. Enumerable. La única parte realmente difícil puede ser el uso de rendimiento palabra clave. Una explicación del comportamiento de esa palabra clave está fuera del alcance de este artículo, pero la referencia de C # en MSDN para la palabra clave de rendimiento puede ser útil si desea obtener más información. Como nota al margen, gran parte del trabajo sobre estos métodos de extensión se toma de la contribución del usuario en StackOverflow que puede encontrar aquí.

Implementando la lógica de ganar

Ahora que se implementan los métodos de extensión necesarios, debería ser bastante fácil implementar la lógica win. Volvamos a la CheckForWin Método e implementarlo. Actualice el método para leer de la siguiente manera:

 vacío privado CheckForWin (jugador de TicTacToePlayer) Func checkWinner = b => b == jugador; if (grid.Row (0) .All (checkWinner) || grid.Row (1) .All (checkWinner) || grid.Row (2) .All (checkWinner) || grid.Column (0) .All ( checkWinner) || grid.Column (1) .All (checkWinner) || grid.Column (2) .All (checkWinner) || grid.Diagonal (MultiDimensionalArrayExtensions.DiagonalDirection.Downgight). All (checkWinner) || grid (MultiDimensionalArrayExtensions.DiagonalDirection.DownLeft) .All (checkWinner)) winner = player;  

Dado lo que ya sabes al crear los métodos de extensión, esto debería ser bastante simple de descifrar. Primero creas un "Func": http: //msdn.microsoft.com/en-us/library/bb549151.aspx objeto que actúa como delegado y le permite usar una declaración lambda (que b => b == jugador parte) para consultar una Enumerable (como los devueltos por el método de extensión) y devuelve un bool. A continuación, aplique esto Func objeto a través de cada fila, columna y diagonal utilizando el Todo enumerable método. Si alguno de esos casos es cierto, entonces asigna el ganador variable de instancia a la jugador parámetro. Si ninguno de esos casos es verdad, entonces no pasa nada..

Ahora, modifica tu CheckForWinnable método:

 vacío privado CheckForWinnable () if (winner == TicTacToePlayer.None) Func checkNone = b => b == TicTacToePlayer.None; if (! grid.All (). Any (checkNone)) winnable = false;  

Este método es muy similar a CheckForWin. Primero, verifica si el juego tiene un ganador. Si no lo hace, creas un Func objeto que comprobará si un elemento es igual a la TicTacToePlayer Ninguna. A continuación, aplique esto Func contra todos los espacios en la cuadrícula, verificando si alguno de los espacios está desocupado. Si no hay ninguno, el juego ya no se puede ganar y alternas la variable de instancia. ganable.

Terminando

En este punto tu juego está listo para empezar. Puede compilar y ejecutar su proyecto presionando F5 y comenzar a jugar (ya sea solo o con un compañero). Tome turnos para colocar piezas en el tablero, observe cómo cambia el mensaje de estado y vea qué sucede cuando gana. Una vez que gane o empate, haga clic en el botón de reinicio y vea cómo el juego vuelve a su estado original.

En este punto, hay una variedad de cosas diferentes que podrías hacer. Podría implementar un conteo ganador que muestre cuántas veces ha ganado cada jugador. Puede cambiar la forma en que se muestran las piezas o agregar una animación genial cuando se declara un ganador. Puedes usar el tema del juego para hacerlo un poco más interesante, tal vez enfrentando a la Alianza Rebelde contra el Imperio Galáctico.?

En este punto, todo depende de ti para expandir y desarrollar lo que quieras. Espero que hayan disfrutado siguiendo este tutorial tanto como yo disfruté escribiéndolo y espero escuchar sus comentarios..