#include "Tetris.h"
#pragma warning (disable:4996) //消除警告,兼容旧版本库文件
Tetris::Tetris() {//通过构造函数完成初始化
lines = 1;
disScore =0;
forceGrade = 0;
data = ReadGrade();
grade = data.hisGrade;//延续上次的等级
difficulty = AdjustDifficulty();//重新计算下落时间
ConfigEnvironment();
SetFont();
InitInterface();
InitBlockInfo();
}
//配置运行窗口
void Tetris:: ConfigEnvironment() {
system("chcp 936");//设置utf-8字符集65001,GBK字符集936,如果乱码才需要更改
//设置标题
char cmd[60];
sprintf(cmd, "title 俄罗斯方块:%s", data.user);//含变量的DOS命令,序列化到字符中再传递
system(cmd);
//设置cmd窗口的大小
sprintf(cmd,"mode con lines=%d cols=%d" ,ROW, 2*COL+40);//改变ROW,COL时窗口自动调整大小
system(cmd);
//设置随机数起点,每次启动,游戏会有不同的开局
srand((unsigned int)time(NULL));
//隐藏光标
CONSOLE_CURSOR_INFO curInfo; //光标结构体变量
curInfo.dwSize = 1; //如果没赋值的话,隐藏光标无效
curInfo.bVisible = FALSE; //可见为TRUE
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //获取标准输出句柄
SetConsoleCursorInfo(handle, &curInfo); //设置光标信息
//游戏界面最大化会破坏布局,禁用最大化
HWND hwnd = GetConsoleWindow();
HMENU hmenu = GetSystemMenu(hwnd, false); // 复制或修改而访问窗口菜单
RemoveMenu(hmenu, SC_MAXIMIZE, MF_BYCOMMAND); // 从指定菜单删除一个菜单项或分离一个子菜单
DrawMenuBar(hwnd);//去除最大化菜单
}
//设置字体,一是美观,二是控制方块大小,太小的方块玩起来太累
//虽然可以游戏启动后手动调节字体,但是为了具有良好游戏体验,直接设好吧
void Tetris::SetFont(int size) {//默认大小为20号字,传入参数可以改变字体及方块大小
CONSOLE_FONT_INFOEX cfi;//控制台字体信息的结构体
cfi.cbSize = sizeof(CONSOLE_FONT_INFOEX);
cfi.nFont = 0;
cfi.dwFontSize.X = 0;
cfi.dwFontSize.Y = size; //设置字体大小
cfi.FontFamily = FF_DONTCARE;
cfi.FontWeight = FW_NORMAL; //字体粗细 FW_BOLD
wcscpy_s(cfi.FaceName, L"隶书"); //设置字体,必须是控制台已有的
SetCurrentConsoleFontEx(GetStdHandle(STD_OUTPUT_HANDLE), FALSE, &cfi);//根据结构体内容改变字体
}
//重新开始
void Tetris::Restart() {
//清空游戏区方块
for (int i = 0; i < ROW-1; i++) {
for (int j = 2; j < 2*COL - 2; j+=2) {
CursorJump(j, i);
printf(" ");//两个空格填充一个方块
}
}
//清除当前分数
disScore = 0;
forceGrade = 0;
grade = 0;//游戏速度降到最低,不再延续以前的速度继续
CursorJump(2 * COL + 22, 16);
printf(" ");//这里可能写了字,清除掉
Display();//刷新游戏灯牌
//清除已落下的方块
for (int i = 0; i < ROW-1; i++) {
for (int j = 1; j < COL - 1; j++) {
face.data[i][j] = 0;
face.color[i][j] = 0;
}
}
return;
}
//光标跳转
void Tetris::CursorJump(int x, int y)
{
COORD pos; //光标位置的结构体变量
pos.X = x; //横坐标
pos.Y = y; //纵坐标
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //获取控制台句柄
SetConsoleCursorPosition(handle, pos); //设置光标位置
}
//刷新游戏灯牌
void Tetris:: Display() {
color(7);//白色
int g = grade < forceGrade ? forceGrade:grade ;//高等级优先
CursorJump(2 * COL + 31, 6);//光标要跳到正确位置再修改相应内容
printf("%d", g);
CursorJump(2 * COL + 23, 8);
int i=0;
for (; i <= g; i++) {//显示一个看似酷炫的速度进度条
color(0xae);//被景绿色,前景黄色
printf(">");
}
for (; i <= 9; i++) {
color(0x80);//灰色背景
printf(" ");
}
color(7);//改回白色
CursorJump(2 * COL + 31, 12);
printf("%-5d", disScore);
CursorJump(2 * COL + 31, 14);
difficulty = AdjustDifficulty();
printf("%-4dms", difficulty);
}
//初始化界面
void Tetris::InitInterface()
{
color(0x38); //边框颜色
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL + 20; j++)
{
if (j == 0 || j == COL - 1 || j == COL + 9||j==COL+19)//竖线位置
{
face.data[i][j] = 1; //标记该位置有方块
CursorJump(2 * j, i);
printf("◆");
}
else if (i == ROW - 1)
{
face.data[i][j] = 1;
printf("◆");
}
else
face.data[i][j] = 0;
}
}
for (int i = COL; i < COL + 10; i++)//左栏横线
{
face.data[8][i] = 1;
CursorJump(2 * i, 8);
printf("◆");
}
for (int i = COL+10; i < COL + 20; i++)//右栏横线
{
face.data[18][i] = 1;
CursorJump(2 * i, 18);
printf("◆");
}
color(7);//操作说明文字设置为白色
CursorJump(2 * COL+4, 1);
printf("下一个方块");
CursorJump(2 * COL + 4, ROW - 19);
printf("左移:A←");
CursorJump(2 * COL + 4, ROW - 17);
printf("右移:F→");
CursorJump(2 * COL + 4, ROW - 15);
printf("加速:D ↓");
CursorJump(2 * COL + 4, ROW - 13);
printf("旋转:空格↑");
CursorJump(2 * COL + 4, ROW - 11);
printf("暂停: S");
CursorJump(2 * COL + 4, ROW - 9);
printf("退出: esc");
CursorJump(2 * COL + 4, ROW - 7);
printf("重新开始:R");
CursorJump(2 * COL + 2, ROW-5);
printf("继续上次游戏:C");
CursorJump(2 * COL + 2, ROW-3);
printf("更换新用户名:U");
//游戏灯牌
CursorJump(2 * COL + 22, 2);
printf("直接跳级提速");
CursorJump(2 * COL + 22, 4);
printf("请选择:0--9");
CursorJump(2 * COL + 22, 6);
printf("当前等级:%d",grade);
CursorJump(2 * COL + 22, 10);
printf("最高纪录:%-5d", data.max);//估计玩到大于10万分就觉得没意思了,所以5位数宽度就够了
CursorJump(2 * COL + 22, 12);
printf("当前分数:%-5d", disScore);
CursorJump(2 * COL + 22, 14);
difficulty = AdjustDifficulty();
printf("下落速度:%-4dms", difficulty);
Display();//画一下进度条
//打印游戏说明
CursorJump(2 * COL + 21, 20);
printf("将方块垒整齐得分");
CursorJump(2 * COL + 21, 21);
printf("连续消多行多得分");
CursorJump(2 * COL + 21, 23);
printf("中途保存可按esc");
CursorJump(2 * COL + 21, 24);
printf("游戏结束不会保存");
CursorJump(2 * COL + 21, 25);
printf("根据你的分数速度");
CursorJump(2 * COL + 21, 26);
printf("只能提速不能降速");
}
//初始化方块信息
void Tetris::InitBlockInfo()//7种方块28种形态预先存入数组,供显示使用
{
//“T”形
for (int i = 0; i <= 2; i++)
block[0][0].space[1][i] = 1;
block[0][0].space[2][1] = 1;
//“L”形
for (int i = 1; i <= 3; i++)
block[1][0].space[i][1] = 1;
block[1][0].space[3][2] = 1;
//“J”形
for (int i = 1; i <= 3; i++)
block[2][0].space[i][2] = 1;
block[2][0].space[3][1] = 1;
for (int i = 0; i <= 1; i++)
{
//“Z”形
block[3][0].space[1][i] = 1;
block[3][0].space[2][i + 1] = 1;
//“S”形
block[4][0].space[1][i + 1] = 1;
block[4][0].space[2][i] = 1;
//“O”形
block[5][0].space[1][i + 1] = 1;
block[5][0].space[2][i + 1] = 1;
}
//“I”形
for (int i = 0; i <= 3; i++)
block[6][0].space[i][1] = 1;
int temp[4][4];
for (int shape = 0; shape < 7; shape++) //7种形状
{
for (int form = 0; form < 3; form++) //4种形态,已经有了一种,每个还需增加3种
{
//获取第form种形态
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
temp[i][j] = block[shape][form].space[i][j];
}
}
//将第form种形态顺时针旋转,得到第form+1种形态
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
block[shape][form + 1].space[i][j] = temp[3 - j][i];
}
}
}
}
}
//颜色设置
void Tetris::
评论1