Red de conocimiento informático - Consumibles informáticos - (100 puntos) Planificación del proceso completo del juego de Tetris (suma 50 puntos si es posible, gracias)

(100 puntos) Planificación del proceso completo del juego de Tetris (suma 50 puntos si es posible, gracias)

El código en CSDN descargado de Internet ^^^

Compartir.........

Usé TC para depurar con éxito

Porque hay gráficos.hgt; en el archivo de encabezado, por lo que no se puede ejecutar en VC

#include stdio.hgt;

#include stdlib.hgt;

#include lt; bios.hgt; /*Aquí necesitas leer el tiempo de ejecución del sistema como un temporizador*/

#include lt;graphics.hgt; los gráficos simples de TC2 me hicieron dejar de usar */

#include lt; conio.hgt /*win32 openGL para explicar.*/

#define MAX_X 14 /* Máximo visible X*/

#define MAX_Y 21 /*Máximo visible Y*/

/*Hemos definido los máximos visibles X e Y, luego aún quedan

visible De hecho, las dos filas en los lados izquierdo y derecho y la parte inferior del mapa (cuadro grande) están llenas de 1, lo que simplifica enormemente el juicio de fuera de límites. De hecho, no hay. dicho código en este ejemplo

porque hay un círculo de 1 al lado para evitar que el cuadro pequeño vaya más allá del rango de control del cuadro más grande

*/

#define MAX_C 7 /*El tipo más grande, no se necesita explicación para esto*/

#define KEY_UP 'w' /*Define arriba, abajo, izquierda y botones derecho*/

#define KEY_DOWN 's'

#define KEY_LEFT 'a'

#define KEY_RIGHT 'd'

#define KEY_ESC 27 /*Salir*/

typedef int BOOL;

#define FALSE 0

#define TRUE 1 /*No hay ninguno en estos TC...defínelo usted mismo :)*/

/*Estructura de reloj*/

typedef struct { /*Estructura de reloj*/

BOOL habilitado; /*Si el reloj está habilitado*/

unsigned int intervel; /*Intervalo de tiempo*/

unsigned int lasttime /*Esta es una variable interna*/

} Temporizador;

/*

*Ahora hemos entrado en la etapa preliminar de programación

*Al principio escribiré todas las funciones. prototipos y sus funciones

*La función principal es Al final del programa, puedes ver la estructura organizativa de todo el juego aquí

*Es muy bueno Solo tiene un. pocas docenas de líneas y es muy fácil de entender. Por supuesto, echemos un vistazo primero al prototipo de función

*y la explicación

*/

/*. **************************** ************************* *******\

* Prototipo y descripción de la función*

\*************************************************** *** *****/

/*Las siguientes tres funciones pueden hacer referencia a la estructura del temporizador Después de la declaración de la función*/

int GetTickCount() /*Return. a la computadora o sistema operativo El tiempo transcurrido durante la operación*/

/*En el entorno win32, se incluye en windows.h y el tiempo devuelto es de 4 bytes*/

/*En el entorno DOS (este código), debe escribirlo usted mismo, utilizando el contenido de BIOS.h*/

int setTimer(Timer *t, unsigned int intv, BOOL en);

/*Configure el reloj t, los parámetros son respectivamente Es el puntero del reloj, el intervalo de tiempo, si está activo*/

/*Intervalo de tiempo, milisegundos en win32, 1/ 18 segundos en DOS (un poco bajo)*/

