Juego de Ajedrez (I). Introducción a la Programación Orientada a Objetos
El código completo tanto en C# como en Visual Basic .NET está disponible en:
Códigos de muestra - Ejemplos MSDN. Juego de Ajedrez
Tras hacer un resumen de lo que iremos viendo a lo largo de los diferentes artículos, vamos a meternos en harina creando el proyecto y la estructura básica de clases que encapsularán la funcionalidad de nuestro juego de ajedrez.
En primer lugar vamos a crear un nuevo proyecto Windows Forms llamado ChessGame:
En este primer artículo vamos a crear la estructura de clases que implementarán la funcionalidad de los diferentes elementos del juego, así que por ahora nos limitaremos a renombrar el formulario por defecto Form1 que crea Visual Studio por ChessGameForm.
Para definir las diferentes clases crearé una nueva carpeta Model en el proyecto y, dentro de ésta, tres archivos de código: Chess.cs/Chess.vb (que contendrá la funcionalidad de la partida), Chessboard.cs/Chessboard.vb (que contendrá la funcionalidad del tablero) y Pieces.cs/Pieces.vb (que contendrá las clases que encapsulan la funcionalidad de las diferentes piezas).
En primer lugar crearé dos enumeraciones en el archivo Chess.cs/Chess.vb: la enumeración PlayerColor define los diferentes colores de los jugadores (blanco o negro) y la enumeración GameState define los diferentes estados en que puede encontrarse la aplicación.
enum PlayerColor { White, Black } enum GameState { PendingForWhiteMove, PendingForBlackMove, WhitePlayerMoving, BlackPlayerMoving, WhitePlayerWin, BlackPlayerWin }
Enum PlayerColor White Black End Enum Enum GameState PendingForWhiteMove PendingForBlackMove WhitePlayerMoving BlackPlayerMoving WhitePlayerWin BlackPlayerWin End Enum
En el archivo Pieces.cs/Pieces.vb crearé una clase abstracta ChessPiece que servirá como clase base para las diferentes piezas del juego.
Una clase abstracta es una clase a partir de la cual no pueden crearse instancias. Su propósito es crear una definición común que puedan compartir las clases derivadas.
En este caso definiremos en la clase ChessPiece la funcionalidad que deben compartir todas las piezas del juego de ajedrez, de forma que este comportamiento común esté definido en un único lugar. Para definir el comportamiento particular de una pieza crearemos una clase derivada de ChessPiece que heredará todo el comportamiento común y en el que definiremos ese comportamiento personalizado.
En esta clase base voy a definir dos propiedades:
- Color: de tipo PlayerColor y que definirá el color de la pieza
- BoardSquare: de tipo Square (que crearemos a continuación) y que devolverá la celda en la que se encuentra posicionada la pieza
Un método:
- GetDestinationSquares: que devolverá una enumeración de las celdas a las que se puede mover la pieza. Como estas celdas dependen del tipo de pieza de que se trata no implementaré ninguna funcionalidad en la clase Piece si no que la funcionalidad del método deberá definirse en cada una de las clases derivadas. Es lo que se denomina un método abstracto y debe marcarse con la palabra reservada abstract (en C#) o MustOverride (en VB)
Y un constructor que recibirá como argumento el color de la pieza.
abstract class ChessPiece { public ChessPiece(PlayerColor color) { Color = color; } public PlayerColor Color { get; set; } public Square BoardSquare { get; internal set; } public abstract IEnumerable<Square> GetDestinationSquares(); }
MustInherit Class ChessPiece Public Sub New(pieceColor As PlayerColor) Color = pieceColor End Sub Property Color As PlayerColor Property BoardSquare As Square Public MustOverride Function GetDestinationSquares() As IEnumerable(Of Square) End Class
En el archivo Chessboard.cs/Chessboard.vb definiré las clases Square, que definirá una celda del tablero, y Chessboard, que definirá el tablero.
En la clase Square definiré cuatro propiedades:
- Board: que mantendrá una referencia al tablero al que pertenece la celda
- Row y Col: que devolverán la fila y columna a las que corresponde la celda
- Piece: que contendrá una referencia a la pieza que se encuentra en la celda
Y un constructor que recibirá el tablero al que pertenece la celda y su número de fila y columna.
class Square { public Square(Chessboard board, int row, int column) { Board = board; Row = row; Column = column; } public Chessboard Board { get; set; } public int Row { get; set; } public int Column { get; set; } public ChessPiece Piece { get; set; } }
Class Square Public Sub New(squareBoard As Chessboard, squareRow As Integer, squareColumn As Integer) Board = squareBoard Row = squareRow Column = squareColumn End Sub Property Board As Chessboard Property Row As Integer Property Column As Integer Property Piece As ChessPiece End Class
La clase Chessboard que define el tablero será básicamente una colección de celdas por lo que heredará del objeto List<Square>.
Además definirá una propiedad:
- PlayerOnTop: que especificará el color del jugador cuyas piezas se colocarán en la parte superior del tablero
Un método:
- GetSquare: que devolverá la celda correspondiente a la fila y columna pasadas como argumentos
Y un constructor en el que inicializaré el tablero creando las 64 celdas y estableciendo por defecto al jugador blanco como jugador para la parte superior del tablero.
class Chessboard : List<Square> { public Chessboard() { for (int row = 0; row < 8; row++) { for (int column = 0; column < 8; column++) Add(new Square(this, row, column)); } PlayerOnTop = PlayerColor.White; } public PlayerColor PlayerOnTop { get; set; } public Square GetSquare(int row, int column) { return this.FirstOrDefault(s => s.Row == row && s.Column == column); } }
Class Chessboard Inherits List(Of Square) Public Sub New() For row = 0 To 7 For column = 0 To 7 Add(New Square(Me, row, column)) Next Next PlayerOnTop = PlayerColor.White End Sub Property PlayerOnTop As PlayerColor Public Function GetSquare(row As Integer, column As Integer) As Square Return Me.FirstOrDefault(Function(s) s.Row = row AndAlso s.Column = column) End Function End Class
Por último, en el archivo Chess.cs/Chess.vb crearé la clase Game que mantendrá el estado de la partida. Por ahora únicamente voy a crear dos propiedades:
- Board: que permitirá acceder al tablero de la partida
- State: que contendrá el estado actual de la partida
Y un constructor que creará el tablero de juego.
class Game { public Game() { Board = new Chessboard(); } public Chessboard Board { get; private set; } public GameState State { get; set; } }
Class Game Public Sub New() _board = New Chessboard() End Sub Private _board As Chessboard Public Property Board() As Chessboard Get Return _board End Get Private Set(ByVal value As Chessboard) _board = value End Set End Property Private _state As GameState Public Property State() As GameState Get Return _state End Get Private Set(ByVal value As GameState) _state = value End Set End Property End Class
Una vez definida la estructura básica, en las próximas entradas continuaré ampliando la funcionalidad de cada una de ellas.
Artículo siguiente:
Juego de Ajedrez (III). Definiendo las piezas
Hola, Asier, disculpa que te moleste, antes que nada, Feliz Navidad.......Quiero consultarte, si sabes y es posible sobre lo siguiente:
ResponderEliminarCuando selecciono una fila de GridView, los datos de esas filas pasan a otro webForm, a unos textBox.....Todos se llenan, y hay 4 de Ellos Enabled=true..........Lo que sucede es que uno de ellos no se llena, y me da un Error, porque luego de operar los que si se pueden se guardan en Base de Datos.
Que sucede que no se llena ese TextBox?.......
Si sabes algo, podrias ayudarme??
Abrazo nos vemos...
Hola Guillermo,
Eliminares difícil saber lo que sucede sin ver el código.
Para estos casos lo mejor es que plantees el problema en los foros de msdn:
Msdn foros
De esta forma tanto yo como los compañeros que colaboran habitualmente en los foros podremos ayudarte mejor.
Un saludo y feliz año.