待施工
#include <iostream>
using namespace std;
struct tagInfo {
int event;
int dir;//旋转方向
int col;//主块在第几列,主块用于控制旋转
int val[2];//两个块的颜色
};
tagInfo tInfo;//当前要下落的块的信息
struct Point {
int x;
int y;
};
int map[50][50] = { 0 };//保存所有的块
int tail[50] = { 0 };//指向第i列为空的行
int mark[50][50];//被标记的块会在updatemap里进行删除
int board_width;//放置块的那个宽度,范围是0-board_width-1
int maxcol = -1;//最高列的块数,达到一定块数后game over
//用于深搜,查找是否有未消除的块
Point drop[10];
int drop_num;
int dfs_search_num;
//方向
int dir[4][2] = {
0,1,
0,-1,
1,0,
-1,0
};
//初始化宽度及每列
void init(int width) {
board_width = width;
for (int i = 0; i < board_width; i++) {
tail[i] = 0;
}
}
//设置普通块的信息,颜色可以不同
void newBlock(int block[]) {
tInfo.event = 1;
tInfo.dir = 0;
tInfo.col = 1;
tInfo.val[0] = block[0];
tInfo.val[1] = block[1];
}
//旋转角度只有四种:0,90,180,270。
//在中间位置主块的列不会变化
//在右侧转到0度时,主块不贴墙,其余情况都贴墙
//在左侧转到180度时,主块不贴墙,其余情况都贴墙
//这里有点问题,移动后再旋转不行
void rotate(int angle) {
tInfo.dir = (tInfo.dir + angle) % 4;
if (tInfo.dir == 0 && tInfo.col == board_width - 1) {
tInfo.col = board_width - 2;
}
if (tInfo.dir == 2 && tInfo.col == 0) {
tInfo.col = 1;
}
}
//移动:改变主块位置,再根据dir判断有没有越界
void move(int distance) {
tInfo.col += distance;
if (tInfo.col >= 1 && tInfo.col <= board_width - 2) return;//在中间不会越界
if (tInfo.dir == 0 && tInfo.col >= board_width - 1) {//挪到右边界外边了,挪回来
tInfo.col = board_width - 2;
return;
}
if (tInfo.col > board_width - 1) {
tInfo.col = board_width - 1;
return;
}
if (tInfo.dir == 2 && tInfo.col <= 0) {//挪到左边界外边了,挪回来
tInfo.dir = 1;
return;
}
if (tInfo.col < 0) {
tInfo.dir = 0;
return;
}
}
//设置特殊块,life直接设置为负数,mark后+1归0
void hinder(int count, int life) {
tInfo.event = 2;
for (int i = 0; i < count; i++) {
map[i][tail[i]++] = -1 * life;
}
}
//深搜找与map[x][y]颜色相同的块,记录下它的数目
//这里也有点冗余,用完的drop没有及时删除
void dfs(int x, int y) {
if (map[x][y] == 0) return;
mark[x][y] = 1;
dfs_search_num++;
for (int i = 0; i < 4; i++) {
int nextx = x + dir[i][0];
int nexty = y + dir[i][1];
if (nextx < 0 || nextx >= board_width || nexty < 0 || nexty >= tail[nextx]) continue;
if (mark[nextx][nexty] == 1) continue;
if (map[x][y] == map[nextx][nexty])
dfs(nextx, nexty);
}
}
//清理mark
void clear(int x, int y) {
if (map[x][y] == 0) return;
mark[x][y] = 0;
for (int i = 0; i < 4; i++) {
int nextx = x + dir[i][0];
int nexty = y + dir[i][1];
if (nextx < 0 || nextx >= board_width || nexty < 0 || nexty >= tail[nextx]) continue;
if (mark[nextx][nexty] == 0) continue;
if (map[x][y] == map[nextx][nexty])
clear(nextx, nexty);
}
}
//检查map[i][j]周围是否有mark了的有颜色的块
int check(int i, int j) {
for (int k = 0; k < 4; k++) {
int x = i + dir[k][0];
int y = j + dir[k][1];
if (x < 0 || x >= board_width || y < 0 || y >= tail[x]) continue;
if (mark[x][y] == 1 && map[x][y] > 0) return 1;
}
return 0;
}
void markhinder() {
for (int i = 0; i < board_width; i++) {
for (int j = 0; j < tail[i]; j++) {
if (map[i][j] < 0) {//找到hinder,如果被炸了一下,改变数值,如果变成0,mark为1
if (check(i, j) != 0) {
map[i][j] += 1;
mark[i][j] = map[i][j] == 0 ? 1 : 0;
}
}
}
}
}
//更新map,将mark的块删除,并记下新的要深搜的drop
void updatemap() {
bool flag = false;
for (int i = 0; i < board_width; i++) {
int k = 0;
for (int j = 0; j < tail[i]; j++) {
if (mark[i][j] == 1) {
mark[i][j] = 0;
map[i][j] = 0;
flag = true;
continue;
}
map[i][k++] = map[i][j];
if (flag && map[i][k-1] > 0) {//被炸之后掉下来的有颜色的块都有可能能继续消除
drop[drop_num].x = i;
drop[drop_num++].y = k - 1;
}
}
tail[i] = k;
flag = false;
}
}
//找同颜色的块,多于四个就能消除
void solve(Point lhs, Point rhs) {
drop_num = 2;
drop[0] = lhs;
drop[1] = rhs;
while (drop_num != 0) {
for (int i = drop_num - 1; i >= 0; i--) {
if (mark[drop[i].x][drop[i].y] == 1) continue;
dfs_search_num = 0;
dfs(drop[i].x, drop[i].y);
cout << "同颜色块数为:" << dfs_search_num << endl;
if (dfs_search_num < 4) {
drop_num--;
clear(drop[i].x, drop[i].y);
}
}
markhinder();
updatemap();
}
}
//让普通块落下,并计算最高列
int land() {
Point pt1, pt2;
if (tInfo.event == 1) {
switch (tInfo.dir)//确定普通块的降落位置,加入map
{
case 0://水平方向
pt1.x = tInfo.col;
pt1.y = tail[tInfo.col];
map[tInfo.col][tail[tInfo.col]++] = tInfo.val[0];
pt2.x = tInfo.col + 1;
pt2.y = tail[tInfo.col + 1];
map[tInfo.col + 1][tail[tInfo.col + 1]++] = tInfo.val[0];
break;
case 1:
pt1.x = tInfo.col;
pt1.y = tail[tInfo.col];
map[tInfo.col][tail[tInfo.col]++] = tInfo.val[1];
pt2.x = tInfo.col;
pt2.y = tail[tInfo.col];
map[tInfo.col][tail[tInfo.col]++] = tInfo.val[0];
break;
case 2:
pt1.x = tInfo.col;
pt1.y = tail[tInfo.col];
map[tInfo.col][tail[tInfo.col]++] = tInfo.val[0];
pt2.x = tInfo.col - 1;
pt2.y = tail[tInfo.col - 1];
map[tInfo.col][tail[tInfo.col - 1]++] = tInfo.val[1];
break;
case 3:
pt1.x = tInfo.col;
pt1.y = tail[tInfo.col];
map[tInfo.col][tail[tInfo.col]++] = tInfo.val[0];
pt2.x = tInfo.col;
pt2.y = tail[tInfo.col];
map[tInfo.col][tail[tInfo.col]++] = tInfo.val[1];
break;
}
solve(pt1, pt2);//看看能不能消除
}
//找到最高列
int max = 0;
for (int i = 0; i < board_width; i++) {
max = tail[i] > max ? tail[i] : max;
}
return max;
}
int main() {
int width;
cout << "请输入宽度" << endl;
cin >> width;
init(width);
while (1) {
cout << "创建普通块还是特殊块?" << endl;
int key;
cin >> key;
switch (key)
{
case 1:
cout << "输入普通块的两种颜色" << endl;
int block[2];
cin >> block[0] >> block[1];
newBlock(block);
cout << "旋转角度?" << endl;
int angle;
cin >> angle;
rotate(angle);
cout << "移动距离?" << endl;
int distance;
cin >> distance;
move(distance);
maxcol = land();
break;
case 2:
cout << "输入块数和生命值" << endl;
int count, life;
cin >> count >> life;
hinder(count, life);
maxcol = land();
break;
default:
break;
}
cout << "目前最高为:" << maxcol << endl;
if (maxcol > 6) {
cout << "游戏结束" << endl;
break;
}
}
}