C语言实现——俄罗斯方块小游戏

俄罗斯方块是一种流行的游戏,其基本玩法是通过随机生成的不同形状的方块,将它们放置在游戏区域中,并尽可能地填满一行或多行。当游戏区域的一行或多行被填满时,这些行将被消除,并且上面的方块将向下移动。如果在游戏过程中方块堆到了游戏区域的顶部,则游戏结束。

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


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT大鸵鸟

你的鼓励是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值