#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#include <windows.h>
#define GRID_WIDTH 10
#define GRID_HEIGHT 20
typedef struct {
int x, y;
} Point;
typedef struct {
Point blocks[4];
Point position;
} Tetromino;
// 定义布尔类型和布尔值
typedef int bool;
#define true 1
#define false 0
Tetromino tetrominoes[7] = {
{{ {0, 0}, {0, 1}, {0, 2}, {0, 3} }, {GRID_WIDTH / 2 - 2, 0}}, // I
{{ {0, 0}, {0, 1}, {1, 0}, {1, 1} }, {GRID_WIDTH / 2 - 1, 0}}, // O
{{ {0, 0}, {1, 0}, {2, 0}, {1, 1} }, {GRID_WIDTH / 2 - 1, 0}}, // T
{{ {0, 1}, {1, 1}, {1, 0}, {2, 0} }, {GRID_WIDTH / 2 - 1, 0}}, // S
{{ {0, 0}, {1, 0}, {1, 1}, {2, 1} }, {GRID_WIDTH / 2 - 1, 0}}, // Z
{{ {0, 1}, {1, 1}, {2, 1}, {2, 0} }, {GRID_WIDTH / 2 - 1, 0}}, // J
{{ {0, 0}, {0, 1}, {1, 1}, {2, 1} }, {GRID_WIDTH / 2 - 1, 0}} // L
};
int grid[GRID_HEIGHT][GRID_WIDTH] = {0};
bool check_collision(Tetromino *tetromino, int offsetX, int offsetY) {
for (int i = 0; i < 4; i++) {
int newX = tetromino->blocks[i].x + tetromino->position.x + offsetX;
int newY = tetromino->blocks[i].y + tetromino->position.y + offsetY;
if (newX < 0 || newX >= GRID_WIDTH || newY < 0 || newY >= GRID_HEIGHT || grid[newY][newX]) {
return true;
}
}
return false;
}
void lock_tetromino(Tetromino *tetromino) {
for (int i = 0; i < 4; i++) {
int x = tetromino->blocks[i].x + tetromino->position.x;
int y = tetromino->blocks[i].y + tetromino->position.y;
grid[y][x] = 1;
}
}
void clear_lines() {
for (int y = 0; y < GRID_HEIGHT; y++) {
bool full = true;
for (int x = 0; x < GRID_WIDTH; x++) {
if (!grid[y][x]) {
full = false;
break;
}
}
if (full) {
for (int i = y; i > 0; i--) {
for (int j = 0; j < GRID_WIDTH; j++) {
grid[i][j] = grid[i-1][j];
}
}
for (int j = 0; j < GRID_WIDTH; j++) {
grid[0][j] = 0;
}
}
}
}
void render_grid() {
for (int y = 0; y < GRID_HEIGHT; y++) {
for (int x = 0; x < GRID_WIDTH; x++) {
if (grid[y][x]) {
printf("#");
} else {
printf(".");
}
}
printf("\n");
}
}
void render_tetromino(Tetromino *tetromino) {
for (int i = 0; i < 4; i++) {
int x = tetromino->blocks[i].x + tetromino->position.x;
int y = tetromino->blocks[i].y + tetromino->position.y;
if (y >= 0) {
COORD pos = { x, y };
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
printf("#");
}
}
}
void rotate_tetromino(Tetromino *tetromino) {
Tetromino temp = *tetromino;
for (int i = 0; i < 4; i++) {
int x = temp.blocks[i].x;
int y = temp.blocks[i].y;
temp.blocks[i].x = y;
temp.blocks[i].y = -x;
}
if (!check_collision(&temp, 0, 0)) {
*tetromino = temp;
}
}
int main() {
srand((unsigned int)time(NULL));
Tetromino current_tetromino = tetrominoes[rand() % 7];
int tick = 0;
bool running = true;
while (running) {
if (_kbhit()) {
switch (_getch()) {
case 'a':
if (!check_collision(¤t_tetromino, -1, 0)) {
current_tetromino.position.x -= 1;
}
break;
case 'd':
if (!check_collision(¤t_tetromino, 1, 0)) {
current_tetromino.position.x += 1;
}
break;
case 's':
if (!check_collision(¤t_tetromino, 0, 1)) {
current_tetromino.position.y += 1;
}
break;
case 'w':
rotate_tetromino(¤t_tetromino);
break;
case 'q':
running = false;
break;
}
}
if (tick == 5) {
if (!check_collision(¤t_tetromino, 0, 1)) {
current_tetromino.position.y += 1;
} else {
lock_tetromino(¤t_tetromino);
clear_lines();
current_tetromino = tetrominoes[rand() % 7];
if (check_collision(¤t_tetromino, 0, 0)) {
running = false;
}
}
tick = 0;
}
// Render
COORD pos = { 0, 0 };
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
render_grid();
render_tetromino(¤t_tetromino);
Sleep(100);
tick++;
}
printf("Game Over!\n");
return 0;
}