Juego de ajedrez en Visual C++

Dibujar el tablero

Para dibujar el tablero de ajedrez dentro de la vista creada tenemos que tener en cuenta los parámetros siguientes:

  1. Etiquetas de filas y columnas.
  2. Margen entre el borde de la ventana y la cuadrícula del tablero.
  3. Tamaño de la celda del tablero.
Imagen 6: Parámetros para dibujar el tablero de ajedrez

Para dibujar el tablero necesitaremos definir 3 valores fijos que no cambiarán y nos servirán para dibujar el tablero cada vez que lo necesitemos.

#define MARGEN    30
#define TAMCELDA  60
#define CELDAS     8

El siguiente paso es crear la función que dibujará el tablero, para ello debemos abrir la vista de clases, hacer clic derecho sobre la clase y elegir “Agregar->Función” luego aparecerá un dialogo como el de la imagen 7. No se deben olvidar de agregar un parámetro del tipo CDC* para que podamos dibujar los elementos.

Imagen 7: Agregar Función DibujarTablero

La función DibujarTablero

A continuación una descripción del algoritmo utilizado para dibujar el trablero de ajedréz.

  1. Crea inicialmente los objetos necesarios para darle color al fondo y a las líneas del tablero de ajedrez (CPen, CBrush)
  2. Luego dibuja celda por celda (for anidado de 8 iteraciones cada uno)
    1. Al inicio de la iteración se calcula las dimensiones de la celda en base a los valores de i y j y los parámetros definidos inicialmente (margen y tamaño de celda) estos valores calculados son almacenados en la variable rcCelda de tipo RECT.
    2. Para dibujar una celda oscura o blanca se verifica si es par o no, de esa forma se intercalan los colores, según estos valores se utiliza el Brush indicado junto a la función CDC::Rectangle.
    3. Se aprovecha el valor de rcCelda para calcular la posición de las etiquetas que están contenidas en la variable m_vEtiquetas de tipo std::vector.
void CAjedrezView::DibujarTablero(CDC* pDC)
{
    //Definición de colores y fondos
    RECT rcCelda;
    CBrush brNegro,brSeleccion;
    brNegro.CreateSolidBrush(0xf36d4d);
    brSeleccion.CreateSolidBrush(RGB(255,240,108));
 
    CPen penAzulMarino,penAmarillo;
    penAzulMarino.CreatePen(PS_SOLID,3,0x00640000);
    penAmarillo.CreatePen(PS_SOLID,4,0x0000EEEE);
 
    CPen *penAnterior = pDC->SelectObject(&penAzulMarino);
    pDC->SetBkMode(TRANSPARENT);
 
    for(int i = 0 ; i < CELDAS ; i++)
    {
        for(int j = 0 ; j < CELDAS ; j++)
        {
            rcCelda.left  = j*TAMCELDA + MARGEN;
            rcCelda.top   = i*TAMCELDA + MARGEN;  
            rcCelda.right = rcCelda.left + TAMCELDA;
            rcCelda.bottom = rcCelda.top + TAMCELDA;
 
            if( i%2 == 0 )
            {
                if(j%2 != 0)
                {
                        CBrush *pFondoAnterior = pDC->SelectObject(&brNegro);
                        pDC->Rectangle(&rcCelda);
                        pDC->SelectObject(pFondoAnterior);
                }
                else
                {
                    pDC->Rectangle(&rcCelda);
                }
            }
            else
            {
                if(j%2 == 0)
                {
                        CBrush *pFondoAnterior = pDC->SelectObject(&brNegro);
                        pDC->Rectangle(&rcCelda);
                        pDC->SelectObject(pFondoAnterior);
                }
                else
                {
                    pDC->Rectangle(&rcCelda);
                }
            }
           
            //Dibujando las etiquetas
            if(j == 0 || j == 7)
            {
                rcCelda.left  = j==0?MARGEN-15:rcCelda.right;
                rcCelda.right = j==0?MARGEN:rcCelda.right + 15;
                pDC->DrawText(m_vEtiquetas[i],
                    &rcCelda,
                    DT_CENTER|DT_VCENTER|DT_SINGLELINE);
               
                //Restaurando valores para que no
                //afecte el pintado de las etiquetas verticales
                rcCelda.left  = j*TAMCELDA + MARGEN;
                rcCelda.right = rcCelda.left + TAMCELDA;
            }
            if(i == 0 || i == 7)
            {
                rcCelda.top    = i==0?MARGEN-20:rcCelda.bottom;
                rcCelda.bottom = i==0?MARGEN:rcCelda.bottom + 20;
                pDC->DrawText(m_vEtiquetas[j+8],
                    &rcCelda,
                    DT_CENTER|DT_VCENTER|DT_SINGLELINE);
            }
 
        }
    }
    pDC->SelectObject(penAnterior);
}

Este código debe ser invocado desde la función OnDraw, la función OnDraw ya esta establecida y recibe como parámetro también un objeto CDC, el mismo debe pasar como parámetro de la función DibujarTablero.

#include "memdc.h"
 
...
 
void CAjedrezView::OnDraw(CDC* pDC)
{
    CAjedrezDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    if (!pDoc)
        return;
 
    CMemDC memdc(pDC);
    DibujarTablero(&memdc);
}

La clase CMemDC es una herramienta para crear un mapa de bits en segundo plano para ir dibujando en él y al final pintar el mapa de bits sobre la ventana para así evitar el parpadeo que se produce al pintar objeto por objeto, esta técnica se le conoce como Double Buffering.

Pueden descargar el archivo memdc.h de codeproject.com, esta clase fue escrita por Keith Rule.

Para que la técnica de double buffering quede completa debemos agregar la función asociada al evento WM_ERASEBKGND que decide si se va a eliminar el fondo antes de pintar nuevamente el tablero.

El código de la función generada se debe ver como sigue:

BOOL CAjedrezView::OnEraseBkgnd(CDC* pDC)
{
    return FALSE;
}

Luego de terminar de escribir la función pueden compilar y verán un resultado como el de la imagen 8.

Imagen 8: Tablero Dibujado por la Función

Descargas

File Description File size
zip Ajedrez Código fuente
85 KB
3 Respuestas a “Juego de ajedrez en Visual C++”
  1. Luis De Anda 8 Ene 2018
    1 Reply

    Hola amigo como estas, oye estoy interesado en una plataforma de juegos, ajedrez, damas inglesas, bagkammon y dominó, me gustaría platicar contigo haber si estas interesado, que tengas un excelente día

Dejar una Respuesta