diff --git "a/\344\277\204\347\275\227\346\226\257\346\226\271\345\235\227.c" "b/\344\277\204\347\275\227\346\226\257\346\226\271\345\235\227.c" new file mode 100644 index 0000000000000000000000000000000000000000..7c0aee630f4a3f785dc1c5a39b51bf69c007d43d --- /dev/null +++ "b/\344\277\204\347\275\227\346\226\257\346\226\271\345\235\227.c" @@ -0,0 +1,470 @@ +#include +#include +#include +#define HEIGHT 28 //设置地图高度 +#define WIDTH 20 //设置地图宽度 +#define ZERO 1 +#define HEIGHT_1 18 +#define Loca_y 6 +#define Loca_x 25 +#define PRINTF printf("■"); +#define LINE printf("\n"); +#define EMPTY printf(" "); +typedef struct Tetris +{ + int x_1, y_1; //主x坐标,主y坐标 + int x_2, y_2; + int x_3, y_3; + int x_4, y_4; + int code;//7种模型代号 + Tetris * next; +}Tetris; +void DeawMap(); //绘制地图 +Tetris * BlockRand(int code); //随机方块生成(先生成主方块,再补齐其他方块) +void JudgeDirection(Tetris ** Block); //按键响应 +void Form(Tetris ** Block); //形态变换 +void ShowBlock(Tetris ** Block); //显示完整方块 +int JudgeWall(Tetris ** Block); //判断左右界限,只需要最左边和最右边即可,以及接触 +void MoveCursor(int x, int y); //移动光标 +void SetColour(int c); //颜色设定 +int JudgeGroud(Tetris * Phead, Tetris ** Block);//判断落地,同样这里需要检测19种形态 若落地经行下一个方块的刷新 +void JudgeEntire(Tetris * Head); //判断整行是否填满,若填满则清除该行 +void NewEntire(Tetris * head, int y); //若上面函数执行清行,则刷新该行上面地图 +void Show(int n); //显示附加信息 +void Location(Tetris ** Block, int x, int y, int a, int b, int c, int d, int e, int f); //确定其他三个方块位置 +void Location_y(Tetris ** Block, int x, int y, int a, int b, int c, int d, int e, int f); //坐标更新 +void Location_x(int x, int y, int a, int b, int c, int d, int e, int f); +Tetris *Phead = NULL; +Tetris *Pend = NULL; +Tetris * Return = NULL; +int form = 0; //判断形态 +int UP = 0; //下降速度判断 +int code_y = 0; +int fengs = 0; +int main() +{ + DeawMap(); + code_y = rand() % 7 + 1; + while (1) + { + Return = BlockRand(code_y); + code_y = rand() % 7 + 1; + Show(code_y); + ShowBlock(&Return); + } + system("pause>nul"); + return 0; +} +void DeawMap() +{ + for (int i = 0; i < WIDTH; i++)PRINTF LINE //上边框 + for (int i = 1; i < HEIGHT - 1; i++) //打印左右边框 + { + for (int j = 0; j < WIDTH; j++) + { + if (j == 0 || j == WIDTH - 1) + { + PRINTF + if (j == WIDTH - 1)LINE + } + else EMPTY + } + } + for (int i = 0; i < WIDTH; i++)PRINTF LINE //下边框 + system("color 03"); +} +void Location(Tetris ** Block, int x, int y, int a, int b, int c, int d, int e, int f) +{ + (*Block)->x_1 = (*Block)->x_1 + x; + (*Block)->y_1 = (*Block)->y_1 + y; + (*Block)->x_2 = (*Block)->x_1 + a; + (*Block)->y_2 = (*Block)->y_1 + b; + (*Block)->x_3 = (*Block)->x_1 + c; + (*Block)->y_3 = (*Block)->y_1 + d; + (*Block)->x_4 = (*Block)->x_1 + e; + (*Block)->y_4 = (*Block)->y_1 + f; +} +void Location_y(Tetris ** Block, int x, int y, int a, int b, int c, int d, int e, int f) +{ + (*Block)->x_1 = (*Block)->x_1 + x; + (*Block)->y_1 = (*Block)->y_1 + y; + (*Block)->x_2 = (*Block)->x_2 + a; + (*Block)->y_2 = (*Block)->y_2 + b; + (*Block)->x_3 = (*Block)->x_3 + c; + (*Block)->y_3 = (*Block)->y_3 + d; + (*Block)->x_4 = (*Block)->x_4 + e; + (*Block)->y_4 = (*Block)->y_4 + f; +} +Tetris * BlockRand(int code_y) +{ + srand((int)time(0)); + Tetris * Block = (Tetris*)malloc(sizeof(Tetris)); + Block->x_1 = 8; + Block->y_1 = 4;//规定初始中心方块的坐标为(8,4) + Block->code = code_y; + if (Phead == NULL)Phead = Block; + else Pend->next = Block; + Block->next = NULL; + Pend = Block; + return Block; +} +void ShowBlock(Tetris ** Block) +{ + while (1) + { + //在打印方块之前,坐标刷新,形态变换要检测完毕 + Form(&Return); //无按键状态 + if ((*Block)->code == 1)SetColour(13); + if ((*Block)->code == 2)SetColour(15); + if ((*Block)->code == 3)SetColour(12); + if ((*Block)->code == 4)SetColour(10); + if ((*Block)->code == 5)SetColour(6); + if ((*Block)->code == 6)SetColour(4); + if ((*Block)->code == 7)SetColour(8); + MoveCursor((*Block)->x_1, (*Block)->y_1); PRINTF + MoveCursor((*Block)->x_2, (*Block)->y_2); PRINTF + MoveCursor((*Block)->x_3, (*Block)->y_3); PRINTF + MoveCursor((*Block)->x_4, (*Block)->y_4); PRINTF + if (JudgeGroud(Phead, &Return) == 0) + { + system("color 03"); + break; + } + if (UP == 0) + { + for (int i = 0; i <= 400000000; i++) {} + } + if (UP == 1) + { + for (int i = 0; i <= 40000000; i++) {} + UP = 0; + } + MoveCursor((*Block)->x_1, (*Block)->y_1); EMPTY + MoveCursor((*Block)->x_2, (*Block)->y_2); EMPTY + MoveCursor((*Block)->x_3, (*Block)->y_3); EMPTY + MoveCursor((*Block)->x_4, (*Block)->y_4); EMPTY + Location_y(&Return, 0, 1, 0, 1, 0, 1, 0, 1); + JudgeDirection(&Return); + JudgeEntire(Phead); + } +} +void JudgeDirection(Tetris ** Block) +{ + if (GetAsyncKeyState(VK_UP) && 0x8000) + { + form += 1; + if (form == 4) + { + form = 0; + } + Form(&Return); + } + if (GetAsyncKeyState(VK_DOWN) && 0x8000) + { + //加速向下 时间加速 + UP = 1; + } + if (GetAsyncKeyState(VK_LEFT) && 0x8000) + { + //向左移动 + if (JudgeWall(&Return) != -1) Location_y(&Return, -1, 0, -1, 0, -1, 0, -1, 0); + } + if (GetAsyncKeyState(VK_RIGHT) && 0x8000) + { + //向右移动 + if (JudgeWall(&Return) != -2) Location_y(&Return, 1, 0, 1, 0, 1, 0, 1, 0); + } + if (GetAsyncKeyState(VK_ESCAPE) && 0x0D) + { + MoveCursor(27, 15); + printf("游戏暂停"); + //判断Esc + while (1) + { + if (GetAsyncKeyState(VK_ESCAPE) && 0x0D) + { + MoveCursor(27, 15); + printf(" "); + break; + } + } + } +} +void Form(Tetris ** Block) +{ + //先确实哪一类,再细分 + switch ((*Block)->code) + { + case 1: + if (form == 0)Location(&Return, 0, 0, -1, 0, 0, -1, 1, 0); + if (form == 1)Location(&Return, 0, 0, 0, 1, 0, -1, 1, 0); + if (form == 2)Location(&Return, 0, 0, 0, 1, -1, 0, 1, 0); + if (form == 3)Location(&Return, 0, 0, 0, 1, -1, 0, 0, -1); + break; + case 2: + Location(&Return, 0, 0, 1, 0, 0, 1, 1, 1); + break; + case 3: + if (form == 0 || form == 2)Location(&Return, 0, 0, 0, -1, 0, 1, 0, 2); + if (form == 1 || form == 3)Location(&Return, 0, 0, -1, 0, 1, 0, 2, 0); + break; + case 4: + if (form == 0)Location(&Return, 0, 0, -1, 0, 1, 0, 1, -1); + if (form == 1)Location(&Return, 0, 0, 0, -1, 1, 0, 0, -2); + if (form == 2)Location(&Return, 0, 0, 0, -1, 1, -1, 2, -1); + if (form == 3)Location(&Return, 0, 0, 0, -1, 0, -2, -1, -2); + break; + case 5: + if (form == 0)Location(&Return, 0, 0, 1, 0, 2, 0, 0, -1); + if (form == 1)Location(&Return, 0, 0, 1, 0, 1, -1, 1, -2); + if (form == 2)Location(&Return, 0, 0, 1, 0, 2, 0, 2, 1); + if (form == 3)Location(&Return, 0, 0, 1, 0, 0, 1, 0, 2); + break; + case 6: + if (form == 0 || form == 2)Location(&Return, 0, 0, 0, -1, 1, 0, 1, 1); + if (form == 1 || form == 3)Location(&Return, 0, 0, 0, -1, 1, -1, -1, 0); + break; + case 7: + if (form == 0 || form == 2)Location(&Return, 0, 0, 0, 1, 1, 0, 1, -1); + if (form == 1 || form == 3)Location(&Return, 0, 0, 0, 1, -1, 0, 1, 1); + } +} +void MoveCursor(int x, int y)//设置光标位置(就是输出显示的开始位置) +{ + COORD pos = { x * 2,y }; + HANDLE output = GetStdHandle(STD_OUTPUT_HANDLE);//获得 标准输出的句柄 + SetConsoleCursorPosition(output, pos); //设置控制台光标位置 +} +void SetColour(int c) +{ + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c);//API函数可以改变控制台颜色 +} +int JudgeWall(Tetris ** Block) +{ + if ((*Block)->x_1 == ZERO || (*Block)->x_2 == ZERO || (*Block)->x_3 == ZERO || (*Block)->x_4 == ZERO)return -1; + if ((*Block)->x_1 == HEIGHT_1 || (*Block)->x_2 == HEIGHT_1 || (*Block)->x_3 == HEIGHT_1 || (*Block)->x_4 == HEIGHT_1)return -2; + return 0; +} +int JudgeGroud(Tetris * Phead, Tetris ** Block) +{ + //如果到达最低层。直接经行下一循环 + Tetris * P = Phead; + if ((*Block)->y_1 == 26 || (*Block)->y_2 == 26 || (*Block)->y_3 == 26 || (*Block)->y_4 == 26)return 0; + while (P->next != NULL) + { + if (P->y_1 == (*Block)->y_1 + 1) + { + if (P->x_1 == (*Block)->x_1)return 0; + } + if (P->y_2 == (*Block)->y_1 + 1) + { + if (P->x_2 == (*Block)->x_1)return 0; + } + if (P->y_3 == (*Block)->y_1 + 1) + { + if (P->x_3 == (*Block)->x_1)return 0; + } + if (P->y_4 == (*Block)->y_1 + 1) + { + if (P->x_4 == (*Block)->x_1)return 0; + } + if (P->y_1 == (*Block)->y_2 + 1) + { + if (P->x_1 == (*Block)->x_2)return 0; + } + if (P->y_2 == (*Block)->y_2 + 1) + { + if (P->x_2 == (*Block)->x_2)return 0; + } + if (P->y_3 == (*Block)->y_2 + 1) + { + if (P->x_3 == (*Block)->x_2)return 0; + } + if (P->y_4 == (*Block)->y_2 + 1) + { + if (P->x_4 == (*Block)->x_2)return 0; + } + if (P->y_1 == (*Block)->y_3 + 1) + { + if (P->x_1 == (*Block)->x_3)return 0; + } + if (P->y_2 == (*Block)->y_3 + 1) + { + if (P->x_2 == (*Block)->x_3)return 0; + } + if (P->y_3 == (*Block)->y_3 + 1) + { + if (P->x_3 == (*Block)->x_3)return 0; + } + if (P->y_4 == (*Block)->y_3 + 1) + { + if (P->x_4 == (*Block)->x_3)return 0; + } + if (P->y_1 == (*Block)->y_4 + 1) + { + if (P->x_1 == (*Block)->x_4)return 0; + } + if (P->y_2 == (*Block)->y_4 + 1) + { + if (P->x_2 == (*Block)->x_4)return 0; + } + if (P->y_3 == (*Block)->y_4 + 1) + { + if (P->x_3 == (*Block)->x_4)return 0; + } + if (P->y_4 == (*Block)->y_4 + 1) + { + if (P->x_4 == (*Block)->x_4)return 0; + } + P = P->next; + } + return 1; +} +void JudgeEntire(Tetris * Head) +{ + Tetris * PHead = Head; + //从1到26 + for (int y = 26; y >= 1; y--) + { + int sum = 0; + while (PHead->next != NULL) + { + if (PHead->y_1 == y)sum++; + if (PHead->y_2 == y)sum++; + if (PHead->y_3 == y)sum++; + if (PHead->y_4 == y)sum++; + MoveCursor(20, 28); + PHead = PHead->next; + } + PHead = Head; + if (sum == 18) + { + //如果成行则,执行NewEntire() 清空该行,并将所有y下降一个单位。 + NewEntire(Phead, y); + fengs += 10; + Show(code_y); + } + sum = 0; + } +} +void NewEntire(Tetris * head,int y) +{ + Tetris * PHead = head; + while (PHead->next != NULL) + { + if (PHead->y_1 == y) + { + MoveCursor(PHead->x_1, PHead->y_1); EMPTY + PHead->x_1 = 99; + PHead->y_1 = 99; + } + if (PHead->y_2 == y) + { + MoveCursor(PHead->x_2, PHead->y_2); EMPTY + PHead->x_2 = 99; + PHead->y_2 = 99; + } + if (PHead->y_3 == y) + { + MoveCursor(PHead->x_3, PHead->y_3); EMPTY + PHead->x_3 = 99; + PHead->y_3 = 99; + } + if (PHead->y_4 == y) + { + MoveCursor(PHead->x_4, PHead->y_4); EMPTY + PHead->x_4 = 99; + PHead->y_4 = 99; + } + PHead = PHead->next; + } + PHead = head; + while (PHead->next != NULL) + { + if (PHead->y_1 < y) + { + MoveCursor(PHead->x_1, PHead->y_1); EMPTY + PHead->y_1 += 1; + MoveCursor(PHead->x_1, PHead->y_1); PRINTF + } + if (PHead->y_2 < y) + { + MoveCursor(PHead->x_2, PHead->y_2); EMPTY + PHead->y_2 += 1; + MoveCursor(PHead->x_2, PHead->y_2); PRINTF + } + if (PHead->y_3 < y) + { + MoveCursor(PHead->x_3, PHead->y_3); EMPTY + PHead->y_3 += 1; + MoveCursor(PHead->x_3, PHead->y_3); PRINTF + } + if (PHead->y_4 < y) + { + MoveCursor(PHead->x_4, PHead->y_4); EMPTY + PHead->y_4 += 1; + MoveCursor(PHead->x_4, PHead->y_4); PRINTF + } + PHead = PHead->next; + } +} +void Show(int n) +{ + //显示下一个方块 + //先清空该区域 + for (int j = 4; j <= 8; j++) + { + for (int i = 23; i <= 28; i++) + { + MoveCursor(i, j); EMPTY + } + } + MoveCursor(24, 3); + printf("下一个方块种类:"); + MoveCursor(24, 10); + printf("游戏得分:%d", fengs); + MoveCursor(24, 12); + printf("花狗Fdog出品,必属精品。"); + if (n == 1) + { + SetColour(13); + Location_x(-1, 0, 0, 0, 1, 0, -1, -1); + } + if (n == 2) + { + SetColour(15); + Location_x(0, 0, 1, 0, -1, 1, 1, 1); + } + if (n == 3) + { + SetColour(12); + Location_x(0, 0, 1, 0, 2, 0, 3, 0); + } + if (n == 4) + { + SetColour(10); + Location_x(0, 0, 1, 0, 2, 0, 2, -1); + } + if (n == 5) + { + SetColour(6); + Location_x(0, -1, 0, 0, 1, 0, 2, 0); + } + if (n == 6) + { + SetColour(4); + Location_x(-1, -1, -1, 0, 0, 0, 0, 1); + } + if (n == 7) + { + SetColour(8); + Location_x(0, -1, 0, 0, -1, 0, -1, 1); + } +} +void Location_x(int x, int y, int a, int b, int c, int d, int e, int f) +{ + MoveCursor(Loca_x+x, Loca_y+y); PRINTF + MoveCursor(Loca_x+a, Loca_y+b); PRINTF + MoveCursor(Loca_x+c, Loca_y+d); PRINTF + MoveCursor(Loca_x+e, Loca_y+f); PRINTF +} \ No newline at end of file