当前位置:网站首页>Implementation of Tetris in C language
Implementation of Tetris in C language
2022-07-03 17:32:00 【Domineering Xiao Ming】
Catalog
Two 、 Complete code , You can copy and run it directly
3、 ... and 、 Required development environment
Four 、 Specific project realization
① Game welcome interface welcome( )
② Game background initGameScreen( )
③ Square means int block[ ][ ][ ]
④ The new square means nextBlock( )
⑤ Design the game cycle main( )
⑥ Build user operation framework move( )Ⅰ
⑦ Determine whether the square can move in the specified direction moveable( )
⑧ Game failure check failCheck( )
⑨ Clear the block during the descent clearBlock( )
⑩ Judge the rotation of the square rotatable( )
①① Draw the square during the descent drawBlock( )
①④ The user operation framework is perfect Ⅱ mov( )
①⑤ Eliminate blocks check( ) + down( )
①⑥ Update scores and grades addScore( ) + updateGrade( )
One 、 Game effect display

The orientation of each square is represented by a two-dimensional array

Two 、 Complete code , You can copy and run it directly
#include<graphics.h>
#include<stdio.h>
#include<time.h>
#include<conio.h> //kbhit()
int score = 0; // Total score
int rank = 0; // Grade
#define BLOCK_COUNT 5
#define BLOCK_WIDTH 5
#define BLOCK_HEIGHT 5
#define UNIT_SIZE 20 // Small square width
#define START_X 130 // Square landing box , Square landing starting position
#define START_Y 30
#define KEY_UP 87 // The user action
#define KEY_LEFT 65
#define KEY_RIGHT 68
#define KEY_DOWN 83
#define KEY_SPACE 32
#define MinX 30 // The upper left corner of the game
#define MinY 30
int speed = 500; // Square landing speed
int NextIndex = -1; // Next block
int BlockIndex = -1; // Current box
typedef enum { // The square faces
BLOCK_UP,
BLOCK_RIGHT,
BLOCK_LEFT,
BLOCK_DOWN
}block_dir_t;
typedef enum { // The moving direction of the square
MOVE_DOWN,
MOVE_LEFT,
MOVE_RIGHT
}move_dir_t;
// Square color
int color[BLOCK_COUNT] = {
GREEN,
CYAN,
MAGENTA,
YELLOW,
BROWN
};
int visit[30][15]; // Access array visit[i][j] = 1 Indicates that there is a square in this position
int markColor[30][15]; // Corresponding position color
int block[BLOCK_COUNT * 4][BLOCK_WIDTH][BLOCK_HEIGHT] = {
// | Shape of square
{ 0,0,0,0,0,0,0,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,0,0,0,0,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,0,1,0,0,0,0,1,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0 },
// L Shape of square
{ 0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,1,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,0,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0 },
// field Shape of square
{ 0,0,0,0,0,0,1,1,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,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,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,1,1,0,0,0,0,0,0,0,0,0,0,0,0 },
// T Shape of square
{ 0,0,0,0,0,0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,1,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,0,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0 },
// Z Shape of square
{ 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,0,0,0,1,1,0,0,0,1,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,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0 },
};
/***************************
* function : The welcome page
* Input :
* nothing
* return :
* nothing
**************************/
void welcome() {
//1. Initialize canvas
initgraph(550, 660);
system("pause");
//2. Set the window title
HWND window = GetHWnd();// Get the window , Get the current window
SetWindowText(window, _T(" tetris Here comes Xiao Ming ")); // Set title
//3. Set the game initial page
setfont(40, 0, _T(" Microsoft YaHei ")); // Set the font style of the text ( high , wide (0 It means adaptive ), typeface )
setcolor(WHITE); // Set the color
outtextxy(205, 200, _T(" Russian method "));
setfont(20, 0, _T(" Regular script "));
setcolor(WHITE); // Set the color
outtextxy(175, 300, _T(" Programming , Start with Tetris "));
Sleep(3000);
}
/***************************
* function : Initialize the game scene
* Input :
* nothing
* return :
* nothing
**************************/
void initGameSceen() {
char str[16]; // Store scores
//1. Clear the screen
cleardevice();
//2. Painting scene
rectangle(27, 27, 336, 635); // Box landing frame outer frame
rectangle(29, 29, 334, 633); // Box landing box inside the box
rectangle(370, 50, 515, 195); // Box prompt
setfont(24, 0, _T(" Regular script ")); // Write “ next ”
setcolor(LIGHTGRAY); // gray
outtextxy(405, 215, _T(" next :"));
setcolor(RED); // Write score
outtextxy(405, 280, _T(" fraction :"));
// In the specified format , take score write in str
sprintf_s(str, 16, "%d", score);
// Here, set the character set to multi character , Guarantee outtextxy You can write out variables str
outtextxy(415, 310, str);
outtextxy(405, 375, _T(" Grade :")); // Grade
// In the specified format , take rank write in str
sprintf_s(str, 16, "%d", rank);
// Here, set the character set to multi character , Guarantee outtextxy You can write out variables str
outtextxy(415, 405, str);
setcolor(LIGHTBLUE); // Operation instructions
outtextxy(390, 475, " Operation instructions :");
outtextxy(390, 500, "↑: rotate ");
outtextxy(390, 525, "↓: falling ");
outtextxy(390, 550, "←: Move left ");
outtextxy(390, 575, "→: Move right ");
outtextxy(390, 600, " Space : Pause ");
}
/*****************************************
* function : Clear the box in the box prompt box
* Input :
* nothing
* return :
* nothing
****************************************/
void clearBlock() {
setcolor(BLACK);
setfont(23, 0, " Regular script ");
for (int i = 0; i < BLOCK_HEIGHT; ++i) {
for (int j = 0; j < BLOCK_WIDTH; ++j) {
int x = 391 + j * UNIT_SIZE;
int y = 71 + i * UNIT_SIZE;
outtextxy(x, y, "■");
}
}
}
/*****************************************
* function : Clear the blocks during landing
* Input :
* x,y - The coordinates of the square ( The position of the upper left corner of the two-dimensional array )
* block_dir_t - Square direction
* return :
* nothing
****************************************/
void clearBlock(int x, int y, block_dir_t blockDir) {
setcolor(BLACK);
// setfont(23, 0, " Regular script ");
int id = BlockIndex * 4 + blockDir;
for (int i = 0; i < BLOCK_HEIGHT; ++i) {
for (int j = 0; j < BLOCK_WIDTH; ++j) {
if (block[id][i][j] == 1) {
int x2 = x + j * UNIT_SIZE;
int y2 = y + i * UNIT_SIZE;
outtextxy(x2, y2, "■");
}
}
}
}
/*****************************************
* function : In the prompt box And Draw a square at the starting position of the landing box
* Input :
* x,y - The coordinates of the square ( The position of the upper left corner of the two-dimensional array )
* return :
* nothing
****************************************/
void drawBlock(int x, int y) {
setcolor(color[NextIndex]);
setfont(23, 0, " Regular script ");
for (int i = 0; i < BLOCK_HEIGHT; ++i) {
for (int j = 0; j < BLOCK_WIDTH; ++j) {
if (block[NextIndex * 4][i][j] == 1) {
int x2 = x + j * UNIT_SIZE;
int y2 = y + i * UNIT_SIZE;
outtextxy(x2, y2, "■");
}
}
}
}
/*****************************************
* function : Draw the square during the descent
* Input :
* x,y - The coordinates of the square ( The position of the upper left corner of the two-dimensional array )
* block_dir_t - Square direction
* return :
* nothing
****************************************/
void drawBlock(int x, int y, block_dir_t dir) {
setcolor(color[BlockIndex]);
setfont(23, 0, " Regular script ");
int id = BlockIndex * 4 + dir;
for (int i = 0; i < BLOCK_HEIGHT; ++i) {
for (int j = 0; j < BLOCK_WIDTH; ++j) {
if (block[id][i][j] == 1) {
// Erase the... Of the box i Xing di j Column
outtextxy(x + j * UNIT_SIZE, y + i * UNIT_SIZE, "■");
}
}
}
}
/*****************************************
* function : A new box is generated in the box prompt
* Input :
* nothing
* return :
* nothing
****************************************/
void nextblock() {
clearBlock();
// Generate random numbers , Randomly select the box
srand((unsigned)time(NULL)); // Use the return value of the time function , As a random seed
NextIndex = rand() % BLOCK_COUNT; // produce 0~5 The random number
drawBlock(391, 71);
}
/*****************************************
* function : Judge whether it can move in the specified direction at the specified position
* Input :
* x,y - Square position
* moveDir - The direction you want to move next
* blockDir - The direction of the current square
* return :
* true - Can be moved
* false - Can't move
****************************************/
bool moveable(int x0, int y0, move_dir_t moveDir, block_dir_t blockDir) {
// The upper left corner of the calculation box is 30×15 Location of the game area ( How many lines , How many columns )
int x = (y0 - MinY) / UNIT_SIZE;
int y = (x0 - MinX) / UNIT_SIZE;
int ret = 1;
int id = BlockIndex * 4 + blockDir;
if (moveDir == MOVE_DOWN) {
for (int i = 0; i < BLOCK_HEIGHT; ++i) {
for (int j = 0; j < BLOCK_WIDTH; ++j) {
// The condition of not moving down : The solid square has reached the bottom (x+i+1==30), Or there are squares at the bottom
if (block[id][i][j] == 1 &&
(x + i + 1 == 30 || visit[x + i + 1][y + j] == 1)) {
ret = 0;
}
}
}
}
else if (moveDir == MOVE_LEFT) {
for (int i = 0; i < BLOCK_HEIGHT; ++i) {
for (int j = 0; j < BLOCK_WIDTH; ++j) {
// The condition of not moving to the left : The solid box has reached the left boundary (y+j==0), Or there is a square on the left
if (block[id][i][j] == 1 &&
(y + j <= 0 || visit[x + i][y + j - 1] == 1)) {
ret = 0;
}
}
}
}
else if (moveDir == MOVE_RIGHT) {
for (int i = 0; i < BLOCK_HEIGHT; ++i) {
for (int j = 0; j < BLOCK_WIDTH; ++j) {
// The condition of not moving down : The solid box has reached the right boundary (y+j+1>=15), Or there is a square on the right
if (block[id][i][j] == 1 &&
(y + j + 1 >= 15 || visit[x + i][y + j + 1] == 1)) {
ret = 0;
}
}
}
}
return ret;
}
/*****************************
* function : Check whether the game is over
* Input :
* nothing
* return :
* nothing
*****************************/
void failCheck() {
// The end condition of the game is that the newly drawn box at the top will “ curing ”, The newly drawn square at the top faces upward , The direction of motion is downward
if (!moveable(START_X, START_Y, MOVE_DOWN, (block_dir_t)BLOCK_UP)) {
setcolor(WHITE);
setfont(45, 0, " Official script ");
outtextxy(75, 300, "Game Over!");
Sleep(1000);
system("pause");
closegraph();
exit(0);
}
}
/**************************
* function : Delay waiting for
* Input :
*
* return :
* nothing
*************************/
void wait(int interval) {
int count = interval / 10;
for (int i = 0; i < count; ++i) {
Sleep(10);
// If the user has a key during sleep , Then sleep ends
if (_kbhit()) {
return;
}
}
}
/*****************************************
* function : Judge whether the current square can rotate in the specified direction
* Input :
* x,y - Square position ( Two dimensional array coordinates )
* dir - The direction of rotation of the square
* return :
* true - Can rotate
* false - Do not rotate
****************************************/
bool rotatable(int x, int y, block_dir_t dir) {
// First, judge whether you can continue to move down
if (!moveable(x, y, MOVE_DOWN, dir)) {
return false;
}
int x2 = (y - MinY) / UNIT_SIZE;
int y2 = (x - MinX) / UNIT_SIZE;
int id = BlockIndex * 4 + dir;
for (int i = 0; i < BLOCK_HEIGHT; ++i) {
for (int j = 0; j < BLOCK_WIDTH; ++j) {
// Cannot rotate condition : The left and right boundaries are out of bounds or there are blocks “ stop ”
if (block[id][i][j] == 1 && (y2 + j < 0 || y2 + j >= 15 || visit[x2 + i][y2 + j] == 1)) {
return false;
}
}
}
return true;
}
/*****************************************
* function :
* Input :
*
* return :
* nothing
****************************************/
void mark(int x, int y, block_dir_t dir) {
int id = BlockIndex * 4 + dir;
int x2 = (y - MinY) / UNIT_SIZE;
int y2 = (x - MinX) / UNIT_SIZE;
for (int i = 0; i < BLOCK_HEIGHT; ++i) {
for (int j = 0; j < BLOCK_WIDTH; ++j) {
if (block[id][i][j] == 1) {
visit[x2 + i][y2 + j] = 1;
markColor[x2 + i][y2 + j] = color[BlockIndex];
}
}
}
}
/*****************************************
* function : Read user actions , Update the landing box from time to time
* Input :
* nothing
* return :
* nothing
****************************************/
void move() {
int x = START_X; // Square start position
int y = START_Y;
int k = 0;
block_dir_t blockDir = (block_dir_t)BLOCK_UP;
int curSpeed = speed; // Define the current square landing speed
// Judge whether the game is over before reading the user's operation
failCheck();
// Keep falling down
while (1) {
int curSpeed = speed; // Define the current square landing speed
// Clear the box
clearBlock(x, k + y, blockDir);
// Judge the direction of choice
if (_kbhit()) {
int key = _getch();
if (key == KEY_SPACE) {
system("pause");
}
else if (key == KEY_UP) {
block_dir_t nextDir = (block_dir_t)((blockDir + 1) % 4);
if (rotatable(x, y + k, nextDir)) {
blockDir = nextDir;
}
}
else if (key == KEY_LEFT) {
if (moveable(x, y + k + 20, MOVE_LEFT, blockDir)) {
x -= UNIT_SIZE;
}
}
else if (key == KEY_RIGHT) {
if (moveable(x, y + k + 20, MOVE_RIGHT, blockDir)) {
x += UNIT_SIZE;
}
}
else if (key == KEY_DOWN) {
curSpeed = 50;
}
}
k += 20;
// Draw box
drawBlock(x, y + k, blockDir);
// Sleep
wait(curSpeed);
// Curing treatment of blocks , After the block is fixed, end the cycle , Of the current box move completion of enforcement
if (!moveable(x, y + k, MOVE_DOWN, blockDir)) {
mark(x, y + k, blockDir);
break;
}
}
}
/*****************************************
* function : Draw the square that just landed from the top , Update the box in the prompt box , Call the block landing function move()
* Input :
* nothing
* return :
* nothing
****************************************/
void newblock() {
BlockIndex = NextIndex;
// Draw the square just falling from the top
drawBlock(START_X, START_Y);
// Let the new box pause for a while
Sleep(200);
// Draw the next box in the upper right corner
nextblock();
// The box landed
move();
}
/*****************************************
* function : Eliminate section i That's ok , And move all the lines down
* Input :
* nothing
* return :
* nothing
****************************************/
void down(int x) {
for (int i = x; i > 0; --i) {
for (int j = 0; j < 15; ++j) {
if (visit[i - 1][j] == 1) {
visit[i][j] = 1;
markColor[i][j] = markColor[i - 1][j];
setcolor(markColor[i][j]);
outtextxy(20 * j + MinX, 20 * i + MinY, "■");
}
else {
visit[i][j] = 0;
setcolor(BLACK);
outtextxy(20 * j + MinX, 20 * i + MinY, "■");
}
}
}
// Clear the top grid
setcolor(BLACK);
for (int j = 0; j < 15; ++j) {
visit[0][j] = 0;
outtextxy(20 * j + MinX, MinY, "■");
}
}
/*****************************************
* function : Update score
* Input :
* nothing
* return :
* nothing
****************************************/
void addScore(int lines) {
char str[32];
score += lines * 10;
sprintf_s(str, 32, "%d", score);
setcolor(RED);
outtextxy(415, 310, str);
}
/*************************
* function : Update level
* Input :
* nothing
* return :
* nothing
*************************/
void updateGrade() {
// Update level
// hypothesis 50 Level by level
rank = score / 50;
char str[32];
sprintf_s(str, 32, "%d", rank);
setcolor(RED);
outtextxy(415, 405, str);
// Update speed
if (speed <= 100) {
speed = 100;
}
else {
speed = 500 - rank * 20;
}
}
/*************************
* function : Check if there is a full line of squares
* Input :
* nothing
* return :
* nothing
*************************/
void check() {
int i, j;
int clearLines = 0;
for (i = 29; i >= 0; i--) {
// Check the i Is the line full
for (j = 0; j < 15 && visit[i][j]; j++);
// At this point , There are two situations :
// 1. The first i The line is not full , That means there is a vacancy here j<15
// 2. The first i The line is full , here j>=15
if (j >= 15) {
// here , The first i The line is full , We need to eliminate i That's ok
down(i); // Eliminate section i That's ok , And move the top lines down
i++; // Because there is... In the outermost cycle i--, So we first i++, Make the next cycle , Check this one again
clearLines++;
}
}
// Update score
addScore(clearLines);
// Update level ( Update level prompt , Update speed )
updateGrade();
}
int main() {
welcome();
initGameSceen();
// Create a new square
nextblock();
// system("pause");
Sleep(800);
// Initialize access array
memset(visit, 0, sizeof(visit));
while (1) {
newblock();
// Eliminate full lines , And update scores and speed
check();
}
system("pause");
closegraph();
return 0;
}3、 ... and 、 Required development environment
1) install VS2019, or VS Other versions
2) install easyX Graphics library
Four 、 Specific project realization
① Game welcome interface welcome( )

