本来是一天上传一点的,结果一次性上传了( ̄▽ ̄)",尴尬。
HANDLE Output;
void printPrompting(); //显示提示信息
void gotoxyWithFullwidth(short x,short y); //进行全角定位
void printScore(const Manager *manager); //显示分数
void printPoolBorder(); //显示游戏池边界
void initGame(Manager *manager,Control *control); //初始化游戏
void startGame(Manager *manager,Control *control); //开始游戏
void printNextTetris(const Manager *manager); //显示下一个和下下一个方块
void printTetrisPool(const Manager *manager,const Control *control); //显示游戏池
void initTetris(Manager *manager); //方块初始化,构造当前方块
void insertTetris(Manager *manager); //把当前方块插入游戏池中
void setPoolColor(const Manager *manager,Control *control); //设置颜色
void printCurrentTetris(const Manager *manager,const Control *control); //显示当前方块
bool checkCollision(const Manager *manager); //碰撞检测
void runGame(Manager *manager,Control *control); //运行游戏
void moveDownTetris(Manager *manager,Control *control); //向下移动方块
void removeTetris(Manager *manager); //移去方块
bool checkErasing(Manager *manager,Control *control); //检测消行
void horzMoveTetris(Manager *manager,Control *control); //左右移动
void rotateTetris(Manager *manager,Control *control); //旋转方块
void keydownControl(Manager *manager,Control *control,int key); //键入指令
void dropDownTetris(Manager *manager,Control *control); //消行
bool ifPlayAgain(); //重新游戏
这是所有的函数。
#include
#include
#include"day8.h"
int main()
{
Manager manager;
Control control;
//初始化函数
initGame(&manager,&control);
//initTetris(&manager);
//runGame(&manager,&control);
//初始化结构体
// Output=GetStdHandle(STD_OUTPUT_HANDLE);
do
{ printPrompting();
//printScore(&manager);
printPoolBorder();
// printNextTetris(&manager);//显示下一个和下下一个方块
// printTetrisPool(&manager,&control);//显示游戏池
// setPoolColor(&manager,&control);
// insertTetris(&manager);
// setPoolColor(&manager,&control);
runGame(&manager,&control);
if(ifPlayAgain())
{
SetConsoleTextAttribute(Output,0x7);
system("cls");//清屏
startGame(&manager,&control);
}
else
{
break;
}
}while(1);
}
//进行全角定位
void gotoxyWithFullwidth(short x,short y)
{
static COORD cd;
cd.X=(x*2);
cd.Y=y;
SetConsoleCursorPosition(Output,cd);
}
//显示提示信息
void printPrompting()
{
SetConsoleTextAttribute(Output,11);
gotoxyWithFullwidth(26,10);
printf("■控制:");
SetConsoleTextAttribute(Output,11);
gotoxyWithFullwidth(27,12);
printf("□向左移动:← A 4");
SetConsoleTextAttribute(Output,11);
gotoxyWithFullwidth(27,13);
printf("□向右移动:→ D 6");
SetConsoleTextAttribute(Output,11);
gotoxyWithFullwidth(27,14);
printf("□向下移动:↓ S 2");
SetConsoleTextAttribute(Output,11);
gotoxyWithFullwidth(27,15);
printf("□顺时针转:↑ W 8");
SetConsoleTextAttribute(Output,11);
gotoxyWithFullwidth(27,16);
printf("□逆时针转:0");
SetConsoleTextAttribute(Output,11);
gotoxyWithFullwidth(27,17);
printf("□直接落地:空格");
SetConsoleTextAttribute(Output,11);
gotoxyWithFullwidth(27,18);
printf("□暂停游戏:回车");
}
//显示分数
void printScore(const Manager *manager)
{
static const char *tetrisbName="ITLJZSO";
int i;
SetConsoleTextAttribute(Output,14);
gotoxyWithFullwidth(2,2);
printf("■得分:%u",manager->score);
//显示消行总数
gotoxyWithFullwidth(1,6);
printf("■消行总数:%u",manager->erasedTotal);
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);
//输出每一行方块数
for(i=0;i<7;++i)
{
gotoxyWithFullwidth(2,17+i);
printf("□%c形:%u",tetrisbName[i],manager->tetrisCount[i]);
}
}
//显示游戏池边界
void printPoolBorder()
{ int j;
//背景高亮白 11110000
SetConsoleTextAttribute(Output,0xf0);
/* //显示纵线
for(i=1;i<24;++i)
{
gotoxyWithFullwidth(10,i);
printf("%2s","");
gotoxyWithFullwidth(23,i);
printf("%2s","");
}
//显示横线
for(j=0;j<12;++j)
{gotoxyWithFullwidth(11+j,23);
printf("%2s","");
}
*/
for(j=4;j<26;++j)
{
//显示纵线
gotoxyWithFullwidth(10,j-3);
printf("%2s","");
gotoxyWithFullwidth(23,j-3);
printf("%2s","");
}
//显示横线
gotoxyWithFullwidth(10,j-3);
printf("%28s","");
}
//初始化游戏
void initGame(Manager *manager,Control *control)
{
//设置一个光标隐藏变量并初始化
CONSOLE_CURSOR_INFO cursorInfo={1,FALSE};
//获取控制台输入句柄
Output=GetStdHandle(STD_OUTPUT_HANDLE);
//设置光标隐藏
SetConsoleCursorInfo(Output,&cursorInfo);
//设置控制台标题
SetConsoleTitle("俄罗斯方块");
//调用一个游戏开始函数
startGame(manager,control);
}
//开始游戏
void startGame(Manager *manager,Control *control)
{
//初始化结构体
memset(manager,0,sizeof(Manager));
memset(control,0,sizeof(Control));
//初始化游戏池
memcpy(manager->pool,gs_uInitialTetrisPool,sizeof(unsigned int[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));
//初始化游戏
initTetris(manager);//给下一个方块
//设置颜色
setPoolColor(manager,control);
}
//显示下一个和下下一个方块
void printNextTetris(const Manager *manager)
{
unsigned int tetris;
int i;
//边框
SetConsoleTextAttribute(Output,15);
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)
{
gotoxyWithFullwidth((i&3)+27,(i>>2)+2);
((tetris>>i)&1)?(printf("■")):printf("%2s","");
};
//显示下下一个方块
tetris=TetrisTable[manager->type[2]][manager->orientation[2]];
SetConsoleTextAttribute(Output,manager->type[2]|8);
for(i=0;i<16;++i)
{
gotoxyWithFullwidth((i&3)+32,(i>>2)+2);
((tetris>>i)&1)?(printf("■")):printf("%2s","");
};
gotoxyWithFullwidth(50,27);
printf("by:yaoe");
}
//显示游戏池 gotoxyInPool(2,4)等价于gotoxyWithFullwidth(11,1)
#define gotoxyInPool(x,y) gotoxyWithFullwidth(x+9,y-3)
void printTetrisPool(const Manager *manager,const Control *control)
{
int x,y;
for (y=4;y<=25;++y)
{
gotoxyInPool(2,y);//把光标打到每行的开头
for(x=2;x<=13;++x)
{
if((manager->pool[y]>>x)&1)//将每一行都遍历一遍
{
//用相应颜色,显示一个实心方块
SetConsoleTextAttribute(Output,control->color[y][x]);
printf("■");
}
else//没有方块,显示空白
{
SetConsoleTextAttribute(Output,0);
printf("%2s","");
}
}
}
}
//方块初始化,构造当前方块
void initTetris(Manager *manager)
{
unsigned int tetris;
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]];//当前方块
manager->y=0;
manager->x=6;
if(checkCollision(manager))
{
manager->dead=true;
}
else
{
insertTetris(manager);//将当前方块加入游戏池
}
++manager->tetrisTotal;//方块总数
++manager->tetrisCount[manager->type[0]];//对应方块数
printScore(manager);
printNextTetris(manager);//显示下一个方块
}
//把当前方块插入游戏池中
void insertTetris(Manager *manager)
{
unsigned int tetris=TetrisTable[manager->type[0]][manager->orientation[0]];
//当前方块每4位取出,位或到游戏池相应位置,即完成插入方块
manager->pool[manager->y+0]|=(((tetris>>0x0)&0x000f)<x);//取方块的最低4位,放入游戏池中,取4
manager->pool[manager->y+1]|=(((tetris>>0x4)&0x000f)<x);//取方块的次低4位,放入游戏池中,取3
manager->pool[manager->y+2]|=(((tetris>>0x8)&0x000f)<x);//取方块的最高4位,放入游戏池中,取2
manager->pool[manager->y+3]|=(((tetris>>0xc)&0x000f)<x);//取方块的最高4位,放入游戏池中,取1
}
//设置颜色
void setPoolColor( const Manager *manager, Control *control)
{
int i,x,y;
//当前方块
unsigned int tetris=TetrisTable[manager->type[0]][manager->orientation[0]];
for(i=0;i<16;++i)
{
y=(i>>2)+manager->y;//待设置的列
if(y>26)//超过底部限制
{
break;
}
x=(i&3)+manager->x;//待设置的行
if((tetris>>i)&1)//检测的到消方格属于当前方块区域
{
control->color[y][x]=(manager->type[0]|8);//设置颜色
}
}
}
//显示当前方块
void printCurrentTetris(const Manager *manager,const Control *control)
{
int x,y;
y=(manager->y>4)?(manager->y-1):4;//向上扩展一行
for(;y<26&&yy+4;++y)
{
x=(manager->x>2)?(manager->x-1):2;//向左扩展一列
for(;x<14&&xx+5;++x)
{
gotoxyInPool(x,y);
if((manager->pool[y]>>x)&1)
{
SetConsoleTextAttribute(Output,control->color[y][x]);
printf("■");
}
else
{
SetConsoleTextAttribute(Output,0);
printf("%2s","");
}
}
}
}
//碰撞检测
bool checkCollision(const Manager *manager)
{
unsigned int tetris=TetrisTable[manager->type[0]][manager->orientation[0]];
unsigned int dest=0;//存放我们在新的位置取出来的16位数
//取dest的最低4位
dest|=(((manager->pool[manager->y+0]>>manager->x)<<0x0)&0x000f);
//取dest的次低4位
dest|=(((manager->pool[manager->y+1]>>manager->x)<<0x4)&0x00f0);
//取dest的次高4位
dest|=(((manager->pool[manager->y+2]>>manager->x)<<0x8)&0x0f00);
//取dest的最高4位
dest|=(((manager->pool[manager->y+3]>>manager->x)<<0xc)&0xf000);
return((dest&tetris)!=0);
}
//运行游戏
void runGame(Manager *manager,Control *control)
{
clock_t clockLast,clockNow;//这里的clock_t为长整型,clock_t是用来保存时间
clockLast=clock();//计时
printTetrisPool(manager,control);//显示游戏池
while(!manager->dead)//没挂
{
while(_kbhit())//有键按下
{
keydownControl(manager,control,getch());//处理按键
}
if(!control->pause)//未暂停
{
clockNow=clock();//计时
//两次计时的间隔超过0.45秒
if(clockNow-clockLast>0.45F*CLOCKS_PER_SEC)//CLOCKS_PER_SER为常量,值为1000
{
clockLast=clockNow;
moveDownTetris(manager,control);
}
}
}
}
//向下移动方块
void moveDownTetris(Manager *manager,Control *control)
{
int y=manager->y;
removeTetris(manager);//移去当前方块
++manager->y;
if(checkCollision(manager))
{
manager->y=y;
insertTetris(manager);//放入当前方块,不需要设置颜色
if(checkErasing(manager,control))
{
printTetrisPool(manager,control);
}
}
else
{
insertTetris(manager);
setPoolColor(manager,control);
printCurrentTetris(manager,control);
}
}
//移去方块
void removeTetris(Manager *manager)
{
//当前方块
unsigned int tetris=TetrisTable[manager->type[0]][manager->orientation[0]];
//当前方块每4位取出,按位取反后位与到游戏池相应位置,即完成移除方块
manager->pool[manager->y+0]&=~(((tetris>>0x0)&0x000F)<x);
manager->pool[manager->y+1]&=~(((tetris>>0x4)&0x000F)<x);
manager->pool[manager->y+2]&=~(((tetris>>0x8)&0x000F)<x);
manager->pool[manager->y+3]&=~(((tetris>>0xc)&0x000F)<x);
}
bool checkErasing(Manager *manager,Control *control)
{
static const unsigned scores[5]={0,10,30,90,150};
int count=0;//本次的消行数
int y=manager->y+3;//从下往上检测
do
{
if(y<26&&manager->pool[y]==0xffff)//有效区域内
{
++count;//
memmove(manager->pool+1,manager->pool,sizeof(unsigned int )*y);
memmove(control->color[1],control->color[0],sizeof(int [16])*y);
}
else
{
--y;
}
}while(y>=manager->y);
manager->erasedTotal+=count;//消行总分
manager->score+=scores[count];//得分
if(count>0)
{
++manager->erasedCount[count-1];//消行
}
initTetris(manager);//初始化方块
setPoolColor(manager,control);//设置颜色
return(count>0);
}
void horzMoveTetris(Manager *manager,Control *control)
{
int x=manager->x;//记录原列位置
removeTetris(manager);//在原来的位置移除方块
control->direction==0?(--manager->x):(++manager->x);//选择移动
if(checkCollision(manager))
{
manager->x=x;//恢复原来的位置
insertTetris(manager);//放入当前方块,由于位置未变,不需要设置颜色
}
else
{
insertTetris(manager);//在新位置放入方块
setPoolColor(manager,control);//设置颜色
printCurrentTetris(manager,control);//显示当前方块
}
}
void rotateTetris(Manager *manager,Control *control)
{
int ori=manager->orientation[0];//记录原旋转状态
removeTetris(manager);//
manager->orientation[0]=(control->clockwise)?((ori+1)&3):((ori+3)&3);
if(checkCollision(manager))
{
manager->orientation[0]=ori;//恢复原来的位置
insertTetris(manager);//放入当前方块,由于位置未变,不需要设置颜色
}
else
{
insertTetris(manager);//在新位置放入方块
setPoolColor(manager,control);//设置颜色
printCurrentTetris(manager,control);//显示当前方块
}
}
void keydownControl(Manager *manager,Control *control,int key)
{
if(key==13)//暂停或解除暂停
{
control->pause=!control->pause;
}
if(control->pause)//暂停状态,不作处理
{
return;
}
switch(key)
{
case 72://上
rotateTetris(manager,control);//旋转方块
break;
case 80://下
moveDownTetris(manager,control);//向下移动方块
break;
case 75://左
control->direction=0;
horzMoveTetris(manager,control);//水平移动方块
break;
case 77://右
control->direction=1;
horzMoveTetris(manager,control);//水平移动方块
break;
case ' '://直接落地
dropDownTetris(manager,control);
break;
default:
break;
}
}
void dropDownTetris(Manager *manager,Control *control)
{
removeTetris(manager);//移走当前方块
for(;manager->y<26;++manager->y)
{
if(checkCollision(manager))//检测到碰撞
{
break;
}
}
--manager->y;
insertTetris(manager);
setPoolColor(manager,control);
checkErasing(manager,control);
printTetrisPool(manager,control);
}
//重玩一次
bool ifPlayAgain()
{
int ch;
SetConsoleTextAttribute(Output,0xf0);
gotoxyWithFullwidth(15,10);
printf("游戏结束");
gotoxyWithFullwidth(13,11);
printf("按Y重玩,按N退出");
do
{
ch=_getch();
if(ch=='Y'||ch=='y')
{
return true;
}
else if(ch=='N'||ch=='n')
{
return false;
}
}while(1);
}
容我偷回懒O(∩_∩)O
#ifndef DAY8_H_INCLUDED
#define DAY8_H_INCLUDED
#include
#include
#include
#include
#include
#include
#include
typedef struct TetrisManager
{
unsigned int pool[28]; //游戏池 //游戏池
int x; //当前方块横坐标,此处坐标为X轴左上角横坐标
int y; //当前方块纵坐标,此处坐标为Y轴左上角纵坐标
int type[3]; //当前、下一个和下下一个方块的类型
int orientation[3]; //当前、下一个和下下一个方块的旋转状态
unsigned score; //得分
unsigned erasedCount[4]; //消行数
unsigned erasedTotal; //消行总数
unsigned tetrisCount[7]; //消方块数
unsigned tetrisTotal; //方块总数
bool dead; //游戏是否结束
}Manager;
typedef struct TetrisControl
{
bool pause; //暂停
bool clockwise; //旋转方向:顺时针为true
int direction; //移动方向:0向左运动,1向右运动
int color[28][16];
}Control;
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型
};
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,0xffff,0xffff
};
HANDLE Output;
void printPrompting(); //显示提示信息
void gotoxyWithFullwidth(short x,short y); //进行全角定位
void printScore(const Manager *manager); //显示分数
void printPoolBorder(); //显示游戏池边界
void initGame(Manager *manager,Control *control); //初始化游戏
void startGame(Manager *manager,Control *control); //开始游戏
void printNextTetris(const Manager *manager); //显示下一个和下下一个方块
void printTetrisPool(const Manager *manager,const Control *control); //显示游戏池
void initTetris(Manager *manager); //方块初始化,构造当前方块
void insertTetris(Manager *manager); //把当前方块插入游戏池中
void setPoolColor(const Manager *manager,Control *control); //设置颜色
void printCurrentTetris(const Manager *manager,const Control *control); //显示当前方块
bool checkCollision(const Manager *manager); //碰撞检测
void runGame(Manager *manager,Control *control); //运行游戏
void moveDownTetris(Manager *manager,Control *control); //向下移动方块
void removeTetris(Manager *manager); //移去方块
bool checkErasing(Manager *manager,Control *control);
void horzMoveTetris(Manager *manager,Control *control);
void rotateTetris(Manager *manager,Control *control);
void keydownControl(Manager *manager,Control *control,int key);
void dropDownTetris(Manager *manager,Control *control);
bool ifPlayAgain();
#endif // DAY8_H_INCLUDED
头文件 ↑
暂且写这些以后再改(o゚v゚)ノ
2018.6