思路:
先写好了几个函数。旋转,四种操作,判断是否可以进行合并消除
题中有好几处要考虑的细节问题,如
自然下落到底部时不进行合并的判断,而是当自然下落非法时才判断
如果消除一行,这一行上面的所以方块只会下落一行,不存在直接下落到底部的情况
比赛时题意没有理解好,错了这两个地方。。
还有一些写法上的错误,这种左右移动的题目坐标还是要从1开始,方便许多
左右移动,如果非法要复原的时候,复原的操作要与移动操作 完全相反,并且这个范围要从0开始,因为移动的时候可能移动到非法的位置。
赛后看了标程,各种优美简洁的代码。模拟能力还有待加强。
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#define pb push_back
#define debug puts("=====================");
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
typedef long long ll;
int t;
int Map[20][20]; //记录整体
int updata[20][20]; //记录当前掉落方块
char ch[1111];
int a[1111];
int n;
int chong() //判断是否有非法操作
{
int sum = 0;
for(int i=1; i<=12; i++)
for(int j=1; j<=9; j++)
if(updata[i][j]) sum++;
if(sum!=4)
return 0;
for(int i=1; i<=12; i++)
for(int j=1; j<=9; j++)
if(updata[i][j]+Map[i][j]>1)
return 0;
return 1;
}
int zhuan(int type,int x,int y) //旋转
{
if(type==1)
{
swap(updata[x-1][y],updata[x][y+1]);
swap(updata[x-2][y],updata[x][y+2]);
swap(updata[x-3][y],updata[x][y+3]);
if(!chong()) //如果非法,再转回来
{
swap(updata[x-1][y],updata[x][y+1]);
swap(updata[x-2][y],updata[x][y+2]);
swap(updata[x-3][y],updata[x][y+3]);
}
}
else if(type==2)
{
if(updata[x][y]==0) ///3->4
{
swap(updata[x-1][y],updata[x-2][y+1]);
swap(updata[x-1][y+2],updata[x][y+1]);
swap(updata[x][y+2],updata[x][y]);
if(!chong())
{
swap(updata[x-1][y],updata[x-2][y+1]);
swap(updata[x-1][y+2],updata[x][y+1]);
swap(updata[x][y+2],updata[x][y]);
}
}
else
{
if(updata[x-1][y]&&updata[x][y+1]) ///1->2
{
swap(updata[x][y+1],updata[x-2][y]);
swap(updata[x][y+2],updata[x-2][y+1]);
if(!chong())
{
swap(updata[x][y+1],updata[x-2][y]);
swap(updata[x][y+2],updata[x-2][y+1]);
}
}
else if(updata[x-1][y]&&!updata[x][y+1]) ///2->3
{
swap(updata[x][y],updata[x-1][y+1]);
swap(updata[x-2][y],updata[x-1][y+2]);
swap(updata[x-2][y+1],updata[x][y+2]);
if(!chong())
{
swap(updata[x][y],updata[x-1][y+1]);
swap(updata[x-2][y],updata[x-1][y+2]);
swap(updata[x-2][y+1],updata[x][y+2]);
}
}
else if(!updata[x-1][y]&&updata[x][y+1]) ///4->1
{
swap(updata[x-1][y+1],updata[x-1][y]);
swap(updata[x-2][y+1],updata[x][y+2]);
if(!chong())
{
swap(updata[x-1][y+1],updata[x-1][y]);
swap(updata[x-2][y+1],updata[x][y+2]);
}
}
}
}
}
int ctrl(char lei,int type) //控制上下左右
{
if(lei=='w')
{
if(type==0)
return 0;
int xx,yy;
xx = -9999;
yy = 9999;
for(int i=1; i<=12; i++)
for(int j=1; j<=9; j++)
if(updata[i][j])
xx = max(xx,i),yy = min(yy,j); //找到绿色的点,以这个点为基准
zhuan(type,xx,yy);
}
else if(lei=='a')
{
for(int i=1; i<=12; i++)
for(int j=0; j<=10; j++)
if(updata[i][j]) swap(updata[i][j],updata[i][j-1]);
if(!chong()) //如果非法,再移回来
{
for(int i=1; i<=12; i++)
for(int j=10; j>=0; j--)
if(updata[i][j]) swap(updata[i][j],updata[i][j+1]);
}
}
else if(lei=='d')
{
for(int i=1; i<=12; i++)
for(int j=10; j>=0; j--)
if(updata[i][j]) swap(updata[i][j],updata[i][j+1]);
if(!chong())
{
for(int i=1; i<=12; i++)
for(int j=0; j<=10; j++)
if(updata[i][j]) swap(updata[i][j],updata[i][j-1]);
}
}
else if(lei=='s')
{
for(int i=13; i>=1; i--)
for(int j=1; j<=9; j++)
if(updata[i][j]) swap(updata[i][j],updata[i+1][j]);
if(!chong())
{
for(int i=1; i<=13; i++)
for(int j=1; j<=9; j++)
if(updata[i][j]) swap(updata[i][j],updata[i-1][j]);
}
}
return 1;
}
int score,tmp,jj,len;
int di() //判断是否可以合并、消除
{
int go = 1;
for(int i=1; i<=11; i++)
for(int j=1; j<=9; j++)
{
if(updata[i][j]&&updata[i+1][j]==0)
{
if(Map[i+1][j])
go = 0;
}
}
for(int j=1; j<=9; j++)
{
if(updata[12][j])
go = 0;
}
if(go)
return 0;
for(int i=1; i<=12; i++)
for(int j=1; j<=9; j++)
{
if(updata[i][j])
Map[i][j] = updata[i][j];
}
while(1)
{
int flag = 0;
int hang = 12;
for(int i=1; i<=12; i++)
{
int sum = 0;
if(Map[i][1])
{
for(int j=1; j<=9; j++)
sum+=Map[i][j];
}
if(sum==9)
{
// cout<<"--------\n";
hang = i;
flag = 1;
score++;
for(int j=1; j<=9; j++)
Map[i][j] = 0;
break;
}
}
if(flag)
{
for(int i=hang-1; i>=1; i--)
for(int j=1; j<=9; j++)
if(Map[i][j]&&Map[i+1][j]==0)
swap(Map[i][j],Map[i+1][j]);
}
else
break;
}
return 1;
}
int main()
{
// freopen( "3.out","w",stdout );
cin>>t;
int cs = 1;
while(t--)
{
score = 0;
scanf("%d%s",&n,ch);
for(int i=0; i<n; i++)
scanf("%d",&a[i]);
memset(Map,0,sizeof(Map));
memset(updata,0,sizeof(updata));
jj = 0;
len=strlen(ch);
for(int i=0; i<n; i++) //下落的方块
{
tmp = a[i];
memset(updata,0,sizeof(updata));
if(a[i]==0)
{
updata[4][4] = 1;
updata[3][4] = 1;
updata[4][5] = 1;
updata[3][5] = 1;
}
else if(a[i]==1)
{
updata[4][4] = 1;
updata[3][4] = 1;
updata[2][4] = 1;
updata[1][4] = 1;
}
else if(a[i]==2)
{
updata[4][4] = 1;
updata[3][4] = 1;
updata[4][5] = 1;
updata[4][6] = 1;
}
for( ; jj<len; jj++) //操作编号
{
if(ch[jj]!='p')
ctrl(ch[jj],tmp);
if(di()) //判断是否进行合并,消除
{
jj++;
break;
}
ctrl('s',tmp); //每次自然下落
}
}
printf("Case %d: %d\n",cs++,score);
}
return 0;
}