There will be a game welcome page before the game starts , The whole page will last about three seconds , Then enter the game scene . In the game welcome page , In addition to displaying the game name , Also modify the window title .
/***************************
* function : The welcome page
* Input :
* nothing
* return :
* nothing
**************************/
void welcome() {
//1. Initialize canvas
initgraph(550, 660);
//2. Set the window title
HWND window = GetHWnd();// Get the window , Get the current window
SetWindowText(window, _T(" tetris Here comes Xiao Ming ")); // Set title
//3. Set the game initial page
setfont(40, 0, _T(" Microsoft YaHei ")); // Set the font style of the text ( high , wide (0 It means adaptive ), typeface )
setcolor(WHITE); // Set the color
outtextxy(205, 200, _T(" Russian method "));
setfont(20, 0, _T(" Regular script "));
setcolor(WHITE); // Set the color
outtextxy(175, 300, _T(" Programming , Start with Tetris "));
Sleep(3000);
}② Game background initGameScreen( )

Draw game scenes
/***************************
* function : Initialize the game scene
* Input :
* nothing
* return :
* nothing
**************************/
void initGameSceen() {
char str[16]; // Store scores
//1. Clear the screen
cleardevice();
//2. Painting scene
rectangle(27, 27, 336, 635); // Box landing frame outer frame
rectangle(29, 29, 334, 633); // Box landing box inside the box
rectangle(370, 50, 515, 195); // Box prompt
setfont(24, 0, _T(" Regular script ")); // Write “ next ”
setcolor(LIGHTGRAY); // gray
outtextxy(405, 215, _T(" next :"));
setcolor(RED); // Write score
outtextxy(405, 280, _T(" fraction :"));
// In the specified format , take score write in str
sprintf_s(str, 16, "%d", score);
// Here, set the character set to multi character , Guarantee outtextxy You can write out variables str
outtextxy(415, 310, str);
outtextxy(405, 375, _T(" Grade :")); // Grade
// In the specified format , take rank write in str
sprintf_s(str, 16, "%d", rank);
// Here, set the character set to multi character , Guarantee outtextxy You can write out variables str
outtextxy(415, 405, str);
setcolor(LIGHTBLUE); // Operation instructions
outtextxy(390, 475, " Operation instructions :");
outtextxy(390, 500, "W: rotate ");
outtextxy(390, 525, "S: falling ");
outtextxy(390, 550, "A: Move left ");
outtextxy(390, 575, "D: Move right ");
outtextxy(390, 600, " Space : Pause ");
system("pause");
}③ Square means int block[ ][ ][ ]

