游戏附件
链接: https://pan.baidu.com/s/1KMBav6Uy9OyyUE3BnRfJGw
提取码: d9tb
游戏画面
|
|
头文件、全局变量以及函数声明
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <time.h>
#include <process.h>
#include <math.h>
// 七种方块类型IJLOSTZ
#define I 0
#define J 1
#define L 2
#define O 3
#define S 4
#define T 5
#define Z 6
COORD block[4],nblock[4],blockchange[4];
int tank[12][24]={0};
int type,ntype,typechange,speed;
int cheatopen=0,score,over=0,best=0;
int blockcolor[7]={11,9,5,14,10,13,12};
int blocktypenum[7]={2,4,4,1,2,4,2};
COORD blocktype[7][4];
COORD changeI[2][4],changeJ[4][4],changeL[4][4],changeS[2][4],changeT[4][4],changeZ[2][4];
HANDLE handle,mutex;
void gotoxy(int x, int y); //移动光标
void color(int b); //设置颜色
void initialize(); //初始化各方块的形状和旋转样式
void drawboard(); //绘制界面
void newblock(); //创建新方块
void blocktwist(); //方块旋转
void cheat(); //方块收缩
bool checkbottom(); //检查是否触底
bool checkright(); //检查是否可右移
bool checkleft(); //检查是否可左移
bool checktwist(); //检查是否可旋转
bool checkdie(); //检查是否游戏结束
void checkclear(); //检查是否有可清楚行
void autoplay(); //单步自动操作
void Sautoplay(); //全自动操作
int checkbest(int x,int typechange); //计算最好的方块位置
void blockmove(int dir); //方块移动
unsigned int __stdcall Fun(void *pPM); //子线程控制方块自动下落
void start(); //游戏流程控制和交互
主要函数:
void start()
{
for(int i=0;i<11;i++)
for(int j=0;j<24;j++)
tank[i][j]=0;
for(int j=0;j<24;j++)
tank[0][j]=1,tank[11][j]=1;
//
drawboard();newblock();char ch;score=0;over=0;
speed=(int)(1000/log((double)score+7.38));
color(15);gotoxy(13,8);printf("SCORE:%d",score);
gotoxy(13,9);printf("INTERVAL:%dms",speed);
mutex=CreateMutex(NULL,FALSE,NULL);
handle=(HANDLE)_beginthreadex(NULL,0,Fun,NULL,0,NULL);
while(1)
{
if (kbhit())
{
ch=getch();
WaitForSingleObject(mutex,INFINITE);
switch(ch)
{
case 'R':if(cheatopen)cheat();break;
case 'E':if(cheatopen)autoplay();break;
case 'a':case 'A':if(checkleft())blockmove(2);break;
case 'w':case 'W':if(checktwist())blocktwist();break;
case 'd':case 'D':if(checkright())blockmove(1);break;
case 's':case 'S':
while(!checkbottom()){Sleep(25);blockmove(0);}break;
case 0x1B:over=1;
}
ReleaseMutex(mutex);
if(cheatopen&&ch=='O')Sautoplay();
}
if(over)break;
}
WaitForSingleObject(handle,INFINITE);
CloseHandle(handle);CloseHandle(mutex);
color(15);gotoxy(0,22);printf("GAME OVER!");
if(score>best)best=score,printf("NEW RECORD!");
system("pause");
}
void blockmove(int d)
{
for(int i=0;i<4;i++)
{
gotoxy(block[i].X,block[i].Y);
if(block[i].X>0&&block[i].Y>0)
printf(" ");
}
switch(d)
{
case 0:for(int i=0;i<4;i++)block[i].Y++;break;
case 1:for(int i=0;i<4;i++)block[i].X++;break;
case 2:for(int i=0;i<4;i++)block[i].X--;break;
}
color(blockcolor[type]);
for(int i=0;i<4;i++)
{
gotoxy(block[i].X,block[i].Y);
if(block[i].Y>0)printf("■");
}
}
void checkclear()
{
int i,j,k,num=0,times=0;
for(i=0;i<=20;i++)
{
num=0;
for(j=1;j<=10;j++)if(tank[j][i+3])num++;
if(num==10)
{
times+=1;Sleep(100);
for(k=i;k>0;k--)
{
gotoxy(1,k);
for(j=1;j<=10;j++)
{
tank[j][k+3]=tank[j][k+2];
if(tank[j][k+3]){color(tank[j][k+3]);printf("■");}
else printf(" ");
}
}
printf("\a");
}
}
score+=(times*times);
speed=(int)(1000/log((double)score+7.38));
color(15);gotoxy(13,8);printf("SCORE:%d",score);
gotoxy(13,9);printf("INTERVAL:%dms",speed);
}
有关自动操作:
思路,遍历当前下落方块的所有位置,所有旋转方向下落后的位置并用checkbest函数对该位置打分,选择打分最高的位置和旋转方向操作。
void autoplay()
{
int k,x,bestnum=0,bestx=5,besttype=0,num=0;
for(k=0;k<blocktypenum[type];k++)
{
for(x=1;x<=10;x++)
{
num=checkbest((x+3)%10+1,k);
if(bestnum<num){bestnum=num;bestx=(x+3)%10+1;besttype=k;}
}
}
//
for(int i=0;i<4;i++)
if(block[i].Y>0){gotoxy(block[i].X,block[i].Y);printf(" ");}
//
block[0].X=bestx;
block[0].Y=block[0].Y;
switch(type)
{
case I: for(int i=1;i<4;i++){
block[i].X=block[0].X+changeI[besttype][i].X;
block[i].Y=block[0].Y+changeI[besttype][i].Y;}
break;
case J: for(int i=1;i<4;i++){
block[i].X=block[0].X+changeJ[besttype][i].X;
block[i].Y=block[0].Y+changeJ[besttype][i].Y;}
break;
case L: for(int i=1;i<4;i++){
block[i].X=block[0].X+changeL[besttype][i].X;
block[i].Y=block[0].Y+changeL[besttype][i].Y;}
break;
case S: for(int i=1;i<4;i++){
block[i].X=block[0].X+changeS[besttype][i].X;
block[i].Y=block[0].Y+changeS[besttype][i].Y;}
break;
case T: for(int i=1;i<4;i++){
block[i].X=block[0].X+changeT[besttype][i].X;
block[i].Y=block[0].Y+changeT[besttype][i].Y;}
break;
case Z: for(int i=1;i<4;i++){
block[i].X=block[0].X+changeZ[besttype][i].X;
block[i].Y=block[0].Y+changeZ[besttype][i].Y;}
break;
case O: block[1].X=block[0].X+1;
block[1].Y=block[0].Y;
block[2].X=block[0].X;
block[2].Y=block[0].Y-1;
block[3].X=block[0].X+1;
block[3].Y=block[0].Y-1;
break;
}
//
color(blockcolor[type]);
for(int i=0;i<4;i++)
{
gotoxy(block[i].X,block[i].Y);
if(block[i].Y>0)printf("■");
}
while(!checkbottom()){Sleep(25);blockmove(0);}
}
int checkbest(int x,int tpc)
{
COORD temp[4];
temp[0].X=x;
temp[0].Y=block[0].Y;
switch(type)
{
case I: for(int i=1;i<4;i++){
temp[i].X=temp[0].X+changeI[tpc][i].X;
temp[i].Y=temp[0].Y+changeI[tpc][i].Y;}
break;
case J: for(int i=1;i<4;i++){
temp[i].X=temp[0].X+changeJ[tpc][i].X;
temp[i].Y=temp[0].Y+changeJ[tpc][i].Y;}
break;
case L: for(int i=1;i<4;i++){
temp[i].X=temp[0].X+changeL[tpc][i].X;
temp[i].Y=temp[0].Y+changeL[tpc][i].Y;}
break;
case S: for(int i=1;i<4;i++){
temp[i].X=temp[0].X+changeS[tpc][i].X;
temp[i].Y=temp[0].Y+changeS[tpc][i].Y;}
break;
case T: for(int i=1;i<4;i++){
temp[i].X=temp[0].X+changeT[tpc][i].X;
temp[i].Y=temp[0].Y+changeT[tpc][i].Y;}
break;
case Z: for(int i=1;i<4;i++){
temp[i].X=temp[0].X+changeZ[tpc][i].X;
temp[i].Y=temp[0].Y+changeZ[tpc][i].Y;}
break;
case O: temp[1].X=temp[0].X+1;
temp[1].Y=temp[0].Y;
temp[2].X=temp[0].X;
temp[2].Y=temp[0].Y-1;
temp[3].X=temp[0].X+1;
temp[3].Y=temp[0].Y-1;
break;
}
for(int i=0;i<4;i++)
{
if(tank[temp[i].X][temp[i].Y+3])return -1;
if(temp[i].X<1||temp[i].X>10||temp[i].Y>20)return -1;
}
int z=0;
while(1)
{
for(int i=0;i<4;i++)if(temp[i].Y>=20||tank[temp[i].X][temp[i].Y+4])z=1;
if(z)break;
for(int k=0;k<4;k++)temp[k].Y++;
}
int num=0;
for(int i=0;i<4;i++){tank[temp[i].X][temp[i].Y+3]=1;}
for(int i=0;i<4;i++)
{
//打分区域开始
if(tank[temp[i].X][temp[i].Y+4])num+=4;
if((!tank[temp[i].X][temp[i].Y+4])&&(temp[i].Y!=20))num-=16;
if((!tank[temp[i].X][temp[i].Y+4])&&(!tank[temp[i].X][temp[i].Y+5])&&(temp[i].Y!=20)&&(temp[i].Y!=19))num-=32;
if(tank[temp[i].X+1][temp[i].Y+3])num+=4;
if(tank[temp[i].X-1][temp[i].Y+3])num+=4;
if(tank[temp[i].X+1][temp[i].Y+3]&&tank[temp[i].X-1][temp[i].Y+3])num+=4;
if(temp[i].Y>=20)num+=6;
if(temp[i].Y<=0)num-=1000;
num+=temp[i].Y;
//打分区域结束
}
int bnum;
for(int k=0;k<=20;k++)
{
bnum=0;
for(int j=1;j<=10;j++)if(tank[j][k+3])bnum++;
if(bnum==10)num+=60;
}
for(int i=0;i<4;i++){tank[temp[i].X][temp[i].Y+3]=0;}
return num;
}
注:checkbest打分标准直接决定了自动操作的技术!!!