Utilice MFC para escribir juegos en C, como Square, Gluttony, etc. No se limite a proporcionar algunos códigos para los pasos detallados. Si no los comprende, no es necesario que los lea. qq:714715223
El área de actividad de la serpiente se compone de muchos cuadrados pequeños. Cuando estos pequeños cuadrados aparecen de color gris, representan el cuerpo de la serpiente. Suponga que toda el área consta de m × n cuadrados y que las coordenadas del cuadrado de la esquina superior izquierda son (0, 0). Una serpiente se compone de múltiples cuadrados adyacentes. Las coordenadas de estos cuadrados se almacenan en una matriz en orden desde la cabeza de la serpiente hasta la cola de la serpiente, lo que representa el cuerpo de la serpiente. Cuando la serpiente "mueve" un cuadrado dentro del área de juego, la operación de matriz correspondiente debe ser insertar las coordenadas de la nueva posición en la cabeza de la matriz y eliminar el último elemento de la matriz. Estas tareas se pueden realizar utilizando una matriz general, pero cuando la operación de inserción requiere mover elementos en la matriz misma, también puede usar CArray para completar estas tareas. Las funciones miembro de CArray proporcionan las operaciones requeridas, lo cual es más simple en operación.
4. Pasos de la solución
(1) Crear un nuevo proyecto Snake En el primer paso del asistente MFC, seleccione un solo documento y haga clic en Finalizar para finalizar.
(2) Seleccione la ventana ResourceView, abra el editor de menú, agregue un menú emergente llamado "Juego" al menú superior y agregue un submenú llamado "Inicio" al menú. ID_GAME_START, como se muestra en la Figura 1.
Figura 1: Diseño del menú
(3) En ClassWizard, agregue una función de procesamiento de mensajes al menú que acaba de editar. Abra ClassWizard y vea la página de asignación de mensajes. Seleccione CSnakeView en el nombre de la clase, seleccione ID_GAME_START en el ID del objeto, seleccione COMMAND en el mensaje y agregue la función de procesamiento de mensajes.
(4) Agregue la función de procesamiento de mensajes del teclado en ClassWizard. Abra ClassWizard y seleccione la página Asignación de mensajes. Seleccione CSnakeView para Nombre de clase, CSnakeView para ID de objeto y WM_KeyDown para Mensaje para agregar la función de controlador de mensajes.
(5) Agregue una función de procesamiento para el mensaje del temporizador en ClassWizard. Abra ClassWizard y seleccione la página Asignación de mensajes. Seleccione CSnakeView para Nombre de clase, CSnakeView para ID de objeto y WM_Timer para Mensaje para agregar la función de controlador de mensajes.
(6) Edite el código generado y complete el programa.
4. Lista de programas fuente
(1) Seleccione la ventana ClassView, haga doble clic en la clase CSnakeView y agregue las siguientes variables miembro.
Y agregue el archivo de encabezado:
#include lt;Afxtempl.hgt;
class CSnakeView: public CView
{
// Esto omite algunas líneas de código generado por el sistema
private.CSnakeView.Afxtempl.html:
void ReDisplay(CPoint pPoint);
void IniGame() ;
void IniAim();
int m_nLeft, m_nTop, m_nWidth, m_nHeight, m_nSize // Coordenadas iniciales, ancho/alto (número de celdas), tamaño de cada celda <; /p>
int m_nDirect; // Dirección actual
// 1-derecha, 2-izquierda, 3-abajo, 4-arriba
CPoint m_pAim; coordenadas de destino
CArray lt; CPoint, CPoint gt; // Cuerpo de serpiente
int m_nGameStatus // Estado del juego: 0 - no iniciado, 1 - iniciado p>
int m_nCount; // Número de objetivos consumidos
int m_nTime, m_nTime1; // Tiempo empleado
};
( 2) Agregue lo siguiente líneas en el archivo CSnakeView.Cpp y agregue 3 funciones miembro en él. En el archivo Cpp, agregue 3 funciones miembro IniAim, IniGame y ReDiaplay:
// Esta función genera aleatoriamente un objetivo para que la serpiente se lo coma. Si el objetivo coincide con el cuerpo de la serpiente, uno nuevo. se generará el objetivo
void CSnakeView::IniAim()
{
int uX, uY // posición de destino
mientras (1 )
{
uX = rand ( ) m_nHeight
uY = rand ( ) m_nWidth
int uTag = 0; / / 0 - no coincide con el cuerpo de la serpiente.
1- superposición
for (int i=0; i lt; = m_aBody.GetUpperBound ( ); i )
{
CPoint uPoint = m_aBody.GetAt (i);
if (uPoint. x == uX ||) uPoint.y == uY ) // El objetivo coincide con el cuerpo de la serpiente
{
uTag = 1;
romper
}
}
si (uTag == 0)
break;
}
m_pAim = CPoint (uX, uY); // El objetivo generado se almacena en una variable miembro
} p>
//Esta función inicializa el juego y define el estado inicial del juego
void CSnakeView::IniGame()
{
/ / Área de juego
p>m_ nDirect = 1;
m_nCount = 0;
//Inicializa el cuerpo de la serpiente
m_aBody. RemoveAll ( );
m_aBody.Add (CPoint (2, 4));
//Restablecer el temporizador a cero
m_nTime = 0;
m_nTime1 = 0;
//Inicializa el generador de números aleatorios
srand ((unsigned) time (NULL)
// Generar). un objetivo
IniAim ( );
}
// Actualiza un pequeño cuadrado en pPoint en el área de juego
void CSnakeView: :ReDisplay(CPoint pPoint) p>
{
InvalidateRect (CRect (m_nLeft pPoint.y * m_nSize, m_nTop pPoint. x * m_nSize,
m_nLeft ( pPoint. y 1) * m_nSize, m_nTop ( pPoint. x 1) * m_nSize) );
}
(3) Modifique el constructor de CSnakeView para completar la inicialización del juego.
CSnakeView::CSnakeView()
{
IniGame();
}
(4) Agregue código en OnDraw para mostrar la interfaz del juego.
void CSnakeView::OnDraw(CDC* pDC)
{
CSnakeDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc );
// TODO: agregue código de dibujo de datos local aquí
// Dibuja el área del juego
pDC -gt; SelectStockObject (WHITE_BRUSH); p>
pDC -gt; Rectángulo (CRect (m_nLeft - 1, m_nTop - 1, m_nLeft m_nWidth * m_nSize 1,
m_nTop m_nHeight * m_nSize 1)
/ / Muestra el tiempo transcurrido actual
CString uStr;
uStr.nTime);
pDC -gt; TextOut (m_nLeft m_nWidth * m_nSize 30, 40 , uStr
//Muestra la puntuación actual
uStr.Format ("Puntuación actual: d", m_nCount
pDC -gt; m_nWidth * m_nSize 30, 140, uStr);
//Mostrar destino
pDC -gt; SelectStockObject (LTGRAY_BRUSH);
pDC -gt.Rectangle ( CRect (m_nLeft m_pAim. y * m_nSize, m_nTop m_pAim. x * m_nSize,
m_nLeft (m_pAim. y 1) * m_nSize, m_nTop (m_pAim. p>/gt.)
// Dibujar serpiente
for (int i=0; ilt; = m_aBody.GetUpperBound (); i )
{
CPoint uPoint = m_aBody.GetAt (i);
pDC -gt.rectangle (CRect (m_nLeft uPoint. y * m_nSize, m_nTop uPoint. x * m_nSize,
m_nLeft (uPoint. y 1) * m_nSize, m_nTop (uPoint. x 1) * m_nSize);
}
}
(5) Agrega código de función de mapeo de información para el elemento de inicio en el menú del juego. .
void CSnakeView::OnGameStart()
{
//Inicia el juego e inicia el cronómetro
IniGame ( ); /p>
p>
m_nGameStatus = 1;
SetTimer (1, 100, NULL) )
Invalidar ( );
}
(6) Agregue el código del controlador de mensajes de teclas del teclado.
//Establece valores que representan diferentes direcciones según las teclas de dirección presionadas
void CSnakeView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
cambiar (nChar)
{<
caso 38:
m_nDirect = 4; descanso ;
caso 40:
m_nDirect = 3;
descanso;
caso 37:
m_nDirect = 2;
rotura;
caso 39:
m_nDirect = 1;
CView::OnKeyDown(nChar, nRepCnt, nFlags);
}
(7) Agregue código a la función de procesamiento de mensajes del temporizador agregando código.
void CSnakeView::OnTimer(UINT nIDEvent)
{
m_nTime1; // temporizador
if (m_nTime1 == 10 ) // Alcanzado 1 segundo
{
m_nTime;
m_nTime1 = 0;
Invalidar ( );
}
CPoint uPoint = m_aBody.GetAt (0); // La posición de la cabeza de serpiente
int uTag = 0 // Si falló
>switch ( m_ nDirect) // Luego determina si la serpiente ha cruzado el límite
{
caso 1: // right
uPoint.y gt; = m_nWidth)
uTag = 1;
break;
caso 2: // izquierda
uPoint.y lt;
uTag = 1 ;
romper;
caso 3: // abajo
uPoint x ;
if ( uPoint. . x gt; = m_nHeight )
uTag = 1;
descanso
caso 4:
uPoint.
Si (uPoint. x lt; 0)
uTag = 1;
ruptura
}
if (uTag == 0) // Determina si la serpiente se ha tocado
{
for (int i=0; i lt;= m_aBody.GetUpperBound(); i )
{
CPoint uPoint1 = m_aBody.GetAt (i);
if (uPoint1. x == uPoint. x amp; amp; uPoint1.y == uPoint.InsertAt ( 0, uPoint); // La posición de la nueva cabeza de serpiente
ReDisplay (uPoint);
if (uPoint. x == m_ pAim. x amp; amp; uPoint. y == m_pAim.y) // Toque el objetivo
{
m_nCount;
IniAim ();
Invalidar ();
}
else
{
CPoint uPoint1 = m_aBody.GetAt (m_aBody.GetUpperBound ( ) )
m_aBody .GetUpperBound ( )RemoveAt (m_aBody.GetUpperBound ( )
ReDisplay ( uPoint1);
else // Juego terminado
{
KillTimer(1);
AfxMessageBox("Fai
l!");
}
CView::OnTimer(nIDEvent);
}