• 【C++项目实现】俄罗斯方块


    初始化页面

    # include  
    # include  
    
    // 欢迎界面
    void welcome() {
    	// 初始化画布
    	initgraph(550, 660);
    
    	// 设置窗口标题
    	HWND window = GetHWnd(); //获取窗口
    	SetWindowText(window, _T("俄罗斯方块")); //设置窗口标题
    
    	// 设置文本的字体样式
    	setfont(40, 0, _T("微软雅黑"));	//设置文字样式(0表示自适应)
    	setcolor(WHITE);
    	outtextxy(205, 200, _T("俄罗斯方块"));
    
    	setfont(22, 0, _T("楷体"));
    	outtextxy(150, 300, _T("适度游戏益脑,沉迷游戏伤身"));
    
    	Sleep(3000); //睡眠(暂停)3000毫秒,3秒针
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    初始化游戏环境

    int score = 0; // 总分
    int rank = 0;  //等级
    
    // 初始化游戏场景
    void initGameScene()
    {
    	char str[16];
    
    	cleardevice();
    	setcolor(WHITE);
    
    	rectangle(29, 29, 334, 633);
    	rectangle(27, 27, 336, 635);
    	rectangle(370, 50, 515, 195);
    
    	setfont(24, 0, _T("楷体"));
    	setcolor(LIGHTGRAY);
    	outtextxy(405, 215, _T("下一个:"));
    	setcolor(RED);
    	outtextxy(405, 280, _T("分数:"));
    	sprintf(str, "%d", score);
    	outtextxy(415, 310, str);
    	outtextxy(405, 375, _T("等级:"));
    	sprintf(str, "%d", rank);
    	outtextxy(425, 405, str);
    	setfont(22, 0, _T("楷体"));
    
    	setcolor(LIGHTBLUE);
    	outtextxy(390, 475, _T("操作说明:"));
    	outtextxy(390, 500, _T("↑: 旋转"));
    	outtextxy(390, 525, _T("↓: 下降"));
    	outtextxy(390, 550, _T("←: 左移"));
    	outtextxy(390, 575, _T("→: 右移"));
    	outtextxy(390, 600, _T("空格: 暂停"));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    新方块

    #define  BLOCK_COUNT	    5
    #define  BLOCK_WIDTH		5
    #define  BLOCK_HEIGHT  	    5
    #define  UNIT_SIZE		    20  //小砖块的宽度和高度
    
    int color[BLOCK_COUNT] = {
    	GREEN,CYAN,MAGENTA,BROWN,YELLOW
    };
    
    int NextIndex = -1;
    
    int block[BLOCK_COUNT * 4][BLOCK_HEIGHT][BLOCK_WIDTH] = {
    	// | 形方块
    	{ 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 形方块
    	{ 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 },
    
    	// 田 形方块
    	{ 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 形方块
    	{ 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 形方块
    	{ 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 },
    };
    
    //清除右上角提示区方块
    void clearBlock() {
    	setcolor(BLACK);
    	setfont(23, 0, "楷体");
    
    	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, "■");
    		}
    	}
    }
    
    //绘制方块
    void drawBlock(int x, int y) {
    	setcolor(color[NextIndex]);
    	setfont(23, 0, "楷体");
    
    	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, "■");
    			}
    		}
    	}
    }
    
    //右上角提示区显示下一个方块
    void nextblock() {
    	clearBlock(); //清除右上角区域
    
    	//随机选择一种方块
    	srand(time(NULL)); //使用时间函数的返回值,来作为随机种子
    	NextIndex = rand() % BLOCK_COUNT;
    
    	drawBlock(391, 71);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180

    降落方块

    使用访问数组来确定是否有方块

    int visit[30][15], Color[30][15]; // visit[i][j] == 1 表示该位置有方块
    
    • 1

    新方块降落

    int BlockIndex = -1; //当前方块的种类
    
    //新方块降落
    void newblock() {
    	//确定即将使用的方块的类别
    	BlockIndex = NextIndex;
    
    	//绘制刚从顶部下降的方块
    	drawBlock(START_X, START_Y);
    
    	//让新出现的方块暂停一会,让用户识别到
    	Sleep(100); //0.1秒
    
    	//在右上角区域,绘制下一个方块
    	nextblock();
    
    	//方块降落
    	move();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    方块降落

    #define  START_X			130
    #define  START_Y			30
    
    #define KEY_UP			72
    #define	KEY_RIGHT		77
    #define KEY_DOWN		80
    #define KEY_LEFT		75
    #define KEY_SPACE		32
    
    int speed = 500;
    int minX = 30;
    int minY = 30;
    
    int markColor[30][15]; //表示对应位置的颜色
    
    typedef enum {
    	BLOCK_UP,
    	BLOCK_RIGHT,
    	BLOCK_DOWN,
    	BLOCK_LEFT
    } block_dir_t;
    
    typedef enum {
    	MOVE_DOWN,
    	MOVE_LEFT,
    	MOVE_RIGHT
    } move_dir_t;
    
    //调整下降速度
    void wait(int interval) {
    	int count = interval / 10;
    	for (int i = 0; i < count; i++) {
    		Sleep(10);
    		if (kbhit()) {
    			return;
    		}
    	}
    }
    
    //标记已到位的方块
    void mark(int x, int y, int blockIndex, block_dir_t dir) {
    	int id = blockIndex * 4 + dir;
    	int x2 = (y - minY) / 20;
    	int y2 = (x - minX) / 20;
    
    	for (int i = 0; i < 5; i++) {
    		for (int j = 0; j < 5; j++) {
    			if (block[id][i][j] == 1) {
    				visit[x2 + i][y2 + j] = 1;
    				markColor[x2 + i][y2 + j] = color[blockIndex];
    			}
    		}
    	}
    }
    
    //如果在指定位置可以向指定方向移动,就返回1, 否则就返回0
    int moveable(int x0, int y0, move_dir_t moveDir, block_dir_t blockDir) {
    	//计算当前方块的左上角在30x15的游戏区中的位置(第多少行,第多少列)
    	int x = (y0 - minY) / UNIT_SIZE;
    	int y = (x0 - minX) / UNIT_SIZE;
    	int id = BlockIndex * 4 + blockDir;
    	int ret = 1;
    
    	if (moveDir == MOVE_DOWN) {
    		for (int i = 0; i < 5; i++) {
    			for (int j = 0; j < 5; j++) {
    				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 < 5; i++) {
    			for (int j = 0; j < 5; j++) {
    				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 < 5; i++) {
    			for (int j = 0; j < 5; j++) {
    				if (block[id][i][j] == 1 &&
    					(y + j + 1 >= 15 || visit[x + i][y + j + 1] == 1)) {
    					ret = 0;
    				}
    			}
    		}
    	}
    
    	return ret;
    }
    
    //判断当前方块是否可以转向到指定方向
    //注意,此时还没有转到该方向!!!
    int rotatable(int x, int y, block_dir_t dir) {
    	int id = BlockIndex * 4 + dir;
    	int xIndex = (y - minY) / 20;
    	int yIndex = (x - minX) / 20;
     
    	if (!moveable(x, y, MOVE_DOWN, dir)) {
    		return 0;
    	}
    
    	for (int i = 0; i < 5; i++) {
    		for (int j = 0; j < 5; j++) {
    			if (block[id][i][j] == 1 &&
    				(yIndex + j < 0 || yIndex + j >= 15 || visit[xIndex + i][yIndex + j] == 1)) {
    				return 0;
    			}
    		}
    	}
    
    	return 1;
    }
    
    //方块降落
    void move() {
    	int x = START_X;
    	int y = START_Y;
    	int k = 0;
    	block_dir_t  blockDir = BLOCK_UP;
    	int curSpeed = speed;
    
    	//检测游戏是否结束
    	failCheck();
    
    	//持续向下降落
    	while (1) {
    		if (kbhit()) {
    			int key = getch();
    			if (key == KEY_SPACE) {
    				getch();
    			}
    		}
    
    		//清除当前方块
    		clearBlock(x, k, blockDir);
    
    		if (kbhit()) {
    			int key = getch();
    
    			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_DOWN) {
    				curSpeed = 50;
    			}
    			else if (key == KEY_LEFT) {
    				if (moveable(x, y + k + 20, MOVE_LEFT, blockDir)) {
    					x -= 20;
    				}
    			}
    			else if (key == KEY_RIGHT) {
    				if (moveable(x, y + k + 20, MOVE_RIGHT, blockDir)) {
    					x += 20;  //x = x + 20;
    				}
    			}
    		}
    
    		k += 20;
    
    		//绘制当前方块
    		drawBlock(x, y + k, BlockIndex, blockDir);
    
    		wait(curSpeed);	//下降速度
    
    		//方块的“固化”处理
    		if (!moveable(x, y + k, MOVE_DOWN, blockDir)) {
    			mark(x, y + k, BlockIndex, blockDir);
    			break;
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182

    检测结果

    //消除第x行,并把上面的行都下移
    void down(int x) {
    	for (int i = x; i > 0; i--) {
    		//消除第i行,第j列的方格消除
    		for (int j = 0; j < 15; j++) {
    			if (visit[i - 1][j]) {
    				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, "■");
    			}
    		}
    	}
    
    	//清除最顶上的哪一行(就是行标为0的那一行)
    	setcolor(BLACK);
    	for (int j = 0; j < 15; j++) {
    		visit[0][j] = 0;
    		outtextxy(20 * j + minX, minY, "■");
    	}
    }
    
    //更新分数,参数lines表示消除的行数
    void addScore(int lines) {
    	char str[32];
    
    	setcolor(RED);
    	score += lines * 10;
    	sprintf(str, "%d", score);
    	outtextxy(415, 310, str);
    }
    
    //更新等级的提示
    void updateGrade() {
    	//假设:50分一级
    	rank = score / 50;
    	char str[16];
    	sprintf(str, "%d", rank);
    	outtextxy(425, 405, str);
    
    	//更新速度, 等级越高,速度越快,speed越小!
    	//最慢:500, 最快是100
    	speed = 500 - rank * 100;
    	if (speed <= 100) {
    		speed = 100;
    	}
    }
    
    //检查是否有行可以消除
    void check() {
    	int i, j;
    	int clearLines = 0;
    
    	for (i = 29; i >= 0; i--) {
    		//检查第i行有没有满
    		for (j = 0; j < 15 && visit[i][j]; j++);
    
    		//执行到此处时,有两种情况:
    		// 1. 第i行没有满,即表示有空位 此时 j<15
    		// 2. 第i行已满了,此时 j>=15
    		if (j >= 15) {
    			//此时,第i行已经满了,就需要消除第i行
    			down(i);  //消除第i行,并把上面的行都下移
    			i++;  //因为最外层的循环中有 i--, 所以我们先i++, 使得下次循环时,再把这一行检查一下
    			clearLines++;
    		}
    	}
    
    	//更新分数
    	addScore(clearLines);
    
    	//更新等级(更新等级提示,更新速度)
    	updateGrade();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79

    全部代码

    info.h

    #pragma once
    #include "block.h"
    
    #define BLOCK_COUNT		5
    #define BLOCK_WIDTH		5
    #define BLOCK_HEIGHT	5
    int block[BLOCK_COUNT * 4][BLOCK_HEIGHT][BLOCK_WIDTH] = {
    	// |  型方块
    	{
    		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 形方块
    	   { 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 },
    
    	   // 田 形方块
    	   { 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 形方块
    	   { 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 形方块
    	   { 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 }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132

    block.h

    #pragma once
    #include 
    #include 
    #include 
    #include  //kbhit()使用
    #include "info.h"
    
    int score = 0; //总分
    int rank = 0;  //等级
    
    #define UNIT_SIZE       20
    
    #define START_X			130
    #define START_Y			30
    
    #define KEY_UP			72
    #define	KEY_RIGHT		77
    #define KEY_DOWN		80
    #define KEY_LEFT		75
    #define KEY_SPACE		32
    
    int speed = 500;
    int minX = 30;
    int minY = 30;
    
    typedef enum {
    	BLOCK_UP,
    	BLOCK_RIGHT,
    	BLOCK_DOWN,
    	BLOCK_LEFT
    } block_dir_t;
    
    typedef enum {
    	MOVE_DOWN,
    	MOVE_LEFT,
    	MOVE_RIGHT
    } move_dir_t;
    
    int NextIndex = -1;  //下一个方块的种类
    int BlockIndex = -1; //当前方块的种类
    
    int color[BLOCK_COUNT] = {
    	GREEN, CYAN,  MAGENTA, BROWN, YELLOW
    };
    
    int visit[30][15]; //访问数组
    int markColor[30][15]; //表示对应位置的颜色
    
    //欢迎界面
    void welcome();
    
    //初始化游戏场景
    void initGameScene();
    
    //绘制方块
    void drawBlock(int x, int y);
    
    //绘制方块:  在指定位置绘制指定方块的指定方向
    void drawBlock(int x, int y, int blockIndex, block_dir_t dir);
    
    //清除指定位置指定方向的方块
    //参数x: 方块的左上角的x坐标
    //参数y: 方块的左上角在游戏区域内的坐标,距离游戏区域顶部的距离
    void clearBlock(int x, int y, block_dir_t dir);
    
    //右上角提示区显示下一个方块
    void nextblock();
    
    //如果在指定位置可以向指定方向移动,就返回1, 否则就返回0
    int moveable(int x0, int y0, move_dir_t moveDir, block_dir_t blockDir);
    
    //检测游戏是否结束
    void failCheck();
    
    //判断当前方块是否可以转向到指定方向
    //注意,此时还没有转到该方向!!!
    int rotatable(int x, int y, block_dir_t dir);
    
    //调整下降速度
    void wait(int interval);
    
    //标记已到位的方块
    void mark(int x, int y, int blockIndex, block_dir_t dir);
    
    //方块降落
    void move();
    
    //新方块降落
    void newblock();
    
    //消除第x行,并把上面的行都下移
    void down(int x);
    
    //更新分数,参数lines表示消除的行数
    void addScore(int lines);
    
    //更新等级的提示
    void updateGrade();
    
    //检查是否有行可以消除
    void check();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101

    block.cpp

    #include "block.h"
    
    int main() {
    	welcome();
    	initGameScene();
    
    	//产生新方块
    	nextblock();
    	Sleep(500);
    
    	//初始化访问数组
    	memset(visit, 0, sizeof(visit));
    
    	while (1) {
    		newblock();
    
    		//消除满行,并更新分数和速度
    		check();
    	}
    
    	system("pause");
    	closegraph();
    	return 0;
    }
    
    //欢迎界面
    void welcome() {
    	//初始化画布
    	initgraph(550, 660);
    
    	//设置窗口标题
    	HWND window = GetHWnd(); //获取窗口
    	SetWindowText(window, _T("俄罗斯方块")); //设置窗口标题
    
    	//设置文本的字体样式
    	setfont(40, 0, _T("微软雅黑"));
    	setcolor(WHITE);
    	outtextxy(205, 200, _T("俄罗斯方块"));
    
    	setfont(22, 0, _T("楷体"));
    	outtextxy(150, 300, _T("适度游戏益脑,沉迷游戏伤身"));
    
    	Sleep(3000); //睡眠(暂停)3000毫秒,3秒针
    }
    
    //初始化游戏场景
    void initGameScene() {
    	char str[16];
    
    	//清除屏幕
    	cleardevice();
    
    	rectangle(27, 27, 336, 635);
    	rectangle(29, 29, 334, 633);
    	rectangle(370, 50, 515, 195);
    
    	setfont(24, 0, _T("楷体"));
    	setcolor(LIGHTGRAY);
    	outtextxy(405, 215, _T("下一个"));
    
    	setcolor(RED);
    	outtextxy(405, 280, _T("分数"));
    	sprintf(str, "%d", score);
    	outtextxy(415, 310, str);
    
    	outtextxy(405, 375, _T("等级"));
    	sprintf(str, "%d", rank);
    	outtextxy(425, 405, str);
    
    	//操作说明  ↑  ↓ ← →
    	setcolor(LIGHTBLUE);
    	outtextxy(390, 475, "操作说明");
    	outtextxy(390, 500, "↑:旋转");
    	outtextxy(390, 525, "↓: 下降");
    	outtextxy(390, 550, "←: 左移");
    	outtextxy(390, 575, "→: 右移");
    	outtextxy(390, 600, "空格:暂停");
    }
    
    //清除右上角提示区方块
    void clearBlock() {
    	setcolor(BLACK);
    	setfont(23, 0, "楷体");
    
    	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, "■");
    		}
    	}
    }
    
    //绘制方块
    void drawBlock(int x, int y) {
    	setcolor(color[NextIndex]);
    	setfont(23, 0, "楷体");
    
    	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, "■");
    			}
    		}
    	}
    }
    
    //绘制方块:  在指定位置绘制指定方块的指定方向
    void drawBlock(int x, int y, int blockIndex, block_dir_t dir) {
    	setcolor(color[blockIndex]);
    	setfont(23, 0, "楷体");
    	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) {
    				int x2 = x + j * UNIT_SIZE;
    				int y2 = y + i * UNIT_SIZE;
    				outtextxy(x2, y2, "■");
    			}
    		}
    	}
    }
    
    //清除指定位置指定方向的方块
    //参数x: 方块的左上角的x坐标
    //参数y: 方块的左上角在游戏区域内的坐标,距离游戏区域顶部的距离
    void clearBlock(int x, int y, block_dir_t dir) {
    	setcolor(BLACK);
    	int id = BlockIndex * 4 + dir;
    	y += START_Y;
    
    	for (int i = 0; i < 5; i++) {
    		for (int j = 0; j < 5; j++) {
    			if (block[id][i][j] == 1) {
    				//擦除该方块的第i行的第j列
    				outtextxy(x + 20 * j, y + i * 20, "■");
    			}
    		}
    	}
    }
    
    //右上角提示区显示下一个方块
    void nextblock() {
    	clearBlock(); //清除右上角区域
    
    	//随机选择一种方块
    	srand(time(NULL)); //使用时间函数的返回值,来作为随机种子
    	NextIndex = rand() % BLOCK_COUNT;
    
    	drawBlock(391, 71);
    }
    
    //如果在指定位置可以向指定方向移动,就返回1, 否则就返回0
    int moveable(int x0, int y0, move_dir_t moveDir, block_dir_t blockDir) {
    	//计算当前方块的左上角在30x15的游戏区中的位置(第多少行,第多少列)
    	int x = (y0 - minY) / UNIT_SIZE;
    	int y = (x0 - minX) / UNIT_SIZE;
    	int id = BlockIndex * 4 + blockDir;
    	int ret = 1;
    
    	if (moveDir == MOVE_DOWN) {
    		for (int i = 0; i < 5; i++) {
    			for (int j = 0; j < 5; j++) {
    				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 < 5; i++) {
    			for (int j = 0; j < 5; j++) {
    				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 < 5; i++) {
    			for (int j = 0; j < 5; j++) {
    				if (block[id][i][j] == 1 &&
    					(y + j + 1 >= 15 || visit[x + i][y + j + 1] == 1)) {
    					ret = 0;
    				}
    			}
    		}
    	}
    
    	return ret;
    }
    
    //检测游戏是否结束
    void failCheck() {
    	if (!moveable(START_X, START_Y, MOVE_DOWN, BLOCK_UP)) {
    		setcolor(WHITE);
    		setfont(45, 0, "隶体");
    		outtextxy(75, 300, "GAME OVER!");
    		Sleep(1000);
    		system("pause");
    		closegraph();
    		exit(0);
    	}
    }
    
    //判断当前方块是否可以转向到指定方向
    //注意,此时还没有转到该方向!!!
    int rotatable(int x, int y, block_dir_t dir) {
    	int id = BlockIndex * 4 + dir;
    	int xIndex = (y - minY) / UNIT_SIZE;
    	int yIndex = (x - minX) / UNIT_SIZE;
    
    	if (!moveable(x, y, MOVE_DOWN, dir)) {
    		return 0;
    	}
    
    	for (int i = 0; i < 5; i++) {
    		for (int j = 0; j < 5; j++) {
    			if (block[id][i][j] == 1 &&
    				(yIndex + j < 0 || yIndex + j >= 15 || visit[xIndex + i][yIndex + j] == 1)) {
    				return 0;
    			}
    		}
    	}
    
    	return 1;
    }
    
    //调整下降速度
    void wait(int interval) {
    	int count = interval / 10;
    	for (int i = 0; i < count; i++) {
    		Sleep(10);
    		if (kbhit()) {
    			return;
    		}
    	}
    }
    
    //标记已到位的方块
    void mark(int x, int y, int blockIndex, block_dir_t dir) {
    	int id = blockIndex * 4 + dir;
    	int x2 = (y - minY) / 20;
    	int y2 = (x - minX) / 20;
    
    	for (int i = 0; i < 5; i++) {
    		for (int j = 0; j < 5; j++) {
    			if (block[id][i][j] == 1) {
    				visit[x2 + i][y2 + j] = 1;
    				markColor[x2 + i][y2 + j] = color[blockIndex];
    			}
    		}
    	}
    }
    
    //方块降落
    void move() {
    	int x = START_X;
    	int y = START_Y;
    	int k = 0;
    	block_dir_t  blockDir = BLOCK_UP;
    	int curSpeed = speed;
    
    	//检测游戏是否结束
    	failCheck();
    
    	//持续向下降落
    	while (1) {
    		if (kbhit()) {
    			int key = getch();
    			if (key == KEY_SPACE) {
    				getch();
    			}
    		}
    
    		//清除当前方块
    		clearBlock(x, k, blockDir);
    
    		if (kbhit()) {
    			int key = getch();
    
    			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_DOWN) {
    				curSpeed = 50;
    			}
    			else if (key == KEY_LEFT) {
    				if (moveable(x, y + k + 20, MOVE_LEFT, blockDir)) {
    					x -= 20;
    				}
    			}
    			else if (key == KEY_RIGHT) {
    				if (moveable(x, y + k + 20, MOVE_RIGHT, blockDir)) {
    					x += 20;  //x = x + 20;
    				}
    			}
    		}
    
    		k += 20;
    
    		//绘制当前方块
    		drawBlock(x, y + k, BlockIndex, blockDir);
    
    		wait(curSpeed);
    
    		//方块的“固化”处理
    		if (!moveable(x, y + k, MOVE_DOWN, blockDir)) {
    			mark(x, y + k, BlockIndex, blockDir);
    			break;
    		}
    	}
    }
    
    //新方块降落
    void newblock() {
    	//确定即将使用的方块的类别
    	BlockIndex = NextIndex;
    
    	//绘制刚从顶部下降的方块
    	drawBlock(START_X, START_Y);
    
    	//让新出现的方块暂停一会,让用户识别到
    	Sleep(100); //0.1秒
    
    	//在右上角区域,绘制下一个方块
    	nextblock();
    
    	//方块降落
    	move();
    }
    
    //消除第x行,并把上面的行都下移
    void down(int x) {
    	for (int i = x; i > 0; i--) {
    		//消除第i行,第j列的方格消除
    		for (int j = 0; j < 15; j++) {
    			if (visit[i - 1][j]) {
    				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, "■");
    			}
    		}
    	}
    
    	//清除最顶上的哪一行(就是行标为0的那一行)
    	setcolor(BLACK);
    	for (int j = 0; j < 15; j++) {
    		visit[0][j] = 0;
    		outtextxy(20 * j + minX, minY, "■");
    	}
    }
    
    //更新分数,参数lines表示消除的行数
    void addScore(int lines) {
    	char str[32];
    
    	setcolor(RED);
    	score += lines * 10;
    	sprintf(str, "%d", score);
    	outtextxy(415, 310, str);
    }
    
    //更新等级的提示
    void updateGrade() {
    	//假设:50分一级
    	rank = score / 50;
    	char str[16];
    	sprintf(str, "%d", rank);
    	outtextxy(425, 405, str);
    
    	//更新速度, 等级越高,速度越快,speed越小!
    	//最慢:500, 最快是100
    	speed = 500 - rank * 100;
    	if (speed <= 100) {
    		speed = 100;
    	}
    }
    
    //检查是否有行可以消除
    void check() {
    	int i, j;
    	int clearLines = 0;
    
    	for (i = 29; i >= 0; i--) {
    		//检查第i行有没有满
    		for (j = 0; j < 15 && visit[i][j]; j++);
    
    		//执行到此处时,有两种情况:
    		// 1. 第i行没有满,即表示有空位 此时 j<15
    		// 2. 第i行已满了,此时 j>=15
    		if (j >= 15) {
    			//此时,第i行已经满了,就需要消除第i行
    			down(i);  //消除第i行,并把上面的行都下移
    			i++;  //因为最外层的循环中有 i--, 所以我们先i++, 使得下次循环时,再把这一行检查一下
    			clearLines++;
    		}
    	}
    
    	//更新分数
    	addScore(clearLines);
    
    	//更新等级(更新等级提示,更新速度)
    	updateGrade();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
  • 相关阅读:
    Kafka生产与消费示例
    替换Series中的值replace()函数
    LuatOS-SOC接口文档(air780E)--nimble - 蓝牙BLE库(nimble版)
    LeetCode(力扣)406. 根据身高重建队列Python
    如何提高表达能力?这五个方法要掌握
    UTF-8、Unicode编码与汉字的相关内容
    学习 | ANSYS经典界面在压力容器分析设计中的应用
    产品设计的六大要素
    Qt+STK项目配置
    数据库生产架构( 二 ) 分库分表
  • 原文地址:https://blog.csdn.net/Newin2020/article/details/126081562