第四天效果图如下
#ifndef _DAY4_H
#define _DAY4_H
#include<windows.h>
#include<time.h>
#include<stdbool.h>
//游戏区域位置设计
#define COL_BEGIN 2
#define COL_END 14
#define ROW_BEGIN 4
#define ROW_END 26
HANDLE Output;//控制台输出句柄
//存储游戏相关数据的结构体
typedef struct TetrisManager//俄罗斯管理
{
unsigned int pool[28];//游戏池
int x;//当前方块的x坐标,左上角坐标
int y;//
int type[3];//当前,下一个,下下一个方块的类型
int orientation[3];//当前,下一个,下下一个方块的旋转状态
//左边栏
unsigned score;//得分
unsigned erasedTotal;//消行总数
unsigned erasedCount[4];//消几行数
unsigned tetrisTotal;//目前出现方块总数
unsigned tetrisCount[7];//目前出现各种方块数
bool dead;//挂
}Manager;//结构体别名
//构造存储游戏控制相关数据的结构体
typedef struct TetrisControl
{
bool pause;//暂停
bool clockwise;//旋转方向;顺时针方向为ture
int direction;//移动方向:0向左移动 1向右移动
//游戏池内每格的颜色
//此版本是彩色的,仅用游戏池数据无法存储颜色
int color[28][16];
}Control;//Control是结构体别名
//初始状态的游戏池
//每个元素表示游戏池的一行
//两端各置两个1,底部两行全部为1,便于进行碰撞
//这样一来游戏池的宽度为12列 共16列
//当某个元素为OXFFFF时,说明该行已经填满
//顶部4行用于给方块,不显示
//底部2行不显示,显示出来的游戏池高度为22行
static const unsigned int gs_uInitialTetrisPool[28]=
{
0XC003,0XC003,0XC003,0XC003,0XC003,0XC003,0XC003,
0XC003,0XC003,0XC003,0XC003,0XC003,0XC003,0XC003,
0XC003,0XC003,0XC003,0XC003,0XC003,0XC003,0XC003,
0XC003,0XC003,0XC003,0XC003,0XC003,0XC003,0XFFFF
//C003 1100 0000 0000 0011
};
//7种方块的4种旋转状态(4位一行)
static const unsigned int TetrisTable[7][4]=
{
{ 0x00f0, 0x2222,0x00f0,0x2222 },//I
{ 0x0072, 0x0262,0x0270,0x0232 },//T
{ 0x0223, 0x0074,0x0622,0x0170 },//L
{ 0x0226, 0x0470,0x0322,0x0071 },//J
{ 0x0063, 0x0264,0x0063,0x0264 },//Z
{ 0x006c, 0x0462,0x006c,0x0462 },//S
{ 0x0660, 0x0660,0x0660,0x0660 },//O
};
//函数声明
void printPoolBorder();//显示游戏池边界
void gotoxyWithFullwidth(short x,short y);//全角显示鼠标定位函数
void printPrompting();//显示按键提示信息
void printScore(const Manager *manager);
void intiGame(Manager* manager,Control*control);//初始化游戏
void startGame(Manager *manager,Control *control);
void printNextTetris(const Manager *manager);
void printTetrisPool(const Manager *manager,Control *control);//显示游戏池
void initTetris(Manager *manager);//初始化方块
void insertTetris(Manager *manager);//插入方块
bool checkCollision(const Manager *manager);//检测碰撞
void setPoolColor(const Manager *manager,Control *control);//设置游戏池颜色
void printCurrentTetris(const Manager *manager,Control *control);
#endif // _DAY4_H
#include <stdio.h>
#include <stdlib.h>
#include"day4.h"
int main()
{
Manager manager;
Control control;
intiGame(&manager,&control);//初始化游戏
printNextTetris(&manager);
do
{
printPrompting();
printPoolBorder();
printScore(&manager);//显示得分
printTetrisPool(&manager,&control);
insertTetris(&manager);//插入方块
setPoolColor(&manager,&control);
}while(1);
return 0;
}
//初始化游戏
void intiGame(Manager* manager,Control*control)
{
Output=GetStdHandle(STD_OUTPUT_HANDLE);
//定义光标隐藏变量并初始化
CONSOLE_CURSOR_INFO info;
info.bVisible=FALSE;//FAlse为光标隐藏
info.dwSize=1;//光标亮度为1-100
//设置光标隐藏
SetConsoleCursorInfo(Output,&info);
SetConsoleTitle("俄罗斯方块");//控制台句柄
startGame(manager,control);//调用游戏
}
//游戏池
void printPoolBorder()
{
int y;
SetConsoleTextAttribute(Output,0xf0);
for(y=4;y<26;y++)
{
//两条纵线
gotoxyWithFullwidth(10,y-3);//鼠标定位
printf("%2s"," ");
gotoxyWithFullwidth(23,y-3);//鼠标定位
printf("%2s"," ");
}
gotoxyWithFullwidth(10,y-3);//一条横线
printf("%28s"," ");
}
//显示全角定位
void gotoxyWithFullwidth(short x,short y)
{
static COORD cd;
cd.X= x*2;//移动1个坐标乘以2,改变2个像素点的 距离
cd.Y=y;
//移动光标到指定位置
SetConsoleCursorPosition(Output,cd);//输出句柄
}
//按键提示信息
void printPrompting()
{
//设置文字颜色,高亮
SetConsoleTextAttribute(Output,0x0B);
//设置文字位置
gotoxyWithFullwidth(26,10);
printf("█控制:");
gotoxyWithFullwidth(27,12);
printf("□向左移动:← A 4");
gotoxyWithFullwidth(27,13);
printf("□向右移动:→ D 6");
gotoxyWithFullwidth(27,14);
printf("□向下移动:↓ S 2");
gotoxyWithFullwidth(27,15);
printf("□顺时针转:↑ W 8");
gotoxyWithFullwidth(27,16);
printf("□逆时针转:0 ");
gotoxyWithFullwidth(27,17);
printf("□直接落地:空格 ");
gotoxyWithFullwidth(27,18);
printf("□暂停游戏:回车 ");
gotoxyWithFullwidth(26,23);
printf("▉By:briup");
}
//显示得分信息
void printScore(const Manager *manager)
{
static const char *tetrisName="ITLJZSO";
int i;
//初始化结构体内存空间
//memset(manager,0,sizeof(Manager));
//设置文字颜色 文字颜色 高亮红+绿=黄色
SetConsoleTextAttribute(Output,0x0E);
//得分
gotoxyWithFullwidth(2,2);
printf("█得分:%u",manager->score);
//消行总数
gotoxyWithFullwidth(1,6);
printf("█消行总数:%u",manager->erasedTotal);
//一次消1234行数纪录
for(i=0;i<4;i++)
{
gotoxyWithFullwidth(2,8+i);
printf("□消%d:%u",i+1,manager->erasedCount[i]);
}
//目前出现的方块总数
gotoxyWithFullwidth(1,15);
printf("█方块总数:%u",manager->tetrisTotal);
//目前出现的ITLJZSO类型的方块数纪录
for(i=0;i<7;i++)
{
gotoxyWithFullwidth(2,17+i);
printf("□%c形:%u",tetrisName[i],manager->tetrisCount[i]);
}
}
//开始游戏
void startGame(Manager *manager,Control *control)
{
/*主要是初始化相关游戏值*/
//初始化结构体内存空间
memset(manager,0,sizeof(Manager));
//初始化游戏池
memcpy(manager->pool,gs_uInitialTetrisPool,sizeof(unsigned [28]) );
//使用时间作为种子参数
srand((unsigned)time(NULL));
//初始化下一个方块
manager->type[1]=rand()%7;
manager->orientation[1]=rand()%4;
manager->type[2]=rand()%7;
manager->orientation[2]=rand()%4;
memset(control,0,sizeof(Control));
//初始化方块2017/6/8
initTetris(manager);//给下一个方块
setPoolColor(manager,control);//设置颜色
}
//显示下一个,下下一个
void printNextTetris(const Manager *manager)
{
int i;
unsigned int tetris;//存储下一个,下下一个类型
//设置边框
SetConsoleTextAttribute(Output,0X0f);//高亮白色
gotoxyWithFullwidth(26,1);
printf("┏━━━━━━━━━┓ ┏━━━━━━━━━┓");
gotoxyWithFullwidth(26,2);
printf("┃%8s ┃ ┃%8s ┃"," " ," ");
gotoxyWithFullwidth(26,3);
printf("┃%8s ┃ ┃%8s ┃"," " ," ");
gotoxyWithFullwidth(26,4);
printf("┃%8s ┃ ┃%8s ┃"," " ," ");
gotoxyWithFullwidth(26,5);
printf("┃%8s ┃ ┃%8s ┃"," " ," ");
gotoxyWithFullwidth(26,6);
printf("┗━━━━━━━━━┛ ┗━━━━━━━━━┛");
//下一个方格用相应的颜色显示
tetris=TetrisTable[manager->type[1]][manager->orientation[1]];
SetConsoleTextAttribute(Output,manager->type[1]|8);//前景高亮
for(i=0;i<16;i++)
{ //x初始位置是27 (i&3)0—15的值为 0123 0123 0123 0123
//y初始位置是2 (i>>2)右移两位0—15的值为0000111122223333
gotoxyWithFullwidth((i&3)+27,(i>>2)+2);
if((tetris>>i)&1)
printf("■");
else
printf("%2s","");
}
tetris=TetrisTable[manager->type[2]][manager->orientation[2]];
SetConsoleTextAttribute(Output,8);
for(i=0;i<16;i++)
{ //x初始位置是33 (i&3)0—15的值为 0123 0123 0123 0123
//y初始位置是2 (i>>2)右移两位0—15的值为0000111122223333
gotoxyWithFullwidth((i&3)+33,(i>>2)+2);
if((tetris>>i)&1)
printf("■");
else
printf("%2s","");
}
}
#define gotoxyInPool(x,y) gotoxyWithFullwidth(11,y-3);
//显示游戏池
void printTetrisPool(const Manager *manager,Control *control)
{
int x,y;
for(y=ROW_BEGIN;y<ROW_END;y++)//4,26
{ gotoxyInPool(2,y);//游戏池中光标定位
// gotoxyWithFullwidth(11,y-3);
//定点到游戏池中的方格2 14
for(x=COL_BEGIN;x<COL_END;x++)
{
if((manager->pool[y]>>x) &1)//1100 0000 0000 0011 >>2
//用相应的颜色,显示一个实心的方块
{
SetConsoleTextAttribute(Output,control->color[y][x]);
//control->color[y][x] 是一个数
//一个方块如0X00f0 只有0和1组成 若想有特定的颜色 就要扩展成4*4的数组
//有1的地方 就赋值为特定的数 也就是特定的颜色
//也就是说这xy坐标所确定的地方 不是1 而是一个特定的颜色数manager->type[0]|8设置高亮
printf("■");
}
else
{
//没有方块,显示空白
SetConsoleTextAttribute(Output,0);
printf("%2s","");
}
}
}
}
//初始化方块
void initTetris(Manager *manager)
{
unsigned int tetris;//16当前方块存放
manager->type[0]=manager->type[1];//下一个方块置为当前
manager->orientation[0]=manager->orientation[1];//下一个方块旋转状态置为当前
manager->type[1]=manager->type[2];//下下一个方块
manager->orientation[1]=manager->orientation[2];
manager->type[2]=rand()%7;//随机生成
manager->orientation[2]=rand()%4;//
tetris=TetrisTable[manager->type[0]][manager->orientation[0]];
//设置当前方块Y坐标,保证刚给出时只显示方块最下面一行 高位
//这种方式使得玩家可以以很快的 速度将方块落在不显示出4行的位置
if(tetris &0xf000)//俄罗斯方块最先显示最下面一行
manager->y=0;
else
manager->y=(tetris &0x0f00)?1:2;
manager->x=6;//设置当前方块x坐标
manager->y=4;//设置当前方块y坐标 实际出现游戏池内方块出现坐标6,1
if(checkCollision(manager)) //检测碰撞
manager->dead=true;//标记游戏结束
else
insertTetris(manager); //将当前方块加入游戏池
manager->tetrisTotal++;//方块总数加起来
manager->tetrisCount[manager->type[0]]++;//相应方块数
printNextTetris(manager);//显示下一个和下下一个方块
printScore(manager);//显示得分信息
}
//插入方块
void insertTetris(Manager *manager)
{
//插入当前方块
unsigned int tetris;//16位
tetris = TetrisTable[manager->type[0]][manager->orientation[0]];
//(tetris >>0x0)&0x0f)当前方块每四位取出,<< manager->x 左移6位 再与0xc003或,最终移到游戏池中央
manager->pool[manager->y+0]|=(((tetris >>0x0)&0x0f)<< manager->x);
manager->pool[manager->y+1]|=(((tetris>>0x4)&0x0f)<<manager->x);
manager->pool[manager->y+2]|=(((tetris >>0x8)&0x0f)<< manager->x);
manager->pool[manager->y+3]|=(((tetris>>0xc)&0x0f)<<manager->x);
}
//设置游戏池内方块的颜色
void setPoolColor(const Manager *manager,Control *control)
{
//只做设置颜色,不需要清除
//当移动方块或给一个方块时候在调用
int x,y,i;
unsigned int tetris;
tetris=TetrisTable[manager->type[0]][manager->orientation[0]];
for(i=0;i<16;i++)
{
y=(i>>2)+manager->y;//0000 1111 2222 3333
x=(i &3)+manager->x;//0123 0123 0123 0123 x=6 游戏池中间值
if(y>ROW_END)//26
break;
if((tetris>>i) &1)
//用相应的颜色,显示一个实心的方块
control->color[y][x]=(manager->type[0]|8);//设置当前方块颜色
//有四行0 1 2 3 每行有四列0123
}
}
bool checkCollision(const Manager *manager)//空语句
{
}