BOOL testTimer (Timer *t /*Prueba si el reloj t alcanza la hora programada*/

/*Como el siguiente código:*/

/*

setTimer(amp;t, 1, 1); Establece el intervalo de 1 unidad

while(1) {

if(testTimer(amp;t)) printf("Active! \n");

}

Active se imprimirá en la pantalla con regularidad ( 1 unidad)!

En términos generales, testTimer debe colocarse en un bucle Ejecutar repetidamente, devolver 1 cuando se activa

*/

void render(void); /*La única función de dibujo*/

/*Tenga en cuenta que esta función vuelve a dibujar todo el mapa, dibuja el cuadro pequeño en la posición apropiada de acuerdo con la matriz de puntos en el mapa y de acuerdo con

coordenada central del cuadro pequeño en el mapa*/

/*Gráficos de DOS, por supuesto, es muy bajo, pero el dibujo en pantalla completa todavía es transitable aquí

Yo uso doble almacenamiento en búfer para intercambiar dibujos, lo que se siente mejor*/

void initMap(void) /*Inicializar el mapa (cuadro grande)*/

/*Como se mencionó anteriormente, hay un círculo de 1 en esta matriz bidimensional para evitar que el cuadro pequeño se salga de los límites. Esta es la función que genera este círculo*/

void newGame() /*Crear un nuevo juego. */

/*Esta función inicializa algunos relojes y crea los primeros cuadros pequeños*/

/*Por supuesto, las vistas previas deben generarse una por una después de la construcción*/

void rotateBox(int ​​​​box1[5][5], int box2[5] [5]);

/*Miembro de la función principal, gira box1 90 grados en sentido antihorario y guarda a box2*/

void rebuidNext();

/*Miembros de la función principal, genera el siguiente cuadro*/

int drop();

/*Miembros de la función principal, mueva el cuadro que cae hacia abajo (en realidad aumenta El cuadro desplegable

es solo el valor Y del hijo. Por supuesto, se debe juzgar si se superpone con el celosía del mapa*/

/*Si se superpone con el mapa, la operación de colocación no se puede completar y se devuelve 0*/

void putBox();

/*Además de esto, el cuadro que cae y el mapa son dos números bidimensionales independientes*/

/*Cuando después de la caída falla, el cuadro pequeño debe regresar a la parte superior y realizar la operación. Cae de nuevo. En este momento, el contenido original de la caja, por supuesto, se convertirá en el contenido del mapa.

, putBox

es escribir el contenido del cuadro que cae en el mapa de acuerdo con XY*/

void clear();

/*Esta función falla cuando el cuadro que cae falla y se ejecuta después de putBox, escanea todo el mapa*/

/*Borrar toda la fila de celosía, los detalles específicos se discutirán en la función*/

int move(int dir);

p>

/*Mueve el cuadro desplegable hacia la izquierda y hacia la derecha, dir indica izquierda o derecha, esto es lo mismo que soltar

*/

int test(int mx, int my, int box[5][5]);

/*El punto clave de esta comparación es determinar si el cuadro está en mx, my es la coordenada y si es una red no vacía en el mapa.

Hay superposición. Una función muy común */

int rotate();

/* Gira el cuadro que cae Por supuesto, si hay un conflicto con el mapa después de la rotación,

Cancelará la rotación y devolverá 0, pero el valor devuelto parece inútil~*/

int newfall();

/*Crea un elemento desplegable y cambia "siguiente" Copia el contenido de la vista previa al cuadro que cae*/

/* y mueve el cuadro que cae a la parte superior del mapa Por supuesto, durante este proceso, si hay un conflicto en la parte superior

, se devolverá 0 Esto indica que está lleno...gameOver*/.

/************************************ ******** *******************\

* Área variable*

\************ * **********************************************/

/*En la descripción anterior, es posible que esté un poco confundido porque es posible que no

* comprenda las variables reales utilizadas

*/

int map[MAX_Y 4][MAX_X 4]; /*Map\big box...MAX_X, Y es el área visible*/

/*Ya he dicho que es necesario colocar dos áreas afuera. Círculo "guard"*/

int curbox[5][5]; /*Cuadro actualmente eliminado*/

int curx, cury /*Guardar el cuadro activo actual en Posición en el mapa*/

int nextbox[5][5] /*El cuadro que contiene la siguiente forma*/

/*Lo anterior son los cuadros y las coordenadas */

/*Aquí están las siete matrices de puntos de gráficos de Tetris estándar, que se copiarán en los cuadros correspondientes cuando se utilicen... :)*/

int box[MAX_C][5 ][5] = { /*MAX_C(7) cuadros predefinidos*/

{

{0, 0, 0, 0, 0},

{0, 0, 0, 0, 0},

{1, 1, 1, 1, 0},

{0, 0, 0, 0, 0},

{0, 0, 0, 0, 0}

},

{

{0, 0, 0, 0 , 0},

{0, 0, 1, 0, 0},

{0, 1, 1, 1, 0},

{ 0, 0, 0, 0, 0},

{0, 0, 0, 0, 0 }

},

{

{0, 0, 0, 0, 0},

{0, 1, 1,

0, 0},

{0, 0, 1, 1, 0},

{0, 0, 0, 0, 0},

{0, 0, 0, 0, 0}

},

{

{0, 0, 0, 0, 0},

{0, 0, 1, 1, 0},

{0, 1, 1, 0, 0},

{0, 0, 0, 0 , 0},

{0, 0, 0, 0, 0}

},

{

{0, 0 , 0, 0, 0},

{0, 1, 1, 0, 0},

{0, 0, 1, 0, 0},

{0, 0, 1, 0, 0},

{0, 0, 0, 0, 0}

},

{

{0, 0, 0, 0, 0},

{0, 0, 1, 1, 0},

{0, 0, 1, 0, 0},

{0, 0, 1, 0, 0},

{0, 0, 0, 0, 0}

},

{

{0, 0, 0, 0, 0},

{0, 0, 1, 1, 0},

{0, 0, 1, 1, 0},

{0, 0, 0, 0, 0},

{0, 0, 0 , 0, 0}

}

};

/********************* ** ************************************\

* Reloj*

\********************************************* ********* *******/

/*La parte del reloj también es muy comprensible, una se usa para configurar el reloj y la otra se usa para probar el estado de activación del reloj*/

Temporizador tDown; *El intervalo de tiempo de caída normal del reloj será relativamente grande*/

Temporizador tFast /*Se utiliza caída rápida al presionar KEY_DOWN*/

p>

int speed = 13; /*Controlar el intervalo de tiempo de caída */

#define FAST_INTV 1 /*Intervalo de reloj rápido*/

/***** ******************* ********************************** \

* Reloj*

\********************************* ***************** ******/

/*La parte del reloj también es muy comprensible, una se usa para configurar el reloj y otra el otro se usa para probar el estado de activación del reloj*/

Temporizador tDown; /* El intervalo de tiempo de caída normal será relativamente grande*/

Temporizador tFast /*Se utiliza caída rápida; al presionar KEY_DOWN*/

#define FAST_INTV 1 /*Intervalo de reloj rápido*/

int GetTickCount() { /*Leer reloj BIOS*/

int ret;

>

ret = peek(0x0, 0x46e); /*realmente lee el contenido en la memoria 0:046e*/

ret lt = 8 /*Este lugar es $ #$^ $amp; ^*/

ret = peek(0x0, 0x46c); /*Hay demasiadas cosas nuevas, busca algunos libros y léelos*/

return (ret)

}

int setTimer(Timer *t, unsigned int intv, BOOL en) {

t -gt enable = en; reloj*/

t -gt; intervel = intv;

t -gt; lasttime = GetTickCount() /*última vez registra el anterior*/

/*Qué tickcount devuelve*/

/*De esta manera, cuando se vuelve a probar el tiempo, se genera un nuevo tickcount

Se resta el tickcount anterior y se obtiene un intervalo de tiempo.

, que se puede comparar con el intervalo para determinar si

está activado

*/

devuelve 0;

}

BOOL testTimer(Timer *t) { /*Explicado en la línea 6 arriba :)*/

unsigned int tmp, dt;

if (!(t -gt; habilitado)) devuelve FALSO;

tmp = GetTickCount();

dt = tmp - ( t -gt; última vez);

if(dt gt; = t -gt; intervel) {

t -gt; lasttime = tmp;

return TRUE;

}

devuelve FALSO;

}

/*************** ************ ******************************\

* Parte de renderizado*

\ ***************************************** ******** **********/

/*Proporciona renderizado para actualizar toda la pantalla*/

/*Todavía hay mucho que decir sobre esta función. , para buscar belleza y flexibilidad durante la compilación*/

/*, esta función es bastante detallada...*/

/*Ahora escribe este juego. Material gráfico... No estoy muy contento de usar TC2's Graphics. Después de todo, está desactualizado, pero como es simple y práctico, es perfecto para enseñar.

Esta es también la razón por la que TC siempre se usa en. A los profesores no les gusta pedirles a los estudiantes que hagan preguntas que les resulten difíciles de dominar...*/

/*Aquí se utiliza el modo VGAMED en lugar de VGAHI, porque VGAMED tiene dos páginas (. se pueden considerar como buffers), que se pueden usar para lograr animaciones sin flash, es decir: en segundo plano

Dibujar gráficos en la página y mostrarlos una vez finalizado.

Aquí se utilizan dos funciones.

:

setactivepage(1 | 0) El parámetro solo puede ser 1 o 0. Seleccione la página de dibujo. Por ejemplo, después de

seleccionar 1, todas las acciones de dibujo futuras se dibujarán en. página 1. Arriba.

setvisualpage(1 | 0) Esto se llama seleccionar la página visible, es decir, elegir si mostrar la página 1 o 0 en la pantalla

*/

void render(void) {

int x, y;

static int cPage = 0; /*Página actual, utilizada para cambiar de página*/

#define STARTX 50 /*Definir varias constantes*/

#define STARTY 0

#define LEN 18

setactivepage(cPage=( cPage = = 0?1:0)); /*Seleccionar página*/

cleardevice(); /*Borrar pantalla*/

setcolor(15);

rectangle( STARTX LEN * 2 - 2,

STARTY LEN * 3 - 2,

STARTX LEN * (MAX_X - 2) 2,

STARTY LEN * (MAX_Y - 2) 2);

/*Dibujar un marco con blanco*/

setfillstyle(SOLID_FILL, 5);

for( y = 3; y lt; MAX_Y - 2; y) { /*Dibujar un mapa*/

for(x = 2; x lt; MAX_X - 2; x) {

if (mapa[y][x]) {

rectángulo( x * LEN STARTX,

y * LEN STARTY,

x * LEN STARTX LEN ,

y * LEN INICIO LEN);

bar( x * LEN INICIOX 1,

y * LEN INICIO 1,

x * LEN STARTX LEN - 2,

y * LEN STARTY LEN - 2);

}

}

}

/*No dé una introducción demasiado complicada a la operación de dibujo. Es solo para funciones*/

/*El párrafo anterior refleja el mapa en la pantalla de acuerdo con la matriz de puntos. en el mapa*/

for(y = 0; y lt; 5; y) { /*Dibujar objetos que caen*/

for(x = 0; x lt; 5 ; x) {

if(curbox[y][x]) {

if(y cury gt; 2) {

rectangle( (x curx ) * LEN STARTX,

(y cury) * LEN STARTY,

(x curx) * LEN STARTX LEN,

(y cury) * LEN

STARTY LEN);

bar( (x curx) * LEN STARTX 1,

(y cury) * LEN STARTY 1,

(x curx) * LEN STARTX LEN - 2,

(y cury) * LEN STARTY LEN - 2);

}

}

}

}

/*Lo anterior muestra las coordenadas del cuadro que cae en el mapa y lo dibuja en el área correspondiente*/

for(y = 0; y lt; 5; y) { /*Dibujar siguiente*/

for(x = 0; x lt; 5; x) {

if(nextbox[y] [x ]) {

rectángulo( x * LEN 320,

y * LEN 10,

x * LEN 338,

y * LEN 28);

barra( x * LEN 321,

y * LEN 11,

x * LEN 336,

y * LEN 26);

}

}

}

/*Esto genera una vista previa del siguiente cuadro*/

setvisualpage(cPage); /*Confirma que el dibujo está realizado en la página cPage*/

/*Mostrarlo*/

}

/************************************************ * *********\

* Parte de inicialización*

\******************** ** **********************************/

/* Proporcionar newGame() a inicializar un nuevo juego */

void initMap(void) { /*Inicializar el mapa*/

int x, y /*Necesitamos un círculo de guardias...* /

for(y = 0; y lt; MAX_Y; y) {

for(x = 0; x lt; MAX_X; x) {

if(x lt; 2 || 0;

}

} /*Esta forma se inicializa aquí*/

} /*Por supuesto que no tiene una portada...*/

void newGame() { /*Crear un nuevo juego*/

int x, y;

initMap(); /*Inicializar el mapa*/

srand(GetTickCo

unt()); /*Inicializa el generador aleatorio*/

rebuidNext(); /*Crea el siguiente*/

setTimer(amp; tDown, speed, 1); / *Inicia el reloj (rápido y lento)*/

setTimer(amp; tFast, FAST_INTV, 1);

newfall() /*Operar el cuadro que cae*/

/*De esta manera el primer bloque que cae

está listo en la parte superior del mapa*/

}

/*** ************************************************** * *\

* Funciones principales*

\**************************** ****** *************************/

void rotateBox(int ​​​​box1[5][ 5], int box2[5] [5]) {

/*Rotar cuadro1 y enviar a cuadro2*/

int x, y;

para (x = 0; x lt; 5 ; x ) /*Esta función puede requerir práctica*/

for(y = 4; y gt; = 0; y--) /*Escríbela como impresionante*/

box2[y][x] = box1[x][4 - y];

}

void rebuidNext() { /* Crea la siguiente forma y colócala en el siguiente cuadro Medio*/

int i, x, y;

i = random(MAX_C); /p>

for(y = 0; y lt; 5; y) /*y cópialo*/

for(x = 0; x lt; 5; x)

nextbox[y ][x] = box[i][y][x]; /*Copiar*/

}

int drop() { /*Drop , devuelve éxito o no* /

int newy /*La nueva posición donde caerá la caja*/

newy = cury 1 /*Es la posición Y actual 1; */

if (test(curx, newy, curbox)) {

cury = newy /*Prueba el cuadro desplegable en esta posición*/

return 1; /*Si hay un conflicto, no Si es así*/

} /*Establecer cury directamente*/

return 0;

}

void putBox() { /* Rellena el cuadro curbox en el mapa*/

int x, y;

for(y = 0; y lt; 5 ; y) /*Esto también es simple, basado principalmente en */

>for(x = 0; x lt; 5; x) /*según curx, cury señala la posición*/

if(curbox[y][x])

map[ y cury][x curx] = curbox[y][x];

}

void clear() { /*Borrar líneas completas*/

/*Esta función es en realidad muy ineficiente por simplicidad

Ha sido probada de principio a fin*/

/*El algoritmo específico es:

Desde la línea 0 hasta la última línea, pruebe si el entramado del mapa está lleno, de ser así

A partir de la línea actual, el mapa de arriba caerá una línea hacia abajo*/

int x, y;

int dx, dy;

int fullflag;

for(y = 0; y lt; MAX_Y - 2; y ) { /*Las dos últimas líneas están reservadas*/

fullflag = 1; /*Se supone que está completo*/

for(x = 2; x lt; MAX_X - 2; x ) { /*Columnas reservadas~*/

if(!map[y][x]) {

fullflag = 0;

break;

break p>

}

}

if(fullflag) { /*Bajar una línea*/

for(dy = y; dy gt; 0; dy--)

for(dx = 2; dx lt; MAX_X - 2; dx)

mapa[dy][dx] = mapa [dy - 1][ dx];

for(dx = 2; dx lt; MAX_X - 2; dx)

mapa[0][dx] = 0;

/ *Y borra la primera línea*/

}

}

}

int move(int dir ) { /*Regreso Éxito o fracaso*/

int newx;

if(dir) newx = curx 1;

/*Igual que soltar, preparar las coordenadas después del movimiento* /

else newx = curx - 1;

if(test(newx, cury, curbox)) { /*Prueba de conflicto*/

curx = newx; /*Cambiar curx si es posible*/

return 1;

}

return 0; }

