1、地图和方块
游戏区域由一个 20x10 的二维数组表示,其中 0 表示空白,1 表示已占用。将方块定义为一个 4x4 的小方阵,这样便于旋转操作。设计多种形状的方块,并用数据结构表示每个方块的形状和位置。使用 map[HEIGHT][WIDTH]
来表示游戏的20x10地图。tetrominoes
数组存储了7种不同形状的方块,每个方块都是4x4的阵列。
#include <stdio.h> #include <stdlib.h> #include <conio.h> #include <windows.h> // 地图大小 #define WIDTH 10 #define HEIGHT 20 // 方块定义(4x4的阵列表示7种不同的方块) int tetrominoes[7][4][4] = { // O 形方块 {{1, 1, 0, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, // I 形方块 {{0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}}, // S 形方块 {{0, 1, 1, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, // Z 形方块 {{1, 1, 0, 0}, {0, 1, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, // L 形方块 {{1, 0, 0, 0}, {1, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}}, // J 形方块 {{0, 0, 1, 0}, {0, 0, 1, 0}, {0, 1, 1, 0}, {0, 0, 0, 0}}, // T 形方块 {{0, 1, 0, 0}, {1, 1, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}} }; // 地图大小 #define WIDTH 10 #define HEIGHT 20 // 地图 int map[HEIGHT][WIDTH] = {0}; // 当前方块的位置 int current_tetromino[4][4]; int current_x, current_y; int tetromino_index; int main() { printf("Hello, World!"); return 0; }
2、方块生成与移动
通过键盘控制方块的左右移动、下落和旋转。spawn_tetromino()
随机生成一个方块。can_move()
用来检查方块能否向指定方向移动。rotate_tetromino()
实现方块的旋转。
#include <stdio.h> #include <stdlib.h> #include <conio.h> #include <windows.h> // 清屏函数 void clear_screen() { system("cls"); } // 随机生成一个方块 void spawn_tetromino() { tetromino_index = rand() % 7; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { current_tetromino[i][j] = tetrominoes[tetromino_index][i][j]; } } current_x = WIDTH / 2 - 2; current_y = 0; } // 检查方块是否能移动 int can_move(int dx, int dy) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (current_tetromino[i][j]) { int new_x = current_x + j + dx; int new_y = current_y + i + dy; if (new_x < 0 || new_x >= WIDTH || new_y >= HEIGHT || map[new_y][new_x]) { return 0; } } } } return 1; } // 旋转方块 void rotate_tetromino() { int temp[4][4]; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { temp[i][j] = current_tetromino[3 - j][i]; } } // 检查是否能旋转 int old_x = current_x, old_y = current_y; if (can_move(0, 0)) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { current_tetromino[i][j] = temp[i][j]; } } } } int main() { printf("Hello, World!"); return 0; }
3、方块固定与行消除
当方块无法下落时,使用 fix_tetromino()
将方块固定在地图上。clear_lines()
检查地图是否有完整的行,如果有就清除该行并将上方的行下移。
#include <stdio.h> #include <stdlib.h> #include <conio.h> #include <windows.h> // 固定方块到地图 void fix_tetromino() { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (current_tetromino[i][j]) { map[current_y + i][current_x + j] = 1; } } } } // 检查并清除完整的行 void clear_lines() { for (int i = 0; i < HEIGHT; i++) { int full_line = 1; for (int j = 0; j < WIDTH; j++) { if (map[i][j] == 0) { full_line = 0; break; } } if (full_line) { for (int k = i; k > 0; k--) { for (int j = 0; j < WIDTH; j++) { map[k][j] = map[k - 1][j]; } } for (int j = 0; j < WIDTH; j++) { map[0][j] = 0; } } } } int main() { printf("Hello, World!"); return 0; }
4、绘制地图
draw()
函数负责在控制台上绘制当前地图和正在下落的方块。
#include <stdio.h> #include <stdlib.h> #include <conio.h> #include <windows.h> // 游戏逻辑循环 void game_loop() { spawn_tetromino(); while (1) { if (_kbhit()) { switch (_getch()) { case 'a': if (can_move(-1, 0)) current_x--; break; case 'd': if (can_move(1, 0)) current_x++; break; case 's': if (can_move(0, 1)) current_y++; break; case 'w': rotate_tetromino(); break; } } if (can_move(0, 1)) { current_y++; } else { fix_tetromino(); clear_lines(); spawn_tetromino(); if (!can_move(0, 0)) { printf("Game Over!\n"); break; } } draw(); Sleep(300); } } int main() { printf("Hello, World!"); return 0; }
5、控制与游戏循环
使用 _kbhit()
和 _getch()
获取玩家输入,支持左右移动 (a, d),快速下落 (s),以及旋转方块 (w)。游戏循环中持续进行方块的下落、绘制和行检测,直到游戏结束。
#include <stdio.h> #include <stdlib.h> #include <conio.h> #include <windows.h> // 游戏逻辑循环 void game_loop() { spawn_tetromino(); while (1) { if (_kbhit()) { switch (_getch()) { case 'a': if (can_move(-1, 0)) current_x--; break; case 'd': if (can_move(1, 0)) current_x++; break; case 's': if (can_move(0, 1)) current_y++; break; case 'w': rotate_tetromino(); break; } } if (can_move(0, 1)) { current_y++; } else { fix_tetromino(); clear_lines(); spawn_tetromino(); if (!can_move(0, 0)) { printf("Game Over!\n"); break; } } draw(); Sleep(300); } } int main() { printf("Hello, World!"); return 0; }
6、完整代码
一个简易的俄罗斯方块游戏,可以根据自己的需求进行扩展和完善。
#include <stdio.h> #include <stdlib.h> #include <conio.h> #include <windows.h> // 地图大小 #define WIDTH 10 #define HEIGHT 20 // 方块定义(4x4的阵列表示7种不同的方块) int tetrominoes[7][4][4] = { // O 形方块 {{1, 1, 0, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, // I 形方块 {{0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}, {0, 1, 0, 0}}, // S 形方块 {{0, 1, 1, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, // Z 形方块 {{1, 1, 0, 0}, {0, 1, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, // L 形方块 {{1, 0, 0, 0}, {1, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}}, // J 形方块 {{0, 0, 1, 0}, {0, 0, 1, 0}, {0, 1, 1, 0}, {0, 0, 0, 0}}, // T 形方块 {{0, 1, 0, 0}, {1, 1, 1, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}} }; // 地图 int map[HEIGHT][WIDTH] = {0}; // 当前方块的位置 int current_tetromino[4][4]; int current_x, current_y; int tetromino_index; // 清屏函数 void clear_screen() { system("cls"); } // 随机生成一个方块 void spawn_tetromino() { tetromino_index = rand() % 7; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { current_tetromino[i][j] = tetrominoes[tetromino_index][i][j]; } } current_x = WIDTH / 2 - 2; current_y = 0; } // 检查方块是否能移动 int can_move(int dx, int dy) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (current_tetromino[i][j]) { int new_x = current_x + j + dx; int new_y = current_y + i + dy; if (new_x < 0 || new_x >= WIDTH || new_y >= HEIGHT || map[new_y][new_x]) { return 0; } } } } return 1; } // 旋转方块 void rotate_tetromino() { int temp[4][4]; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { temp[i][j] = current_tetromino[3 - j][i]; } } // 检查是否能旋转 int old_x = current_x, old_y = current_y; if (can_move(0, 0)) { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { current_tetromino[i][j] = temp[i][j]; } } } } // 固定方块到地图 void fix_tetromino() { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (current_tetromino[i][j]) { map[current_y + i][current_x + j] = 1; } } } } // 检查并清除完整的行 void clear_lines() { for (int i = 0; i < HEIGHT; i++) { int full_line = 1; for (int j = 0; j < WIDTH; j++) { if (map[i][j] == 0) { full_line = 0; break; } } if (full_line) { for (int k = i; k > 0; k--) { for (int j = 0; j < WIDTH; j++) { map[k][j] = map[k - 1][j]; } } for (int j = 0; j < WIDTH; j++) { map[0][j] = 0; } } } } // 打印地图和当前方块 void draw() { clear_screen(); for (int i = 0; i < HEIGHT; i++) { for (int j = 0; j < WIDTH; j++) { if (map[i][j]) { printf("#"); } else { int is_part_of_tetromino = 0; for (int m = 0; m < 4; m++) { for (int n = 0; n < 4; n++) { if (current_tetromino[m][n] && current_y + m == i && current_x + n == j) { is_part_of_tetromino = 1; } } } if (is_part_of_tetromino) { printf("O"); } else { printf(" "); } } } printf("\n"); } } // 游戏逻辑循环 void game_loop() { spawn_tetromino(); while (1) { if (_kbhit()) { switch (_getch()) { case 'a': if (can_move(-1, 0)) current_x--; break; case 'd': if (can_move(1, 0)) current_x++; break; case 's': if (can_move(0, 1)) current_y++; break; case 'w': rotate_tetromino(); break; } } if (can_move(0, 1)) { current_y++; } else { fix_tetromino(); clear_lines(); spawn_tetromino(); if (!can_move(0, 0)) { printf("Game Over!\n"); break; } } draw(); Sleep(300); } } int main() { srand(time(0)); game_loop(); return 0; }