The orientation of each square is represented by a two-dimensional array . This time, five kinds of squares were designed , Each square has four orientations , Use a three-dimensional array to store each stiffness and its orientation .1 It means that the point is a square .
#define BLOCK_COUNT 5
#define BLOCK_WIDTH 5
#define BLOCK_HEIGHT 5
int block[BLOCK_COUNT * 4][BLOCK_WIDTH][BLOCK_HEIGHT] = {
// | Shape of square
{ 0,0,0,0,0,0,0,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,0,0,0,0,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,0,1,0,0,0,0,1,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0 },
// L Shape of square
{ 0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,1,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,0,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0 },
// field Shape of square
{ 0,0,0,0,0,0,1,1,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,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,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,1,1,0,0,0,0,0,0,0,0,0,0,0,0 },
// T Shape of square
{ 0,0,0,0,0,0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,1,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,0,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0 },
// Z Shape of square
{ 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,0,0,0,1,1,0,0,0,1,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,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0 },
};④ The new square means nextBlock( )

In the box prompt box, each time a new box is generated, it consists of two actions , First, erase the square , Then draw a new square .
/*****************************************
* function : Clear the box in the box prompt box
* Input :
* nothing
* return :
* nothing
****************************************/
void clearBlock() {
setcolor(BLACK);
setfont(23, 0, " Regular script ");
for (int i = 0; i < BLOCK_HEIGHT; ++i) {
for (int j = 0; j < BLOCK_WIDTH; ++j) {
int x = 391 + j * UNIT_SIZE;
int y = 71 + i * UNIT_SIZE;
outtextxy(x, y, "■");
}
}
}
/*****************************************
* function : In the prompt box And Draw a square at the starting position of the landing box
* Input :
* x,y - The coordinates of the square ( The position of the upper left corner of the two-dimensional array )
* return :
* nothing
****************************************/
void drawBlock(int x, int y) {
setcolor(color[NextIndex]);
setfont(23, 0, " Regular script ");
for (int i = 0; i < BLOCK_HEIGHT; ++i) {
for (int j = 0; j < BLOCK_WIDTH; ++j) {
if (block[NextIndex * 4][i][j] == 1) {
int x2 = x + j * UNIT_SIZE;
int y2 = y + i * UNIT_SIZE;
outtextxy(x2, y2, "■");
}
}
}
}
/*****************************************
* function : A new box is generated in the box prompt
* Input :
* nothing
* return :
* nothing
****************************************/
void nextblock() {
clearBlock();
// Generate random numbers , Randomly select the box
srand((unsigned)time(NULL)); // Use the return value of the time function , As a random seed
NextIndex = rand() % BLOCK_COUNT; // produce 0~5 The random number
drawBlock(391, 71);
}
⑤ Design the game cycle main( )
Each time a new box is generated in the game box, it will enter the landing processing of the new box , After processing, it will cycle
int main() {
welcome();
initGameSceen();
// Create a new square
nextblock();
Sleep(800);
// Initialize access array
memset(visit, 0, sizeof(visit));
while (1) {
newblock();
}
system("pause");
closegraph();
return 0;
}
/*****************************************
* function : Draw the square that just landed from the top , Update the box in the prompt box , Call the block landing function move()
* Input :
* nothing
* return :
* nothing
****************************************/
void newblock() {
BlockIndex = NextIndex;
// Draw the square just falling from the top
drawBlock(START_X, START_Y);
// Let the new box pause for a while
Sleep(200);
// Draw the next box in the upper right corner
nextblock();
// The box landed
move();
}⑥ Build user operation framework move( )Ⅰ
User operation framework : Decide whether the game is over → Erase the current square → User key operation → Draw a new square → Delay waiting for → Whether the square should be solidified ( Curing indicates the end of the operation on the current block ).
#define KEY_UP 87 // The user action
#define KEY_LEFT 65
#define KEY_RIGHT 68
#define KEY_DOWN 83
#define KEY_SPACE 32
/*****************************************
* function : Read user actions , Update the landing box from time to time
* Input :
* nothing
* return :
* nothing
****************************************/
void move() {
// Judge whether the game is over before reading the user's operation
failCheck();
// Keep falling down
while (1) {
// Clear the box
//to do
// Judge the direction of choice
if (_kbhit()) {
int key = _getch();
if (key == KEY_SPACE) {
//to do
}
else if (key == KEY_UP) {
//to do
}
else if (key == KEY_LEFT) {
//to do
}
else if (key == KEY_RIGHT) {
//to do
}
else if (key == KEY_DOWN) {
//to do
}
}
// Draw box
//to do
// Sleep
//to do
// Curing treatment of blocks , After the block is fixed, end the cycle , Of the current box move completion of enforcement
//to do
}
}⑦ Determine whether the square can move in the specified direction moveable( )
When the new box was just drawn from the top, it hit “ curing ” The square indicates the end of the game , So we just need to judge whether the box can move down . Here we first realize the function of judging whether the box can move in the specified direction .
/*****************************************
* function : Judge whether it can move in the specified direction at the specified position
* Input :
* x,y - Square position
* moveDir - The direction you want to move next
* blockDir - The direction of the current square
* return :
* true - Can be moved
* false - Can't move
****************************************/
bool moveable(int x0, int y0, move_dir_t moveDir, block_dir_t blockDir) {
// The upper left corner of the calculation box is 30×15 Location of the game area ( How many lines , How many columns )
int x = (y0 - MinY) / UNIT_SIZE;
int y = (x0 - MinX) / UNIT_SIZE;
int ret = 1;
int id = BlockIndex * 4 + blockDir;
if (moveDir == MOVE_DOWN) {
for (int i = 0; i < BLOCK_HEIGHT; ++i) {
for (int j = 0; j < BLOCK_WIDTH; ++j) {
// The condition of not moving down : The solid square has reached the bottom (x+i+1==30), Or there are squares at the bottom
if (block[id][i][j] == 1 &&
(x + i + 1 == 30 || visit[x + i + 1][y + j] == 1)) {
ret = 0;
}
}
}
}
else if (moveDir == MOVE_LEFT) {
for (int i = 0; i < BLOCK_HEIGHT; ++i) {
for (int j = 0; j < BLOCK_WIDTH; ++j) {
// The condition of not moving to the left : The solid box has reached the left boundary (y+j==0), Or there is a square on the left
if (block[id][i][j] == 1 &&
(y + j <= 0 || visit[x + i][y + j - 1] == 1)) {
ret = 0;
}
}
}
}
else if (moveDir == MOVE_RIGHT) {
for (int i = 0; i < BLOCK_HEIGHT; ++i) {
for (int j = 0; j < BLOCK_WIDTH; ++j) {
// The condition of not moving down : The solid box has reached the right boundary (y+j+1>=15), Or there is a square on the right
if (block[id][i][j] == 1 &&
(y + j + 1 >= 15 || visit[x + i][y + j + 1] == 1)) {
ret = 0;
}
}
}
}
return ret;
}
⑧ Game failure check failCheck( )