int test(int mx, int my, int box[5][5]) {

/*Prueba si la caja puede aterrizar en la posición de mx y my in el mapa*/

/*Esta es la función más crítica, que determina si ocurre un conflicto no nulo*/

/*Pero el algoritmo sigue siendo muy simple*/

int x, y ;

for(y = 0; y lt; 5; y)

for(x = 0; x lt; 5; x )

if( mapa[y my][x mx] amp; amp; box[y][x])

retur

n 0;

retorno 1

}

int rotar() {

int x, y;

int newbox[5][5]; /*Debemos mover el cuadro actual a un cuadro nuevo*/

/*Probar el conflicto de este nuevo cuadro*/

rotarBox(curbox, newbox); /*Girar a un nuevo cuadro*/

if(test(curx, cury, newbox)) {

/*Y se pueden colocar nuevos cuadros el mapa sin conflicto*/

for(y = 0; y lt; 5; y)

for(x = 0; x lt; 5; x )

curbox[y][x] = newbox[y][x] /*Copiar en*/

return 1;

}

else return 0;

}

int newfall() { /*Error al crear un elemento de caída y devolver 0*/

int x, y ;

curx = MAX_X / 2 - 2; /*Reespecificar la posición del cuadro pequeño*/

cury = 0;

for(y = 0; y lt; 5; y)

for(x = 0; x lt; 5; x)

curbox[y][x] = nextbox[y][x];/ *Copiar nextBox*/

rebuidNext(); /*Reconstruir nextBox*/

return test(curx, cury, curbox);

}

