思路:
1. 把掉落的叫做方块,下面已经搭好的叫做城堡
2. 让方块从给定的列往下掉,每次下降一行,直到下面两种情况停止掉落:一是方块含有 1 的最下面一行碰到城堡底部, 而是方块中有 1 碰到城堡中的 1。例如下图:
要么第一行达到城堡底部,要么在中途碰到其他为 1 的城堡部分。
3. 为了简单,把原来城堡的高度 15 增加到 18 或以上,这样可以减少一些麻烦的判断。由于只有 0 和 1 ,适当地运用一下位运算也是一个不错的选择。
代码如下:
#include <iostream>
#include <cmath>
#include <memory.h>
using namespace std;
int main()
{
int grid[19][10]; //grid是城堡
int pattern[4][4]; //pattern是方格
int pos(0);
memset(grid, 0, sizeof(grid));
for(int i=0; i<150; i++) cin >> grid[i/10][i%10];
for(int i=0; i<16; i++) cin >> pattern[i/4][i%4];
cin>> pos;
pos -= 1; //从 0 开始
int notNull; //**从下往上**第一个非空的行,比如上图的直线 notNull = 0
for(int i = 3; i>=0; i--)
{
if(pattern[i][0] | pattern[i][1] | pattern[i][2] | pattern[i][3])
{notNull = i; break;}
}
int row = 0;
while(1)
{
for(int i = 0;i<4; i++)
for(int j= 0; j<4; j++)
if((row + notNull == 15) || (grid[row + i][pos + j] & pattern[i][j]))
//上句if判断的是要么碰到底部要么中途碰到有 1 的城堡
goto out; //跳出多层循环,goto是个不错的选择
++row;
}
out:
row -= 1; //此时的 row刚好是城堡底部的下面一行(注意上面的if判断里面的 15)或者是刚好碰到那一行,所以要减 1
for(int i = 0;i<4; i++)
for(int j= 0; j<4; j++)
grid[row+i][pos + j] |= pattern[i][j];
for(int i=0; i<15; i++)
{
for(int j=0; j<10; j++)
cout << grid[i][j] <<" ";
cout<<endl;
}
return 0;
}