Game failure detection , When the newly drawn box cannot move down, the game fails .
/*****************************
* function : Check whether the game is over
* Input :
* nothing
* return :
* nothing
*****************************/
void failCheck() {
// The end condition of the game is that the newly drawn box at the top will “ curing ”, The newly drawn square at the top faces upward , The direction of motion is downward
if (!moveable(START_X, START_Y, MOVE_DOWN, (block_dir_t)BLOCK_UP)) {
setcolor(WHITE);
setfont(45, 0, " Official script ");
outtextxy(75, 300, "Game Over!");
Sleep(1000);
system("pause");
closegraph();
exit(0);
}
}
⑨ Clear the block during the descent clearBlock( )
If the game doesn't fail , It indicates that the user can continue to operate , Clear the box in the landing box before reading the user's operation .
/*****************************************
* function : Clear the blocks during landing
* Input :
* x,y - The coordinates of the square ( The position of the upper left corner of the two-dimensional array )
* block_dir_t - Square direction
* return :
* nothing
****************************************/
void clearBlock(int x, int y, block_dir_t blockDir) {
setcolor(BLACK);
// setfont(23, 0, " Regular script ");
int id = BlockIndex * 4 + blockDir;
for (int i = 0; i < BLOCK_HEIGHT; ++i) {
for (int j = 0; j < BLOCK_WIDTH; ++j) {
if (block[id][i][j] == 1) {
int x2 = x + j * UNIT_SIZE;
int y2 = y + i * UNIT_SIZE;
outtextxy(x2, y2, "■");
}
}
}
}⑩ Judge the rotation of the square rotatable( )

