目录
一、前言
二、需求分析
2.1 产品需求概述
2.1.1 功能简介
2.1.2 运行环境
2.2 功能需求
2.2.1 绘制地图
2.2.2 生成随机方块
2.2.3 按键响应
2.2.4 预览方块
2.2.5 分数累加
三、概要设计
3.1 系统体系结构图
3.2 模块描述
四、详细设计
4.1 系统主要函数说明
4.1.1 函数DeawMap
4.1.2 函数Tetris*BlockRand
4.1.3 函数JudgeDirection
4.1.4 函数Form
4.1.5 函数ShowBlock
4.1.6 函数JudgeWall
4.1.7 函数MoveCursor
4.1.8 函数SetColour
4.1.9 函数JudgeGroud
4.1.10 函数JudgeEntire
4.1.11 函数Show
4.1.12 函数Location
五、系统测试
5.1 初始界面
5.2 控制方块
5.3 控制方块旋转
六、程序设计
一、前言
俄罗斯方块游戏,是俄罗斯人阿莱克斯·帕伊特诺夫在八十年代末制作一款游戏,以其规则简单,容易上手,游戏过程变化无穷,已经成为一个家喻户晓老少皆宜的大众游戏。该程序是完成一个简易的俄罗斯方块的任务,其通过结构体、指针、绘图等方面的知识完成几个重要的功能:界面,方块下落,旋转,判断是否还能下落,左右移动,分数,速度设置,清除满的每行,下个方块的预览等。
二、需求分析
2.1 产品需求概述
2.1.1 功能简介
该程序是完成一个简易的俄罗斯方块的任务,规则简单,容易上手,游戏过程变化无穷,是一个家喻户晓、老少皆宜的大众游戏。本程序通过结构体、指针、绘图等方面的知识完成几个重要的功能:界面,方块下落,旋转,判断是否还能下落,左右移动,分数,速度设置,清除满的每行,下个方块的预览等。
2.1.2 运行环境
(1)硬件环境:
最低配置:CPU:Pentium3 800以上或其他的兼容规格,内存:256M以上,硬盘:100GB以上空间
推荐配置:CPU:Pentium4 1.6G,内存:512M以上,硬盘:100GB以上空间
(2)软件环境:
运用VC++6.0编程环境
2.2 功能需求
本系统主要功能:绘制地图;生成随机方块;按键响应;预览方块;分数累加。
2.2.1 绘制地图
2.2.2 生成随机方块
随机生成下一个方块。
2.2.3 按键响应
通过按键控制程序,上键旋转方块,下键加速下落,左右键控制方块向左向右移动,Esc暂停游戏。
2.2.4 预览方块
在地图右上方显示下一个方块种类。
2.2.5 分数累加
1.在地图右上方显示目前已获得分数;
2.一次消除的行数越多,得分指数越高。
三、概要设计
根据对题目的分析,该系统主要包括,生成方块、输出方块、按键响应、落地判断、刷新界面、预览方块六个功能,每一个功能都由相应的函数及其他函数辅助实现。主函数控制整个程序的运行及生成地图,可以使程序在一次的运行之中循环执行所有的功能,除此外还具有暂停功能,根据需要暂停程序,使程序更加的完美。
3.1 系统体系结构图
图 1 俄罗斯方块_系统体系结构图
3.2 模块描述
本系统为俄罗斯方块游戏系统,每个模块均为实现游戏功能,无子系统。
模块1:绘制地图
名 称 | 绘制地图 | 标识 | DeawMap | 系统名称 | 俄罗斯方块 | ||
接口说明 | 输入 | 无 | |||||
输出 | 游戏地图 | ||||||
功能说明 | 绘制游戏地图 | ||||||
运行环境 | 运行于VC++6.0编程坏境之下 | ||||||
调用关系 | 调用模块 | 无 | |||||
被调用模块 | 无 |
模块2:生成随机方块
名 称 | 生成随机方块 | 标识 | Tetris*BlockRand | 系统名称 | 俄罗斯方块 | ||
接口说明 | 输入 | 无 | |||||
输出 | 方块 | ||||||
功能说明 | 确定下一个方块的类型 | ||||||
运行环境 | 运行于VC++6.0编程坏境之下 | ||||||
调用关系 | 调用模块 | 颜色设定 | |||||
被调用模块 | 无 |
模块3:按键响应
名 称 | 按键响应 | 标识 | JudgeDirection | 系统名称 | 俄罗斯方块 | ||
接口说明 | 输入 | 键盘 | |||||
输出 | 无 | ||||||
功能说明 | 控制方块 | ||||||
运行环境 | 运行于VC++6.0编程坏境之下 | ||||||
调用关系 | 调用模块 | 无 | |||||
被调用模块 | 无 |
模块4:确定坐标
名 称 | 确定坐标 | 标识 | Form | 系统名称 | 俄罗斯方块 | ||
接口说明 | 输入 | 无 | |||||
输出 | 无 | ||||||
功能说明 | 确定方块坐标 | ||||||
运行环境 | 运行于VC++6.0编程坏境之下 | ||||||
调用关系 | 调用模块 | 坐标更新 | |||||
被调用模块 | 无 |
模块5:显示完整方块
名 称 | 显示完整方块 | 标识 | ShowBlock | 系统名称 | 俄罗斯方块 | ||
接口说明 | 输入 | 无 | |||||
输出 | |||||||
功能说明 | 显示生成的方块 | ||||||
运行环境 | 运行于VC++6.0编程坏境之下 | ||||||
调用关系 | 调用模块 | 确定坐标、颜色设定、判断落地、判断是否落地、坐标更新、设置光标位置 | |||||
被调用模块 | 无 |
模块6:判断左右界限
名 称 | 判断左右界限 | 标识 | JudgeWall | 系统名称 | 俄罗斯方块 | ||
接口说明 | 输入 | 无 | |||||
输出 | 无 | ||||||
功能说明 | 判断左右界限 | ||||||
运行环境 | 运行于VC++6.0编程坏境之下 | ||||||
调用关系 | 调用模块 | 无 | |||||
被调用模块 | 无 |
模块7:设置光标位置
名 称 | 设置光标位置 | 标识 | MoveCursor | 系统名称 | 俄罗斯方块 | ||
接口说明 | 输入 | 无 | |||||
输出 | 无 | ||||||
功能说明 | 设置光标位置 | ||||||
运行环境 | 运行于VC++6.0编程坏境之下 | ||||||
调用关系 | 调用模块 | 无 | |||||
被调用模块 | 无 |
模块8:颜色设定
名 称 | 颜色设定 | 标识 | SetColour | 系统名称 | 俄罗斯方块 | ||
接口说明 | 输入 | 无 | |||||
输出 | 无 | ||||||
功能说明 | 确定下一个方块颜色 | ||||||
运行环境 | 运行于VC++6.0编程坏境之下 | ||||||
调用关系 | 调用模块 | 无 | |||||
被调用模块 | 无 |
模块9:判断落地
名 称 | 判断落地 | 标识 | JudgeGroud | 系统名称 | 俄罗斯方块 | ||
接口说明 | 输入 | 无 | |||||
输出 | 无 | ||||||
功能说明 | 判断是接触到方块或界面底边 | ||||||
运行环境 | 运行于VC++6.0编程坏境之下 | ||||||
调用关系 | 调用模块 | 无 | |||||
被调用模块 | 无 |
模块10:判断整行是否填满
名 称 | 判断整行是否填满 | 标识 | JudgeEntire | 系统名称 | 俄罗斯方块 | ||
接口说明 | 输入 | 无 | |||||
输出 | 无 | ||||||
功能说明 | 判读是否有整行被填满,若填满则清除行 | ||||||
运行环境 | 运行于VC++6.0编程坏境之下 | ||||||
调用关系 | 调用模块 | 无 | |||||
被调用模块 | 无 |
模块11:显示信息
名 称 | 显示信息 | 标识 | show | 系统名称 | 俄罗斯方块 | ||
接口说明 | 输入 | 无 | |||||
输出 | 无 | ||||||
功能说明 | 显示得分和下一个方块 | ||||||
运行环境 | 运行于VC++6.0编程坏境之下 | ||||||
调用关系 | 调用模块 | 设置光标位置 | |||||
被调用模块 | 无 |
模块12:信息更新
名 称 | 信息更新 | 标识 | Location | 系统名称 | 俄罗斯方块 | ||
接口说明 | 输入 | 无 | |||||
输出 | 无 | ||||||
功能说明 | 更新坐标和界面 | ||||||
运行环境 | 运行于VC++6.0编程坏境之下 | ||||||
调用关系 | 调用模块 | 设置光标位置 | |||||
被调用模块 | 无 |
四、详细设计
4.1 系统主要函数说明
函数名称 | 函数功能 |
DeawMap | 绘制游戏地图 |
Tetris*BlockRand | 确定下一个方块的类型 |
JudgeDirection | 控制方块 |
Form | 确定方块坐标 |
ShowBlock | 显示生成的方块 |
JudgeWall | 判断左右界限 |
MoveCursor | 设置光标位置 |
SetColour | 确定下一个方块颜色 |
JudgeGroud | 判断是接触到方块或界面底边 |
JudgeEntire | 判读是否有整行被填满 |
Show | 显示得分和下一个方块 |
Location | 更新坐标和界面 |
4.1.1 函数DeawMap
【功能】
绘制游戏地图
【参数】
无
【返回值】
无
【算法描述】
设置i,j两个整型变量,再通过for循环控制打印次数、内容及位置,绘制地图。
4.1.2 函数Tetris*BlockRand
【功能】
确定下一个方块的类型
【参数】
无
【返回值】
无
【算法描述】
用指针确定方块的类型及初始位置。
4.1.3 函数JudgeDirection
【功能】
控制方块
【参数】
无
【返回值】
无
【算法描述】
用if条件语句判断按键,实现不同按键对应的功能。
4.1.4 函数Form
【功能】
确定方块坐标
【参数】
无
【返回值】
无
【算法描述】
用Switch语句判断方块类型,在用if语句判断形态,并调用Location函数更新坐标。
4.1.5 函数ShowBlock
【功能】
显示生成的方块
【参数】
无
【返回值】
无
【算法描述】
调用JudgeDirection函数控制方块,用指针更新坐标、颜色信息,并调用MoveCursor函数更新光标位置,以及用if语句调用JudgeGroud函数判断是否到底面,最后调用JudgeEntire函数判断是否有整行被填满。
4.1.6 函数JudgeWall
【功能】
判断左右界限
【参数】
无
【返回值】
无
【算法描述】
用if条件语句判断当前方块坐标是否等于地图左右边界。
4.1.7 函数MoveCursor
【功能】
设置光标位置
【参数】
无
【返回值】
无
【算法描述】
用HANDLE output、GetStdHandle()获取标准输出的句柄,再用SetConsole CursorPosition()设置控制台光标位置。
4.1.8 函数SetColour
【功能】
确定方块颜色
【参数】
无
【返回值】
无
【算法描述】
用SetConsoleTextAttribute()控制方块颜色。
4.1.9 函数JudgeGroud
【功能】
判断是接触到方块或界面底边
【参数】
无
【返回值】
无
【算法描述】
用指针获取当前方块坐标,再用数个if语句判断是否到达底层,若到达底层则直接进行下一循环。
4.1.10 函数JudgeEntire
【功能】
判读是否有整行被填满
【参数】
无
【返回值】
无
【算法描述】
用if语句判断是否有整行被填满,若有整行被填满,则清除行,并调用Show更新得分。
4.1.11 函数Show
【功能】
在地图右上方显示得分和预览下一个方块
【参数】
无
【返回值】
无
【算法描述】
先用for循环二重嵌套调用MoveCursor清空显示区域,再用if语句判断新方块类型,将其打印在显示区域。
4.1.12 函数Location
【功能】
若填满则清除行
【参数】
无
【返回值】
无
【算法描述】
用指针更新坐标。
五、系统测试
5.1 初始界面
输出方块到顶部,显示下一个方块及得分
图 2 输出方块到顶部
5.2 控制方块
图 3 控制方块_初始位置
控制方块向左
图 4 控制方块_向左
控制方块向右
图 5 控制方块_向右
5.3 控制方块旋转
图 6 方块初始形态
图 7 方块旋转后形态
六、程序设计
#include<stdio.h>
#include<time.h>
#include<Windows.h>#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); //判断落地
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); //坐标更新1
void Location_y(Tetris ** Block, int x, int y, int a, int b, int c, int d, int e, int f); //坐标更新2
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 = 220; //得分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){PRINTFif (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)//坐标更新1
{(*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)//坐标更新2
{(*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); PRINTFMoveCursor((*Block)->x_2, (*Block)->y_2); PRINTFMoveCursor((*Block)->x_3, (*Block)->y_3); PRINTFMoveCursor((*Block)->x_4, (*Block)->y_4); PRINTFif (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); EMPTYMoveCursor((*Block)->x_2, (*Block)->y_2); EMPTYMoveCursor((*Block)->x_3, (*Block)->y_3); EMPTYMoveCursor((*Block)->x_4, (*Block)->y_4); EMPTYLocation_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("游戏暂停");//判断Escwhile (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到26for (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); EMPTYPHead->x_1 = 99;PHead->y_1 = 99;}if (PHead->y_2 == y){MoveCursor(PHead->x_2, PHead->y_2); EMPTYPHead->x_2 = 99;PHead->y_2 = 99;}if (PHead->y_3 == y){MoveCursor(PHead->x_3, PHead->y_3); EMPTYPHead->x_3 = 99;PHead->y_3 = 99;}if (PHead->y_4 == y){MoveCursor(PHead->x_4, PHead->y_4); EMPTYPHead->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); EMPTYPHead->y_1 += 1;MoveCursor(PHead->x_1, PHead->y_1); PRINTF}if (PHead->y_2 < y){MoveCursor(PHead->x_2, PHead->y_2); EMPTYPHead->y_2 += 1;MoveCursor(PHead->x_2, PHead->y_2); PRINTF}if (PHead->y_3 < y){MoveCursor(PHead->x_3, PHead->y_3); EMPTYPHead->y_3 += 1;MoveCursor(PHead->x_3, PHead->y_3); PRINTF}if (PHead->y_4 < y){MoveCursor(PHead->x_4, PHead->y_4); EMPTYPHead->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);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); PRINTFMoveCursor(Loca_x+a, Loca_y+b); PRINTFMoveCursor(Loca_x+c, Loca_y+d); PRINTFMoveCursor(Loca_x+e, Loca_y+f); PRINTF
}