消消乐游戏中,如何计算一组连续方块的数量?

TESJackeyIove 2018-09-09 04:15:11
有一个二维数组,里面有几种不一样的元素,类似于下图,现在给定一个坐标,如何计算坐标位置及其周围一组连续相同元素的数量?
...全文
753 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2018-09-10
  • 打赏
  • 举报
回复
再供参考:
//试题编号:0186
//海龟圈地
//难度级别:D; 运行时间限制:1000ms; 运行空间限制:51200KB; 代码长度限制:2000000B
//试题描述
// 海龟小蛮在沙滩上趾高气扬地走来走去,并且蛮横地宣布:“凡我足迹所到之处均为本海龟的领地。”
// 海龟的任何行动均可分解为下面三个基本动作:
// f 向前爬一格
// l 原地左转90度
// r 原地右转90度
// 由于小蛮不允许别的海龟经过它的领地,所以,由它足迹围成的封闭区域也就都成了它的领地。
// 你的任务是编程序根据文件输入的小蛮的一系列基本动作,计算出小蛮共霸占了多少格的领地。
// 程序文件主名为turtle。
// 为加深对题意的理解,我们观察下面的基本动作序列:
// flffflfffrfrrffflf
// 小蛮在出发点当然会留下足迹#,如果把它开始的方向设为向下,可以把它的足迹(用*标出的位置)画成下面的示意图:
// ****
// * *
// # *
// ****
// 显然,小蛮的领地总数为15格。
//输入
// 其中只有一个长度不超过1000的字符串,且该字符串不包含'f'、'l'、'r'之外的字符。
//输出
// 其中只有一个正整数,即领地总格数。
//输入示例
// flffflfffrfrrffflf
//输出示例
// 15
//其他说明
// 2011年北京市海淀区中学组赛题
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXN 1000
static char n[2*MAXN+2][2*MAXN+2];//记录某处被爬过信息:0未爬过|1爬过
char f;//当前方向'N'|'S'|'W'|'E'
int x,y;//当前位置
char p[MAXN+1];
int i,L;
int a,b,h,t;
int sp=0;
int x1[MAXN];
int x2[MAXN];
int y1[MAXN];
int yy1,xx1,xx2;
void push(int ay1,int ax1,int ax2) {
y1[sp]=ay1;
x1[sp]=ax1;
x2[sp]=ax2;
if (sp<MAXN-1) {
sp=sp+1;
} else {
printf("stack overflow!\n");
exit(1);
}
}
void pop(void) {
sp=sp-1;
yy1=y1[sp];
xx1=x1[sp];
xx2=x2[sp];
}
//void show() {
// int zy,zx;
//
// for (zy=0;zy<2*MAXN+2;zy++) {
// for (zx=0;zx<2*MAXN+2;zx++) {
// printf("%d",n[zy][zx]);
// }
// printf("\n");
// }
// printf("\n");
//}
void scanlinefill() {
int xx,ax1,ax2;
while (1) {
if (sp<=0) break;//
pop();
// printf("O yy1,xx1,xx2=%d,%d,%d\n",yy1,xx1,xx2);
for (xx=xx1;xx<=xx2;xx++) n[yy1][xx]=2;//填充本条线
yy1++;
if (yy1<=2*MAXN)
for (xx=xx1;xx<=xx2;xx++) {//从左往右考查紧挨下面一条线各点
if (n[yy1][xx ]==0) {
ax1=xx-1;
while (1) {//向左找非0点
if (n[yy1][ax1]!=0) break;
ax1--;
}
ax1++;//非0点右边为新扫描线左点
}
if (n[yy1][xx ]==0) {
ax2=xx+1;
while (1) {//向右找非0点
if (n[yy1][ax2]!=0) break;
ax2++;
}
ax2--;//非0点左边为新扫描线右点
// printf("I yy1,ax1,ax2=%d,%d,%d\n",yy1,ax1,ax2);
push(yy1,ax1,ax2);//记录新扫描线到堆栈中
xx=ax2+1;//下次循环从该新扫描线右点的右边开始考查
}
}
}
}
int main() {
scanf("%s",p);
f='S';
y=MAXN;
x=MAXN;
n[y][x]=1;
L=strlen(p);
for (i=0;i<L;i++) {
switch (p[i]) {
case 'f':
switch (f) {
case 'N':y--;n[y][x]=1;break;
case 'S':y++;n[y][x]=1;break;
case 'W':x--;n[y][x]=1;break;
case 'E':x++;n[y][x]=1;break;
}
break;
case 'l':
switch (f) {
case 'N':f='W';break;
case 'S':f='E';break;
case 'W':f='S';break;
case 'E':f='N';break;
}
break;
case 'r':
switch (f) {
case 'N':f='E';break;
case 'S':f='W';break;
case 'W':f='N';break;
case 'E':f='S';break;
}
break;
}
}
// show();
for (y=0;y<2*MAXN+2;y++) {n[y][0]=2;n[y ][2*MAXN+1]=2;}
for (x=0;x<2*MAXN+2;x++) {n[0][x]=2;n[2*MAXN+1][x ]=2;}
// show();
push(1,1,2*MAXN);//从(y1==1,x1==1,x2==2*MAXN)开始
scanlinefill();//往下使用扫描线种子填充算法填充2
// show();
a=0;
for (y=0;y<2*MAXN+1;y++) {
for (x=0;x<2*MAXN+1;x++) {
if (n[y][x]!=2) a++;
}
}
printf("%d\n",a);
return 0;
}
zangfong 2018-09-10
  • 打赏
  • 举报
