题目链接:
题意:
俄罗斯方块游戏, 给出一个玩家的操作序列(w,a,s,d,p), 和依次出现的n个方块的形状,
问最终玩家消除了几行.
解题思路:
大模拟,想清楚就好写了,
用一个数组保存 所有形状 所有状态下 四个点的相对位置
每进行一次操作时,判断是否合法(越界,重叠)
下落时判断是否重叠 ,如果重叠则不动 将方块加入地图,消行,换下一个方块继续
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int dir[3][4][4][2]={
{ {0,0,0,1,1,0,1,1},{0,0,0,1,1,0,1,1},{0,0,0,1,1,0,1,1},{0,0,0,1,1,0,1,1} }, //方形
{ {0,0,0,1,0,2,0,3},{0,0,1,0,2,0,3,0},{0,0,0,1,0,2,0,3},{0,0,1,0,2,0,3,0} }, //I形
{ {0,0,0,1,1,0,2,0},{0,0,0,1,0,2,1,2},{0,1,1,1,2,1,2,0},{0,0,1,0,1,1,1,2} } //L形
};
int map[15][15];
char op[1050];
int block[1050];
int ans;
int ok(int x,int y,int b,int state) //判重叠 越界
{
int tx,ty;
for(int i=0;i<4;i++)
{
tx=x+dir[b][state][i][0];
ty=y+dir[b][state][i][1];
if(tx<1||tx>9||ty<1||ty>12||map[tx][ty]==1)
return 0;
}
return 1;
}
void change_map(int x,int y,int b,int state) //更新地图
{
int tx,ty,flag,loc;
for(int i=0;i<4;i++)
{
tx=x+dir[b][state][i][0];
ty=y+dir[b][state][i][1];
map[tx][ty]=1;
}
// for(int i=8;i>=1;i--){ //方块下落全过程...
// for(int j=1;j<=9;j++)
// printf("%d",map[j][i]);
// cout<<endl;
// }
// printf("-------------\n");
while(1)
{
for(int i=1;i<=8;i++){
flag=1;
for(int j=1;j<=9;j++)
if(map[j][i]==0)
{
flag=0;
break;
}
if(flag){
loc=i;
break;
}
}
if(!flag)
return;
ans++;
for(int i=loc;i<=8;i++)
for(int j=1;j<=9;j++)
map[j][i]=map[j][i+1];
}
}
int main()
{
int T,n,s_x=4,s_y=9;
int x,y,state,pos;
int len;
int Case=1;
scanf("%d",&T);
while(T--)
{
memset(map,0,sizeof(map));
pos=1,x=s_x,y=s_y,state=0; //每个方块的初始状态
ans=0;
scanf("%d",&n);
scanf("%s",op);
len=strlen(op);
for(int i=1;i<=n;i++)
scanf("%d",&block[i]);
for(int i=0;i<len;i++)
{
if(op[i]=='w'&&ok(x,y,block[pos],(state+1)%4))
state=(state+1)%4;
else if(op[i]=='s'&&ok(x,y-1,block[pos],state))
y--;
else if(op[i]=='a'&&ok(x-1,y,block[pos],state))
x--;
else if(op[i]=='d'&&ok(x+1,y,block[pos],state))
x++;
if(ok(x,y-1,block[pos],state))
y--;
else {
change_map(x,y,block[pos],state);
x=s_x,y=s_y,state=0;
pos++;
if(pos>n)
break;
}
}
printf("Case %d: %d\n",Case++,ans);
}
return 0;
}