#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <conio.h>
#include <windows.h>
#define kd 14 //宽度
#define gd 23 //高度
//----------功能键设置------------
#define zuoyi 'a' //左移动
#define youyi 'd'//右移动
#define xiayi 's'//下移动 (加速)
#define bx '-' //变形
#define zt '+' //暂停
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
//---------------定义结构----------------------
typedef struct{//坐标结构
int x;
int y;
}zb;
typedef struct{//方块结构
int lx; //他的类型 0是田 1是T 2是F,3是N,4是条
int x1;//3初始
int y1;//2初始
zb zb; //他的坐标,中心点
const char *p[6];//指向一个形状地址;
}xz;
//----------------定义函数---------------------
void gotoxy( int x, int y );
void chushi();//初始一些数据
void printf_dy();//打印地图数据
void bianxing(xz*dqxz);//变形 (方块指针,旋转几次)
char jieshou();//接受字符输入,直到接受到字符才返回;
int get_c();//缓冲区获取一个功能键状态,如果获取失败,返回字符-1 (马上返回 ) -1失败 0左移 1下移动 2右移动 3变型 4暂停
int jiance(int n);//下左右移动检测 OK返回1,失败返回0
void zanting();//暂停
int yidong(int n);//根据方向移动, 到底部,返回-1
int jiaru();//将当前不能下降的方块加入到障碍物数组里面;并消行,返回有多少行消了
void xiaohang(int h);//消行(行坐标)
void shenchan();//生产方块
int naozhong();//闹钟,间隔多久
//-------------定义全局变量-------------------
const char *ditu[kd][gd];//地图
const char *zhangaiwu[kd][gd] ;//障碍物
clock_t jg;
int nd;//设置难度,就是方块下降的速度 间隔时间,微妙
int sfch;//是否重行绘制 1绘制 0不绘制
int jifen;//当前玩了多少分
xz dqxz; //当前形状 ------
xz xgxz;//下一个形状--------------
xz lsxz; //临时形状----
const char *leixing[5][6]={ //这里的指针都是指向常量区的,大家可以添加跟多的方块类型
{"■","■","■","■"," "," "},//方块田比较特殊,旋转就不用旋转
{"■"," ","■","■","■"," "}, //T块
{"■","■","■"," ","■"," "}, //F块
{" ","■","■","■","■"," "}, //N块
{"■"," ","■"," ","■"," "}, //条块
};
int fx[6]={-1,0,1,0,1,0};//方向坐标
//-----------------------函数-------------------------------
int naozhong(){
clock_t njg=clock();
if(njg-jg>=nd){
jg=njg;
return 1;
}else{
return 0;
}
}
void shenchan(){
dqxz.zb =xgxz.zb ;
dqxz.x1 =xgxz.x1;
dqxz.y1 =xgxz.y1;
dqxz.lx =xgxz.lx;
int n;
for(n=0;n<6;n++){
dqxz.p[n] =xgxz.p[n];
}
//生产一个下一个方块数据
xgxz.lx=rand()%5;
xgxz.x1=3;
xgxz.y1=2;
xgxz.zb .x=(kd-2)/2;
xgxz.zb.y =-1;
for(n=0;n<6;n++){
xgxz.p[n]= leixing[xgxz.lx][n];
}
for(n=0;n<rand()%5;n++){
bianxing(&xgxz);
}
}
int jiaru(){//加入障碍物 ,返回有多少行可以消
int x1,y1,x,y,m,n=0;
for(y=0;y<dqxz.x1 ;y++){//打印方块
for(x=0;x<dqxz.y1 ;x++){
if(*(dqxz.p +n)=="■" ){
x1=dqxz.zb .x+x;
y1=dqxz.zb .y+y;
zhangaiwu[x1][y1]="■";
}
n++;
}
}
m=0;
for(y1=0;y1<dqxz.x1 ;y1++){
n=0;
for(x=0;x<kd;x++){
y=dqxz.zb .y+y1;
if(zhangaiwu[x][y]=="■" && y<gd-1) {
n++;
}
}
if(n==kd){
xiaohang(y);
m++;
}
}
return m;
}
void xiaohang(int h){//消行坐标
int x,y,y1;
for(y1=0;y1<h;y1++){
for(x=1;x<kd-1;x++){
y=h-y1;
if(y>0){
zhangaiwu[x][y]=zhangaiwu[x][y-1];
}else{
zhangaiwu[x][y]=". ";
}
}
}
}
int yidong(int n){//根据字符控制方块状态,如果到底部,则返回-1
int f=1;
if(jiance(n)==1){
if(n==1){
while(jiance(n)==1){
dqxz.zb .x=dqxz.zb .x+fx[n];
dqxz.zb .y=dqxz.zb .y+fx[n+3];
}
}else{
dqxz.zb .x=dqxz.zb .x+fx[n];
dqxz.zb .y=dqxz.zb .y+fx[n+3];
}
}
if(jiance(1)==0){
f=0;
}
return f;
}
void gotoxy( int x, int y ){
COORD c;
c.X = x - 1; c.Y = y - 1;
SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE ), c );
}
void zanting(){//暂停
gotoxy(kd*2+2,gd/2+7);
printf("请安“+”加号键继续!!");
while(jieshou()!='+'){//游戏继续啦
}
gotoxy(kd*2+2,gd/2+7);
printf(" -变形 +暂停 ");
}
int jiance(int f){//下左右移动检测 OK返回1,失败返回0
xz lsxz;//零时形状
int x,y,n=0,m=1;
int x1,y1;
lsxz=dqxz;
lsxz.zb .x=lsxz.zb.x +fx[f];
lsxz.zb .y=lsxz.zb.y +fx[f+3];
for(y=0;y<lsxz.x1 ;y++){//打印方块
for(x=0;x<lsxz.y1 ;x++){
if(*(dqxz.p +n)=="■" ){
x1=lsxz.zb .x+x;
y1=lsxz.zb .y+y;
if(x1<1 ||x1>kd-2 ||y1<0 ||y1>gd-2){
m=0;
break;
}else if( zhangaiwu[x1][y1]=="■" && y1>0){
m=0;
break;
}
}
n++;
}
}
return m;
}
int get_c(){//缓冲区获取一个功能键状态,如果获取失败,返回字符-1 (马上返回 ) -1失败 0左移 1下移动 2右移动 3变型 4暂停
char ls;
int n=-1;
if(kbhit()!=0){
ls=getch();
while(kbhit()){
getch();
}
}
switch(ls){
case zuoyi:n=0;break;
case youyi:n=2;break;
case xiayi:n=1;break;
case bx:n=3;break;
case zt:n=4;break;
}
return n;
}
void bianxing(xz*ybxz){//变形 (方块指针,旋转几次)
if(ybxz->lx==0){
return ;
}
int x,y,n,i;
int z[2][6]={{4,2,0,5,3,1},{3,0,4,1,5,2}};
int z2[3][2]={{2,3},{3,2},{1,-1}};
lsxz.zb=ybxz->zb ;
if(ybxz->x1==2){
i=1;
}else{
i=0;
}
for(n=0;n<6;n++){//旋转
lsxz.p[n]=ybxz->p[z[i][n]];
}
lsxz.zb.y=lsxz.zb.y +z2[2][i];//旋转之后的坐标的变换,我这里只简单处理了下,具体的坐标是这么样的没研究出来,考亲们研究啦
lsxz.x1 =z2[0][i];
lsxz.y1 =z2[1][i];
//---------------------------------
int x1,y1,m=1;
n=0;
for(y=0;y<lsxz.x1 ;y++){//遍历
for(x=0;x<lsxz.y1;x++){
if(lsxz.p[n]=="■" ){
x1=lsxz.zb .x+x;
y1=lsxz.zb .y+y;
if(x1<1 ||x1>kd-2 ||y1>gd-2){
m=0;
break;
}else if( zhangaiwu[x1][y1]=="■" && y1>0){
m=0;
break;
}
}
n++;
}
}
//--------------------------------------------
if(m==1){//如果零时方块和障碍物没有重叠,则把零时方块的信息复制个当前方块
ybxz->zb =lsxz.zb;
ybxz->x1=lsxz.x1 ;
ybxz->y1=lsxz.y1 ;
for(n=0;n<6;n++){
ybxz->p[n]=lsxz.p [n];
}
}
}
void chushi(){//初始一些数据
jifen=0;//初始化积分
srand((unsigned int)time(NULL));//初始化随机种子
jg=clock();//初始化时间
nd=300;//初始化难度,毫米级别
//---------初始化下个形状的数据---------------
int n;
xgxz.lx=rand()%5;
xgxz.x1=3;
xgxz.y1=2;
xgxz.zb .x=(kd-2)/2;
xgxz.zb.y =-1;
for(n=0;n<6;n++){
xgxz.p[n]= leixing[xgxz.lx][n];
}
shenchan(); //产生一个方块
int x,y;
for(y=0;y<gd;y++){//初始化障碍物
for(x=0;x<kd;x++){
if(x==0||x==kd-1||y==gd-1){
zhangaiwu[x][y]="■";
}else{
zhangaiwu[x][y]=". ";
}
}
}
}
void printf_dy(){//打印地图数据
int x,y,n=0;
for(y=0;y<gd;y++){//初始化地图
for(x=0;x<kd;x++){
if(x==0||x==kd-1||y==0||y==gd-1){
ditu[x][y]="●";
}else{
ditu[x][y]=zhangaiwu[x][y];
}
}
}
// system("cls");
for(y=0;y<dqxz.x1 ;y++){//打印方块
for(x=0;x<dqxz.y1 ;x++){
int x1=dqxz.zb .x+x;
int y1=dqxz.zb .y+y;
if(dqxz.p[n]=="■" && x1>0 &&x<kd-1 && y1>0 && y<gd-1){
ditu[x1][y1]=dqxz.p[n];
}
n++;
}
}
gotoxy(1,1);//将光标移到最上面
for(y=0;y<gd;y++){//打印地图
for(x=0;x<kd;x++){
printf("%s",ditu[x][y]);
}
printf("\n");
}
gotoxy(kd*2+2,gd/2-4);
printf("---下个方块---");
n=0;
for(x=0;x<3;x++){
gotoxy(kd*2+6,gd/2-2+x);
for(y=0;y<3 ;y++){
if(x<xgxz.x1 && y<xgxz.y1 ){
printf("%s",xgxz.p[n]);
n++;
}else{
printf(" ");
}
}
}
gotoxy(kd*2+2,gd/2+2);
printf("---游戏积分---");
gotoxy(kd*2+2,gd/2+3);
printf(" %d",jifen*10);
gotoxy(kd*2+2,gd/2+5);
printf("---控制按钮---");
gotoxy(kd*2+2,gd/2+6);
printf(" A下 S下 D右 ");
gotoxy(kd*2+2,gd/2+7);
printf(" -变形 +暂停 ");
}
char jieshou(){//接受字符输入,直到接受到字符才返回;
while( !kbhit() ){
Sleep(20);
}
char ls=getch();
while(kbhit()){
getch();
}
return ls;
}
int main(int argc, char *argv[]) {
chushi();
int jc,n;
while(1){
if(sfch=1){//检测是否重行绘制
printf_dy();
sfch=0;
}
jc=jiance(1);
if(jc==1){//这里检测是否能往下移动
if(sfch=naozhong()){
dqxz.zb .y=dqxz.zb .y+1;
}
}else if(jc==0 && dqxz.zb .y<0){//检测是否到顶部了,到顶部了就结束游戏
system("cls");
printf("游戏失败");//放假了心静不下来,不想搞了,简单处理
break;
}else{ //不能移动了,就说明到底部了,把当前方块加入到障碍物里面
jifen=jiaru()+jifen;
nd=nd*19/20;//放假了心静不下来,不想搞了,简单处理
shenchan();
}
n=get_c();//从键盘区获取一个功能键状态 -1失败 0左移 1下移动 2右移动 3变型 4暂停
switch(n){
case -1:;break;//非法移动
case 4://暂停
zanting();
break;
case 3:
bianxing(&dqxz);
sfch=1;
break;//变型
default: //移动
yidong(n);
sfch=1;
break;
}
}
return 0;
}