If the square can move downward in the direction to be turned, it indicates that the square can rotate , Therefore, it only needs to be used less moveable Function .
/*****************************************
* function : Judge whether the current square can rotate in the specified direction
* Input :
* x,y - Square position ( Two dimensional array coordinates )
* dir - The direction of rotation of the square
* return :
* true - Can rotate
* false - Do not rotate
****************************************/
bool rotatable(int x, int y, block_dir_t dir) {
// First, judge whether you can continue to move down
if (!moveable(x, y, MOVE_DOWN, dir)) {
return false;
}
int x2 = (y - MinY) / UNIT_SIZE;
int y2 = (x - MinX) / UNIT_SIZE;
int id = BlockIndex * 4 + dir;
for (int i = 0; i < BLOCK_HEIGHT; ++i) {
for (int j = 0; j < BLOCK_WIDTH; ++j) {
// Cannot rotate condition : The left and right boundaries are out of bounds or there are blocks “ stop ”
if (block[id][i][j] == 1 && (y2 + j < 0 || y2 + j >= 15 || visit[x2 + i][y2 + j] == 1)) {
return false;
}
}
}
return true;
}①① Draw the square during the descent drawBlock( )
Draw a new square every time according to the user's operation
/*****************************************
* function : Draw the square during the descent
* Input :
* x,y - The coordinates of the square ( The position of the upper left corner of the two-dimensional array )
* block_dir_t - Square direction
* return :
* nothing
****************************************/
void drawBlock(int x, int y, block_dir_t dir) {
setcolor(color[BlockIndex]);
setfont(23, 0, " Regular script ");
int id = BlockIndex * 4 + dir;
for (int i = 0; i < BLOCK_HEIGHT; ++i) {
for (int j = 0; j < BLOCK_WIDTH; ++j) {
if (block[id][i][j] == 1) {
// Erase the... Of the box i Xing di j Column
outtextxy(x + j * UNIT_SIZE, y + i * UNIT_SIZE, "■");
}
}
}
}①② Delay waiting for wait ( )
Every time After handling the user's operation, it will enter the delay waiting , The waiting time will depend on the current square landing speed , During the delay waiting period, if the user is detected to have a key operation, the waiting will end .
/**************************
* function : Delay waiting for
* Input :
*
* return :
* nothing
*************************/
void wait(int interval) {
int count = interval / 10;
for (int i = 0; i < count; ++i) {
Sleep(10);
// If the user has a key during sleep , Then sleep ends
if (_kbhit()) {
return;
}
}
}①③ Fixed block mark( )
Each time a new square is drawn, judge whether the square can continue to move , If it cannot be moved, it indicates that the block needs to be solidified .
/*****************************************
* function : Block fixation
* Input :
* x,y - Square coordinates
* dir - The square faces
* return :
* nothing
****************************************/
void mark(int x, int y, block_dir_t dir) {
int id = BlockIndex * 4 + dir;
int x2 = (y - MinY) / UNIT_SIZE;
int y2 = (x - MinX) / UNIT_SIZE;
for (int i = 0; i < BLOCK_HEIGHT; ++i) {
for (int j = 0; j < BLOCK_WIDTH; ++j) {
if (block[id][i][j] == 1) {
visit[x2 + i][y2 + j] = 1;
markColor[x2 + i][y2 + j] = color[BlockIndex];
}
}
}
}①④ The user operation framework is perfect Ⅱ mov( )
Add the above implementation functions to the operation framework
void move() {
int x = START_X; // Square start position
int y = START_Y;
int k = 0;
block_dir_t blockDir = (block_dir_t)BLOCK_UP;
int curSpeed = speed; // Define the current square landing speed
// Judge whether the game is over before reading the user's operation
failCheck();
// Keep falling down
while (1) {
int curSpeed = speed; // Define the current square landing speed
// Clear the box
clearBlock(x, k + y, blockDir);
// Judge the direction of choice
if (_kbhit()) {
int key = _getch();
if (key == KEY_SPACE) {
system("pause");
}
else if (key == KEY_UP) {
block_dir_t nextDir = (block_dir_t)((blockDir + 1) % 4);
if (rotatable(x, y + k, nextDir)) {
blockDir = nextDir;
}
}
else if (key == KEY_LEFT) {
if (moveable(x, y + k + 20, MOVE_LEFT, blockDir)) {
x -= UNIT_SIZE;
}
}
else if (key == KEY_RIGHT) {
if (moveable(x, y + k + 20, MOVE_RIGHT, blockDir)) {
x += UNIT_SIZE;
}
}
else if (key == KEY_DOWN) {
curSpeed = 50;
}
}
k += 20;
// Draw box
drawBlock(x, y + k, blockDir);
// Sleep
wait(curSpeed);
// Curing treatment of blocks , After the block is fixed, end the cycle , Of the current box move completion of enforcement
if (!moveable(x, y + k, MOVE_DOWN, blockDir)) {
mark(x, y + k, blockDir);
break;
}
}
}①⑤ Eliminate blocks check( ) + down( )

