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;
}