/******************************************** ** *****************\

* Función principal: toda la estructura del juego*

\******* ***** ********************************************** ****** **/

int main() {

char key; /*Registrar la clave actual*/

int i;

int gd = VGA, gm = VGAMED; /*Modo de gráficos inicializado*/

Temporizador *ptDown; /*El reloj señalado por la gota (con velocidad)*/

Temporizador de tendencia /*Para evitar que el renderizado cause una carga excesiva en el programa*/

/*Utilice un reloj para controlar la velocidad de renderizado*/

/ *Establezca el intervalo = 1,*/

/*Esto es 18 FPS, por supuesto que no puede alcanzar el estándar*/

/*El estándar 60 FPS... Después de todo , esto es DOS...*/

setTimer(amp;trender, 1, 1);

initgraph(amp;gd, amp;gm, ""); Inicializar gráfico*/

newGame( ); /*Nuevo juego...*/

while(1) {

/*Bucle principal del juego*/

if(kbhit()) { /*Si se presiona el teclado*/

key = getch() /*Leer un valor clave para key*/

}

else key = 0;

switch(key) { /*Juzga la clave leída*/

case KEY_UP:

rotate(); /*Arriba, rota el cuadro que cae*/

romper;

case KEY_DOWN:

ptDown = amp; tFast; /*Usar reloj tFast*/

break;

case KEY_LEFT:

move(0);

romper;

case KEY_RIGHT:

move(1); /*Mover a la derecha*/

romper;

case KEY_ESC:

closegraph(); /*Fin del juego*/

salir(0);

predeterminado:

ptDown = amp; tDown; /*Usa la velocidad original*/

}

if(testTimer(ptDown)) { /*El paradero se ha establecido arriba

El reloj utilizado está en ptDown*/

if(!drop()) { /*Drop, devuelve 0 en caso de falla*/

putBox() / *Write; al mapa*/

clear(); /*Borrar líneas completas*/

if(!newfall()) { /*Crear un nuevo drop, si falla, el el juego terminará* /

closegraph();

exit(0);

}

}

}

if(testTimer(amp;trender)) /*Finalmente...render...*/

render();

}

}