用 c 语言写俄罗斯方块
时间: 2023-12-31 15:06:42 浏览: 22
好的,下面是一个简单的俄罗斯方块实现,仅供参考:
```c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#include <windows.h>
#define ROW 20 // 游戏区域行数
#define COL 10 // 游戏区域列数
#define BLOCK_SIZE 4 // 方块大小
// 方块类型
enum BlockType {
I_BLOCK, // I型方块
J_BLOCK, // J型方块
L_BLOCK, // L型方块
O_BLOCK, // O型方块
S_BLOCK, // S型方块
T_BLOCK, // T型方块
Z_BLOCK // Z型方块
};
// 方块结构体
struct Block {
int type; // 类型
int x, y; // 左上角坐标
int shape[BLOCK_SIZE][BLOCK_SIZE]; // 形状
};
// 方块数组
struct Block blocks[] = {
// I型方块
{
I_BLOCK,
3, 0,
{
{0, 0, 0, 0},
{1, 1, 1, 1},
{0, 0, 0, 0},
{0, 0, 0, 0},
}
},
// J型方块
{
J_BLOCK,
3, 0,
{
{1, 0, 0},
{1, 1, 1},
{0, 0, 0},
}
},
// L型方块
{
L_BLOCK,
3, 0,
{
{0, 0, 1},
{1, 1, 1},
{0, 0, 0},
}
},
// O型方块
{
O_BLOCK,
4, 0,
{
{1, 1},
{1, 1},
}
},
// S型方块
{
S_BLOCK,
3, 0,
{
{0, 1, 1},
{1, 1, 0},
{0, 0, 0},
}
},
// T型方块
{
T_BLOCK,
3, 0,
{
{0, 1, 0},
{1, 1, 1},
{0, 0, 0},
}
},
// Z型方块
{
Z_BLOCK,
3, 0,
{
{1, 1, 0},
{0, 1, 1},
{0, 0, 0},
}
},
};
// 游戏区域
int board[ROW][COL];
// 判断方块是否超出边界或与其他方块重叠
int is_valid(struct Block block) {
for (int i = 0; i < BLOCK_SIZE; i++) {
for (int j = 0; j < BLOCK_SIZE; j++) {
if (block.shape[i][j] == 1) {
int x = block.x + j, y = block.y + i;
if (x < 0 || x >= COL || y < 0 || y >= ROW) {
return 0; // 超出边界
}
if (board[y][x] == 1) {
return 0; // 与其他方块重叠
}
}
}
}
return 1;
}
// 绘制游戏区域和方块
void draw_board(struct Block block) {
system("cls"); // 清屏
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COL; j++) {
if (board[i][j] == 0) {
printf("□");
} else {
printf("■");
}
}
printf("\n");
}
for (int i = 0; i < BLOCK_SIZE; i++) {
for (int j = 0; j < BLOCK_SIZE; j++) {
if (block.shape[i][j] == 1) {
int x = block.x + j, y = block.y + i;
printf("\033[%d;%dH", y + 1, x * 2 + 1); // 移动光标到指定位置
printf("■");
}
}
}
}
// 初始化游戏区域
void init_board() {
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COL; j++) {
board[i][j] = 0;
}
}
}
// 将方块加入游戏区域
void add_block(struct Block block) {
for (int i = 0; i < BLOCK_SIZE; i++) {
for (int j = 0; j < BLOCK_SIZE; j++) {
if (block.shape[i][j] == 1) {
int x = block.x + j, y = block.y + i;
board[y][x] = 1;
}
}
}
}
// 消除满行
void remove_full_rows() {
int count = 0;
for (int i = ROW - 1; i >= 0; i--) {
int full = 1;
for (int j = 0; j < COL; j++) {
if (board[i][j] == 0) {
full = 0;
break;
}
}
if (full) {
count++;
for (int k = i; k > 0; k--) {
for (int j = 0; j < COL; j++) {
board[k][j] = board[k - 1][j];
}
}
for (int j = 0; j < COL; j++) {
board[0][j] = 0;
}
i++; // 因为当前行已经往下移动了一行,所以需要重新检查这一行
}
}
if (count > 0) {
printf("Score: %d\n", count * 10); // 打印得分
}
}
// 游戏结束
void game_over() {
printf("\033[%d;%dH", ROW + 1, 0); // 移动光标到最后一行
printf("Game over!\n");
exit(0);
}
int main() {
srand((unsigned)time(NULL)); // 初始化随机数种子
init_board(); // 初始化游戏区域
int score = 0; // 得分
while (1) {
struct Block block = blocks[rand() % 7]; // 随机选择一个方块
if (!is_valid(block)) {
game_over();
}
draw_board(block); // 绘制游戏区域和方块
while (1) {
if (_kbhit()) { // 检测是否有按键按下
int key = _getch(); // 获取按键
if (key == 224) { // 方向键
key = _getch();
switch (key) {
case 72: // 上
block.y--;
break;
case 80: // 下
block.y++;
break;
case 75: // 左
block.x--;
break;
case 77: // 右
block.x++;
break;
}
} else if (key == 32) { // 空格键
while (is_valid(block)) {
block.y++;
}
block.y--;
break;
} else if (key == 'q') { // 退出游戏
exit(0);
}
if (!is_valid(block)) { // 检查方块是否合法
switch (key) {
case 72: // 上
block.y++;
break;
case 80: // 下
block.y--;
break;
case 75: // 左
block.x++;
break;
case 77: // 右
block.x--;
break;
}
}
} else { // 方块自动下落
block.y++;
if (!is_valid(block)) { // 检查方块是否合法
block.y--;
add_block(block); // 将方块加入游戏区域
remove_full_rows(); // 消除满行
score += 10;
break;
}
}
draw_board(block); // 绘制游戏区域和方块
}
}
return 0;
}
```
这份代码仅实现了一个简单的俄罗斯方块,如果想增加游戏难度或者添加其他功能,可以根据实际需求进行修改。