本文介绍的是我空闲时间用C语言写的一个俄罗斯方块游戏,整个程序只有一个文件,实现了基本的游戏功能,但还是有些缺陷,希望有心之士能够继续完善,感谢各位!
请注意!a、d、s、w都是小写
/*
author: New_Teen
time: 2023.11.2 20:14 周四
IDE: visual studio 2019
俄罗斯方块
*/
#include
#include
#include
#include
#include
#include
#define BOARD_CUBE ' '
#define WIDTH 15
#define HEIGHT 15
#define FLUSH_RATE 200
char curr_cube;
int curr_square;
int curr_x, curr_y;
int score = 0;
int start_number = 0;
char board[HEIGHT][WIDTH];
int tmp[4][2];
int square[5][4][4] = { {{1,0,0,0},
{1,0,0,0},
{1,0,0,0},
{1,0,0,0}},
{{1,0,0,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}},
{{1,1,0,0},
{1,1,0,0},
{0,0,0,0},
{0,0,0,0}},
{{0,1,0,0},
{1,1,0,0},
{1,0,0,0},
{0,0,0,0}} };
void init_board(); //初始化游戏面板
void clear_board(); //清空控制台
void delay_board(); //延时
void print_board(); //打印游戏面板
void init_square(); //初始化方块
void drop_square(); //方块默认下落
void update_board(); //更新游戏面板
bool is_collision_left(); //检测方块左侧是否碰撞
bool is_collision_right(); //检测方块右侧是否碰撞
bool is_collision_bottom(); //检测方块下方是否碰撞
bool is_collsion_rotate(); //检测方块是否可以旋转
bool is_game_over(); //检测游戏是否结束
void rotate(); //旋转方块
void rush_board(); //消除成层方块(得分)
void start_game(); //游戏开始面板
int main() {
srand((unsigned)time(NULL)); //根据程序执行时间产生随机数种子
start_game();
init_board();
while (1) {
init_square();
if (is_game_over())
break;
for (;;) {
if (!is_collision_bottom())
drop_square();
else
break;
if (_kbhit()) {
char ch = _getch();
if (ch == 'a' && !is_collision_left())
curr_x--;
else if (ch == 'd' && !is_collision_right())
curr_x++;
else if (ch == 's' && !is_collision_bottom())
curr_y++;
else if (ch == 'w' && !is_collsion_rotate())
rotate();
}
update_board();
rush_board();
print_board();
delay_board();
clear_board();
}
}
printf("Game over!!\nYour score is %d\n", score);
return 0;
}
void init_board() {
for (int i = 0; i < HEIGHT; ++i)
for (int j = 0; j < WIDTH; ++j)
board[i][j] = BOARD_CUBE;
}
void clear_board() {
system("cls");
}
void delay_board() {
Sleep(FLUSH_RATE);
}
void print_board() {
for (int i = 0; i < HEIGHT; ++i) {
for (int j = 0; j < WIDTH; ++j)
putchar(board[i][j]);
puts("#");
}
puts("################");
printf("score: %d\n", score);
}
void init_square() {
curr_cube = "ABCDEFGH"[rand()%8];
start_number == 1 ? curr_square = 0 : curr_square = rand() % 5;
curr_x = WIDTH / 2, curr_y = -4;
int count = 0;
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
if (square[curr_square][i][j]) {
tmp[count][0] = curr_y + i;
tmp[count][1] = curr_x + j;
count++;
}
}
void drop_square() {
curr_y++;
}
void update_board() {
//清除之前位置的方块
int row, col;
for (int i = 0; i < 4; ++i) {
row = tmp[i][0];
col = tmp[i][1];
if (row >= 0 && row < HEIGHT
&& col >= 0 && col < WIDTH)
board[row][col] = BOARD_CUBE;
}
int count = 0;
//画出现在位置的方块,并更新tmp
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
row = curr_y + i;
col = curr_x + j;
if (square[curr_square][i][j]) {
tmp[count][0] = row;
tmp[count][1] = col;
count++;
if (row >= 0 && row < HEIGHT
&& col >= 0 && col < WIDTH)
board[row][col] = curr_cube;
}
}
}
}
bool is_collision_left() {
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
if (square[curr_square][i][j]) {
//检测方块与面板左墙壁的碰撞
if (curr_x + j <= 0)
return true;
//检测方块与左侧方块的碰撞
if (j == 0) {
if (board[curr_y + i][curr_x + j - 1] != BOARD_CUBE)
return true;
}
else {
if (!square[curr_square][i][j - 1] &&
board[curr_y + i][curr_x + j - 1] != BOARD_CUBE)
return true;
}
}
return false;
}
bool is_collision_right() {
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
if (square[curr_square][i][j]) {
//检测方块与面板右墙壁的碰撞
if (curr_x + j >= WIDTH-1)
return true;
//检测方块与右侧方块的碰撞
if (j == 3) {
if (board[curr_y + i][curr_x + j + 1] != BOARD_CUBE)
return true;
}
else {
if (!square[curr_square][i][j + 1] &&
board[curr_y + i][curr_x + j + 1] != BOARD_CUBE)
return true;
}
}
return false;
}
bool is_collision_bottom() {
//找到当前方块的最下层
int low = -99;
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
if (square[curr_square][i][j] == 1)
low = i;
//如果达到面板最底部
if(curr_y + low >= HEIGHT-1)
return true;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
//考虑方块下面有方块的情况
if (i < 3) {
if (square[curr_square][i][j] && !square[curr_square][i + 1][j]
&& (curr_y + i + 1 >=0) && board[curr_y + i + 1][curr_x + j] != BOARD_CUBE)
return true;
}
else {
if (square[curr_square][i][j] && (curr_y + i + 1 >= 0)
&& board[curr_y + i + 1][curr_x + j] != BOARD_CUBE)
return true;
}
}
}
return false;
}
bool is_collsion_rotate() {
int middle[4][4] = { 0 };
//暂存旋转后方块
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
middle[i][j] = square[curr_square][j][i];
//旋转后方块是否与面板已有方块重叠
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
if (!square[curr_square][i][j] && middle[i][j]
&& board[curr_y + i][curr_x + j] != BOARD_CUBE)
return true;
return false;
}
void rotate() {
//清除之前位置的方块
int row, col;
for (int i = 0; i < 4; ++i) {
row = tmp[i][0];
col = tmp[i][1];
if (row >= 0 && row < HEIGHT
&& col >= 0 && col < WIDTH)
board[row][col] = BOARD_CUBE;
}
//旋转方块
int rotate_tmp[4][4] = { 0 };
memcpy(rotate_tmp, square[curr_square], 16 * sizeof(int));
for (int i = 0; i < 4; ++i)
for (int j = 0; j < 4; ++j)
square[curr_square][i][j] = rotate_tmp[j][i];
int count = 0;
//画出现在位置的方块,并更新tmp
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
row = curr_y + i;
col = curr_x + j;
if (square[curr_square][i][j]) {
tmp[count][0] = row;
tmp[count][1] = col;
count++;
if (row >= 0 && row < HEIGHT
&& col >= 0 && col < WIDTH)
board[row][col] = curr_cube;
}
}
}
}
bool is_game_over() {
for (int j = 0; j < WIDTH; ++j)
if (board[0][j] != BOARD_CUBE)
return true;
return false;
}
void rush_board() {
int count, floor;
floor = 0;
for (int i = HEIGHT - 1; i >= 0; --i) {
count = 0;
for (int j = 0; j < WIDTH; ++j)
if (board[i][j] != BOARD_CUBE)
count++;
if (count == WIDTH)
floor++;
else
break;
}
//得到floor后,面板下移floor层
if (floor != 0) {
for (int i = HEIGHT - 1 - floor; i >= 0; --i)
for (int j = 0; j < WIDTH; ++j)
board[i + floor][j] = board[i][j];
score += floor;
}
}
void start_game() {
printf("----------------俄罗斯方块----------------\n");
printf("\n游戏规则:a:左移 d:右移 s:下移 w:旋转\n");
printf("\n输入1:全程长条方块 输入2:经典随机方块\n");
while (start_number != 1 && start_number != 2) {\
printf("\n请输入序号(1或者2): ");
scanf_s("%d", &start_number);
}
clear_board();
}