When the descending operation of a block is completed , Find in the cured block array “ Full line ” square , If there is “ Full line ” The square should be cleared , Then update user scores and grades .
g
/*************************
* function : Check if there is a full line of squares
* Input :
* nothing
* return :
* nothing
*************************/
void check() {
int i, j;
int clearLines = 0;
for (i = 29; i >= 0; i--) {
// Check the i Is the line full
for (j = 0; j < 15 && visit[i][j]; j++);
// At this point , There are two situations :
// 1. The first i The line is not full , That means there is a vacancy here j<15
// 2. The first i The line is full , here j>=15
if (j >= 15) {
// here , The first i The line is full , We need to eliminate i That's ok
down(i); // Eliminate section i That's ok , And move the top lines down
i++; // Because there is... In the outermost cycle i--, So we first i++, Make the next cycle , Check this one again
clearLines++;
}
}
// Update score
addScore(clearLines);
// Update level ( Update level prompt , Update speed )
updateGrade();
}
/*****************************************
* function : Eliminate section i That's ok , And move all the lines down
* Input :
* nothing
* return :
* nothing
****************************************/
void down(int x) {
for (int i = x; i > 0; --i) {
for (int j = 0; j < 15; ++j) {
if (visit[i - 1][j] == 1) {
visit[i][j] = 1;
markColor[i][j] = markColor[i - 1][j];
setcolor(markColor[i][j]);
outtextxy(20 * j + MinX, 20 * i + MinY, "■");
}
else {
visit[i][j] = 0;
setcolor(BLACK);
outtextxy(20 * j + MinX, 20 * i + MinY, "■");
}
}
}
// Clear the top grid
setcolor(BLACK);
for (int j = 0; j < 15; ++j) {
visit[0][j] = 0;
outtextxy(20 * j + MinX, MinY, "■");
}
}
①⑥ Update scores and grades addScore( ) + updateGrade( )
Update the user score and level according to the number of clear block lines .
/*****************************************
* function : Update score
* Input :
* nothing
* return :
* nothing
****************************************/
void addScore(int lines) {
char str[32];
score += lines * 10;
sprintf_s(str, 32, "%d", score);
setcolor(RED);
outtextxy(415, 310, str);
}
/*************************
* function : Update level
* Input :
* nothing
* return :
* nothing
*************************/
void updateGrade() {
// Update level
// hypothesis 50 Level by level
rank = score / 50;
char str[32];
sprintf_s(str, 32, "%d", rank);
setcolor(RED);
outtextxy(415, 405, str);
// Update speed
if (speed <= 100) {
speed = 100;
}
else {
speed = 500 - rank * 20;
}
}Code integration runs