回复
就是用1楼所说的方法,深度优先遍历(dfs)。简单举个例子,bubble数组就是泡泡,vivist数组用于表示是否访问过该坐标,访问过就标记为1,以避免重复访问:
#include<stdio.h>

#define MAXN 11
int bubble[MAXN][MAXN] = {0};
int visit[MAXN][MAXN] = {0};
int cnt = 0;

void dfs(int x, int y, int value)
{
if(visit[x][y] == 1 || (bubble[x][y] != value)) return;
cnt++;
visit[x][y] = 1;

dfs(x-1,y,value);
dfs(x,y-1,value); /* bubble[x][y] */ dfs(x,y+1,value);
dfs(x+1,y,value);
}

int main()
{
bubble[1][5] = bubble[1][4] = bubble[1][6] = bubble[1][7] = bubble[2][4] = bubble[2][3] = 1 ;
bubble[3][2] = bubble[3][5] = bubble[2][5] = bubble[3][6] = 1;

int i,j;
for(i = 0; i < MAXN; i++)
{
for(j = 0; j < MAXN; j++)
{
printf("%d ",bubble[i][j]);
}
printf("\n");
}

cnt = 0;
int value = bubble[1][5];
dfs(1,5,value);
printf("相邻块总数=%d\n",cnt);

return 0;
}


不过,DFS递归遍历,要注意边界问题,数组四周的最外围一圈,需要设置为不会与buuble中的泡泡的值重复的数字,如-1,这样就形成了dfs递归的天然终止条件,也就不用考虑数组访问是否越界了。
这个例子中使用全局变量cnt来记录相邻泡泡的总数,这个cnt和visit数组在每次调用dfs之前都要重新置0。

AlbertS 2018-09-10
  • 打赏
  • 举报
回复
我也只能想到遍历,从指定点向四个方向推进
赵4老师 2018-09-10
  • 打赏
  • 举报
回复
仅供参考:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <graphics.h>
int xs[10000];
int ys[10000];
int i=0,xx,yy;
int fc,bc;
void push(int x,int y) {
xs[i]=x;
ys[i]=y;
if (i<10000-1) {
i=i+1;
} else {
printf("stack overflow!\n");
exit(1);
}
}
void pop(void) {
i=i-1;
xx=xs[i];
yy=ys[i];
}
int check(int x,int y) {
int c;

c=getpixel(x,y); /* 获取当前点的颜色 */
return ((c!=bc)&&(c!=fc));/* 如果颜色为边界色或填充色则不填充 */
}
void seedfilling(int x,int y,int fill_color,int boundary_color) {
fc=fill_color;
bc=boundary_color;
push(x,y);
while (1) {
if (i<=0) return;
pop();
if (check(xx,yy)) {
putpixel(xx, yy, 14);getch(); /* 加上这行显示当前填充状态 */

putpixel(xx, yy, fill_color); /* 画点 */

if (check(xx-1,yy )) push(xx-1,yy );
if (check(xx ,yy+1)) push(xx ,yy+1);
if (check(xx ,yy-1)) push(xx ,yy-1);
if (check(xx+1,yy )) push(xx+1,yy );
/* 去掉下面四句就是四连通 */
if (check(xx-1,yy-1)) push(xx-1,yy-1);
if (check(xx-1,yy+1)) push(xx-1,yy+1);
if (check(xx+1,yy-1)) push(xx+1,yy-1);
if (check(xx+1,yy+1)) push(xx+1,yy+1);
}
}
}
void main() {
int a,b,color;
int gdriver = DETECT, gmode, errorcode;
int poly[10];

initgraph(&gdriver, &gmode, "d:\\bc\\bgi");
a=150;
b=140;
color=4;
poly[0]=110;/* 第一个点的x坐标以及y坐标 */
poly[1]=110;
poly[2]=200;/* 第二点 */
poly[3]=105;
poly[4]=170;/* 第三点 */
poly[5]=120;
poly[6]=150;/* 第四点 */
poly[7]=170;
poly[8]=110;/* 多边形的起点与终点一样 */
poly[9]=110;
drawpoly(5,poly);/* 显示各点连接起来的多边形 */

/* 保证边界对八连通是封闭的 */
setviewport(0,1,600,300,0);
drawpoly(5,poly);/* 显示各点连接起来的多边形 */
setviewport(1,0,600,300,0);
drawpoly(5,poly);/* 显示各点连接起来的多边形 */
setviewport(1,1,600,300,0);
drawpoly(5,poly);/* 显示各点连接起来的多边形 */

/* 恢复默认viewport */
setviewport(0,0,600,300,0);

seedfilling(a,b,color,15); /* 种子填充多边形 */

getch();
closegraph();
}

33,311

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