俄罗斯方块是一种流行的游戏,其基本玩法是通过随机生成的不同形状的方块,将它们放置在游戏区域中,并尽可能地填满一行或多行。当游戏区域的一行或多行被填满时,这些行将被消除,并且上面的方块将向下移动。如果在游戏过程中方块堆到了游戏区域的顶部,则游戏结束。
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
#include <windows.h>
#define WIDTH 10
#define HEIGHT 20
#define BLOCK_SIZE 4
// 定义游戏区域
int game_area[HEIGHT][WIDTH] = {0};
// 七种方块形状
int blocks[7][4][4] = {
{
{0, 1, 0, 0},
{0, 1, 0, 0},
{0, 1, 0, 0},
{0, 1, 0, 0}
},
{
{0, 1, 1, 0},
{0, 1, 1, 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, 1, 1, 0},
{1, 1, 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, 1, 0},
{1, 1, 1, 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}
}
};
typedef struct {
int x, y;
int block[BLOCK_SIZE][BLOCK_SIZE];
} Tetrimino;
Tetrimino current_piece;
void generate_new_piece() {
int random_block = rand() % 7;
current_piece.x = WIDTH / 2 - 2;
current_piece.y = 0;
memcpy(current_piece.block, blocks[random_block], sizeof(blocks[random_block]));
}
int collision(int dx, int dy) {
for (int y = 0; y < BLOCK_SIZE; y++) {
for (int x = 0; x < BLOCK_SIZE; x++) {
if (current_piece.block[y][x]) {
int nx = current_piece.x + x + dx;
int ny = current_piece.y + y + dy;
if (nx < 0 || nx >= WIDTH || ny >= HEIGHT || game_area[ny][nx]) {
return 1;
}
}
}
}
return 0;
}
void merge_piece_to_game_area() {
for (int y = 0; y < BLOCK_SIZE; y++) {
for (int x = 0; x < BLOCK_SIZE; x++) {
if (current_piece.block[y][x]) {
game_area[current_piece.y + y][current_piece.x + x] = 1;
}
}
}
}
void move_piece(int dx, int dy) {
if (!collision(dx, dy)) {
current_piece.x += dx;
current_piece.y += dy;
}
}
void rotate_piece() {
int rotated_block[BLOCK_SIZE][BLOCK_SIZE] = {0};
for (int y = 0; y < BLOCK_SIZE; y++) {
for (int x = 0; x < BLOCK_SIZE; x++) {
rotated_block[y][x] = current_piece.block[BLOCK_SIZE - x - 1][y];
}
}
if (!collision(0, 0)) {
memcpy(current_piece.block, rotated_block, sizeof(rotated_block));
}
}
void remove_line(int line) {
for (int y = line; y > 0; y--) {
for (int x = 0; x < WIDTH; x++) {
game_area[y][x] = game_area[y - 1][x];
}
}
}
void check_lines() {
for (int y = 0; y < HEIGHT; y++) {
int filled = 1;
for (int x = 0; x < WIDTH; x++) {
if (!game_area[y][x]) {
filled = 0;
break;
}
}
if (filled) {
remove_line(y);
}
}
}
int game_over() {
for (int x = 0; x < WIDTH; x++) {
if (game_area[0][x]) {
return 1;
}
}
return 0;
}
void draw_game_area() {
system("cls");
printf("Tetris\n");
printf("----------\n");
for (int y = 0; y < HEIGHT; y++) {
for (int x = 0; x < WIDTH; x++) {
if (game_area[y][x] == 0 && !(current_piece.y + y >= 0 && current_piece.y + y < HEIGHT && current_piece.x + x >= 0
&& current_piece.x + x < WIDTH && current_piece.block[y][x])) {
printf(" ");
} else {
printf("#");
}
}
printf("\n");
}
printf("----------\n");
}
void update_game() {
static int initialized = 0;
static int speed_counter = 0;
static int speed = 10;
if (!initialized) {
srand(time(NULL));
generate_new_piece();
initialized = 1;
}
if (_kbhit()) {
int key = _getch();
switch (key) {
case 'a':
move_piece(-1, 0);
break;
case 'd':
move_piece(1, 0);
break;
case 's':
move_piece(0, 1);
break;
case 'w':
rotate_piece();
break;
default:
break;
}
}
speed_counter++;
if (speed_counter >= speed) {
speed_counter = 0;
if (!collision(0, 1)) {
current_piece.y++;
} else {
merge_piece_to_game_area();
check_lines();
generate_new_piece();
if (game_over()) {
// 游戏结束
printf("Game Over!\n");
exit(0);
}
}
}
}
int main() {
while (1) {
update_game();
draw_game_area();
Sleep(50);
}
return 0;
}