5、 ... and 、 deficiencies
- Use easyX mapping , Import game pictures , So that the game effect is more realistic
- Preservation of game achievements
- The operation control is slightly stuck
边栏推荐
- 【RT-Thread】nxp rt10xx 设备驱动框架之--Audio搭建和使用
- Free data | new library online | cnopendata complete data of China's insurance intermediary outlets
- Loop through JSON object list
- Solution to long waiting time of SSH connection to remote host
- AcWing 4489. 最长子序列
- Life is still confused? Maybe these subscription numbers have the answers you need!
- How do large consumer enterprises make digital transformation?
- One brush 147-force deduction hot question-4 find the median of two positive arrays (H)
- 互联网医院HIS管理平台源码,在线问诊,预约挂号 智慧医院小程序源码
- 一位普通程序员一天工作清单
猜你喜欢

Leetcode 108 converts an ordered array into a binary search tree -- recursive method

How to purchase Google colab members in China

【JokerのZYNQ7020】DDS_ Compiler。

Tensorboard quick start (pytoch uses tensorboard)

Simple use of unity pen XR grab

kubernetes资源对象介绍及常用命令(三)

鸿蒙第四次培训

国内如何购买Google Colab会员

设计电商秒杀

QT adjust win screen brightness and sound size
随机推荐
Simple use of unity pen XR grab
Unity notes unityxr simple to use
【RT-Thread】nxp rt10xx 设备驱动框架之--Audio搭建和使用
POM in idea XML graying solution
Leetcode Valentine's Day Special - looking for a single dog
September, 19, "cam principle and application" online assignment [Full Score answer]
互联网医院HIS管理平台源码,在线问诊,预约挂号 智慧医院小程序源码
AcWing 3438. Number system conversion
[error reporting] omp: error 15: initializing libiomp5md dll, but found libiomp5md. dll already initialized.
Leetcode 538 converts binary search tree into cumulative tree -- recursive method and iterative method
基于主机的入侵系统IDS
UE4 official charging resources, with a total price of several thousand
RedHat 6.2 configuring ZABBIX
Vs2013 has blocked the installer, and ie10 needs to be installed
Redis: operation commands for list type data
企业级自定义表单引擎解决方案(十一)--表单规则引擎1
Introduction to SolidWorks gear design software tool geartrax
Golang unit test, mock test and benchmark test
Host based intrusion system IDS
AcWing 4489. 最长子序列