连连看游戏笔记

整理下自己最近尝试 开发的连连看小游戏吧,实现了游戏基本的一些功能,例如碰撞是否能连线,连线,点击标记等一些很基本的功能。图片来自于互联网,下面是游戏运行的一些图:

下面来说下开发过程中遇到的一些问题吧:

1.在xml里嵌套一个view抛出异常,谷歌百度,问题解决了微笑,原来是要实现一个构造函数即可,注意,在xml里嵌套的那个view报名不要写错了,例如可以写成:

<com.love.myView.GameView 
         android:layout_width="fill_parent"
         android:layout_height="fill_parent"
         android:id="@+id/gameView"/>


要实现的那个构造函数

public GameView(Context context, AttributeSet attrs) {//注:在xml里使用这一个类必须得添加该构造函数
		super(context, attrs);
		paint = new Paint();
		//在view里获取分辨率
		DisplayMetrics dm = context.getApplicationContext().getResources().getDisplayMetrics();
		screenWidth = dm.widthPixels;
		screenHeight = dm.heightPixels;
		//per_Row = screenHeight/ ROW;
		//per_Col = (screenWidth - 20)/ COL;
		//init();
		//canvas = new Canvas();
		bmp = new Bitmap[id.length];
		setFocusable(true);
		setFocusableInTouchMode(true);
	}


 

2.在xml里嵌套的那个view如何确定大小

自己也纠结了这个好久,到最后还是被我找到了,哈哈,其实只要复写protected void onSizeChanged(int w, int h, int oldw, int oldh)函数即可,部分代码如下:

@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		// TODO Auto-generated method stub
		width = w / ROW;
		height = h / COL;
		System.out.println("每列的宽度为:" + width);
		super.onSizeChanged(w, h, oldw, oldh);
	}


3.如何判断所点击的图能否连线

这个我是参照一位前辈写的,博客网址是:http://www.iteye.com/topic/480020,里面讲的灰常清楚,非常值得去看下。思路是:分为四种判断形式:分别为水平判断,垂直判断,一个拐角的判断和两个拐角的判断。自己有点难懂的是对于两个拐角的实现,这里说下自己的理解吧:首先可以通过scan函数来保存那些两个拐角的点,例如有源点A和目标点D,可以先假设A点向右扫描,扫描到B,建立C点坐标 ,这时如果可以保证B,C之间可以直接垂直连通,那么就可以通过判断A和B,C和D是否同时水平连通,如果符合的话,这样就说明A和D符合两个拐角 ,可以连线了。不符合的话,可以继续扫描到B1,建立坐标C1,继续判断,其他情况也类似。scan函数所做的就是在B和C可以直接连通的情况下,把B和C点加入链表中,到时再取出来判断。图如下所示:

下面是部分代码:

private boolean horizon(Point1 a, Point1 b) {//水平判断 
		if (a.x == b.x && a.y == b.y)
			return false;
		int x_start = a.y <= b.y ? a.y : b.y;
		int x_end = a.y <= b.y ? b.y : a.y;
		for (int x = x_start + 1; x < x_end; x++)
			if (grid[a.x][x] != 0) {
				return false;
			}
		p = new Point1[] { a, b };
		lineType = H_LINE;
		return true;
	}
	
	public boolean vertical(Point1 a,Point1 b)//垂直判断
	{
		if(a.x == b.x && a.y == b.y)return false;
		int start = a.x <= b.x ? a.x:b.x;
		int end = a.x >= b.x?a.x:b.x;
		for(int i = start + 1; i < end; i++)
		{
			if(grid[i][a.y] != 0)return false;
		}
		p = new Point1[]{a, b };
		lineType = V_LINE;
		return true;
	}
	
	public boolean oneCorner(Point1 a,Point1 b)//一个拐角的判断
	{
		Point1 c = new Point1(a.x, b.y);
		Point1 d = new Point1(b.x, a.y);
		if(grid[c.x][c.y] == 0)
		{
			boolean method1 = horizon(a, c) && vertical(b, c);
			p = new Point1[] { a, new Point1(c.x, c.y), b };
			lineType = ONE_LINE;
			return method1;
		}
		if(grid[d.x][d.y] == 0)
		{
			boolean method2 = vertical(a, d) && horizon(b, d);
			p = new Point1[] { a, new Point1(d.x, d.y), b };
			lineType = ONE_LINE;
			return method2;
		}
		else {return false;}
	}
	
	/*
	 * scan函数实现的是原点所扫描的上下左右四个方向以及终点组成的线的两个坐标加入到Linkedlist表中去
	 */
	private LinkedList<Line> scan(Point1 a,Point1 b) {//扫描所有可走路径
		li = new LinkedList<Line>();
		for (int y = a.y; y >= 0; y--)//纵向向上扫描,把纵向所有向上的点都加进去
			if (grid[a.x][y] == 0 && grid[b.x][y] == 0
					&& vertical(new Point1(a.x, y), new Point1(b.x, y)))
				li.add(new Line(0, new Point1(a.x, y), new Point1(b.x, y)));

		for (int y = a.y; y < ROW; y++)//纵向向下扫描,把纵向所有向上的点都加进去
			if (grid[a.x][y] == 0 && grid[b.x][y] == 0
					&& vertical(new Point1(a.x, y), new Point1(b.x, y)))
				li.add(new Line(0, new Point1(a.x, y), new Point1(b.x, y)));

		for (int x = a.x; x >= 0; x--)//横向向左扫描,把横向所有向左的点都加进去
			if (grid[x][a.y] == 0 && grid[x][b.y] == 0
					&& horizon(new Point1(x, a.y), new Point1(x, b.y)))
				li.add(new Line(1, new Point1(x, a.y), new Point1(x, b.y)));

		for (int x = a.x; x < COL; x++)//横向向右扫描,把横向所有向右的点都加进去
			if (grid[x][a.y] == 0 && grid[x][b.y] == 0
					&& horizon(new Point1(x, a.y), new Point1(x, b.y)))
				li.add(new Line(1, new Point1(x, a.y), new Point1(x, b.y)));

		return li;
	}
	
	private boolean twoCorner(Point1 a,Point1 b)//两个拐角的判断
	{
		li = scan(a, b);
		if(li.isEmpty())return false;
		for (int index = 0; index < li.size(); index++) {//遍历所有可能的情况
			Line line = li.get(index);
			if(line.direct == 1)
			{
				if(vertical(a, line.a) && vertical(b, line.b))
				{
					System.out.println("二次转角");
					p = new Point1[]{a,line.a,line.b,b};
					lineType = TWO_LINE;
					return true;
				}
			}
			else  if(horizon(a, line.a) && horizon(b, line.b))
			{
				p = new Point1[]{a,line.a,line.b,b};
				System.out.println("二次转角");
				lineType = TWO_LINE;
				return true;
			}
		}
		return false;
	}
	public boolean checkLink(Point1 a,Point1 b)
	{
		if (grid[a.x][a.y] != grid[b.x][b.y])// 如果图案不同,直接为false
			return false;
		if (a.x == b.x && horizon(a, b))
			return true;
		if (a.y == b.y && vertical(a, b))
			return true;
		if (oneCorner(a, b))
			return true;
		else
			return twoCorner(a, b);
	}


4.怎样实现连线

可以这样做:建立一个数组用来保存连线 所有 的点,在判断可以连线的时候可以把连线的类型保存下来,例如,可以是一个拐角 ,两个拐角等。等到 在画图的时候就可以通过判断连线的类型,把数组中的点取出来,在进行画线,例如,如果是两个拐角的话,数组就应该保存四个节点, 如果是一个拐角的话,就应该是三个节点。部分代码如下:

public void drawLines(Canvas canvas){
		need_line = false;
		Paint lineColor = new Paint();
		lineColor.setStrokeWidth(3.0f);
		lineColor.setColor(Color.GREEN);
		switch (lineType) {
		case H_LINE:
			canvas.drawLine(p[0].x * width + width / 2, p[0].y * height
					+ height / 2, p[1].x * width + width / 2, p[1].y
					* height + height / 2, lineColor);
			break;

		case V_LINE:
			canvas.drawLine(p[0].x * width + width / 2, p[0].y * height
					+ height / 2, p[1].x * width + width / 2, p[1].y
					* height + height / 2, lineColor);
			break;
		case ONE_LINE:
			canvas.drawLine(p[0].x * width + width / 2, p[0].y * height
					+ height / 2, p[1].x * width + width / 2, p[1].y
					* height + height / 2, lineColor);
			canvas.drawLine(p[1].x * width + width / 2, p[1].y * height
					+ height / 2, p[2].x * width + width / 2, p[2].y
					* height + height / 2, lineColor);
			break;
		case TWO_LINE:
			canvas.drawLine(p[0].x * width + width / 2, p[0].y * height
					+ height / 2, p[1].x * width + width / 2, p[1].y
					* height + height / 2, lineColor);
			canvas.drawLine(p[1].x * width + width / 2, p[1].y * height
					+ height / 2, p[2].x * width + width / 2, p[2].y
					* height + height / 2, lineColor);
			canvas.drawLine(p[3].x * width + width / 2, p[3].y * height
					+ height / 2, p[2].x * width + width / 2, p[2].y
					* height + height / 2, lineColor);
			break;
		default:
			break;
		}


 

让线一会消失的思路,我的思路是这样的。设置一个布尔变量,如果判断需要画线的时候,布尔变量为真,在 绘制函数中绘图,画完之后,布尔变量为假,在invalidate重新刷新一次,不过这样做效率不高,不过自己也没找到啥好方法,这个只能留给以后再慢慢想了哭。同样,这个问题,也同样困扰了我点击标记图片为已选,功能是实现了,可是反应有点慢,标记图片部分代码如下:

public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		System.out.println("点击了" + event.getX() / width +"列的图片");
		if(event.getAction() != MotionEvent.ACTION_DOWN)return true;
		int num_x = (int) (event.getX() / width);
		int num_y = (int) (event.getY() / height);
		if(grid[num_x][num_y] == 0)
		{
			return true;
		}
		else {
			if(!hasSelect)//如果当前没有选定图案
			{
				hasSelect = true;
				p1 = new Point1(num_x, num_y);
				//invalidate(rect);//消除点击图片的标志,待定中
				rect.set(num_x * ((int)width),num_y * ((int)height),
						(num_x + 1) * ((int)width),(num_y + 1) * ((int)height));
				//isSelected = true;
				invalidate(rect);//局部刷新特定的区域(这里是一个网格 内的颜色)
			}
			else {//之前已经选定了图案
				p2 = new Point1(num_x, num_y);
				if(checkLink(p2, p1))
				{
					need_line = true;
					rid_rect = true;
					System.out.println("可以消去");
					hasSelect = false;
					hero_num = hero_num - 2;
					grid[p1.x][p1.y] = 0;
					grid[p2.x][p2.y] = 0;
					invalidate();//待定中
					//invalidate(rect);
				}
				else//如果之前选择了图案而这次选择的图案不能连线
				{
					System.out.println("不能消去");
					hasSelect = true;
					p1 = p2;
					invalidate(rect);//消除点击图片的标志
					rect.set(num_x * ((int)width),num_y * ((int)height),
							(num_x + 1) * ((int)width),(num_y + 1) * ((int)height));
					//isSelected = true;
					invalidate(rect);
				}
			}
		}
		//click[0] = num_x;
		//click[1] = num_y;

		
		//selImage = BitmapFactory.decodeResource(getResources(), grid[num_x][num_y]);
		//invalidate();
		return super.onTouchEvent(event);
	}


还有一个问题就是,游戏过程中 不能自动检测游戏是否进入了“死局"的情况。哭,问题还是存在不少,不扯了,以后还得要更加努力加油啊奋斗

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园的建设目标是通过数据整合、全面共享,实现校园内教学、科研、管理、服务流程的数字化、信息化、智能化和多媒体化,以提高资源利用率和管理效率,确保校园安全。 智慧校园的建设思路包括构建统一支撑平台、建立完善管理体系、大数据辅助决策和建设校园智慧环境。通过云架构的数据中心与智慧的学习、办公环境,实现日常教学活动、资源建设情况、学业水平情况的全面统计和分析,为决策提供辅助。此外,智慧校园还涵盖了多媒体教学、智慧录播、电子图书馆、VR教室等多种教学模式,以及校园网络、智慧班牌、校园广播等教务管理功能,旨在提升教学品质和管理水平。 智慧校园的详细方案设计进一步细化了教学、教务、安防和运维等多个方面的应用。例如,在智慧教学领域,通过多媒体教学、智慧录播、电子图书馆等技术,实现教学资源的共享和教学模式的创新。在智慧教务方面,校园网络、考场监控、智慧班牌等系统为校园管理提供了便捷和高效。智慧安防系统包括视频监控、一键报警、阳光厨房等,确保校园安全。智慧运维则通过综合管理平台、设备管理、能效管理和资产管理,实现校园设施的智能化管理。 智慧校园的优势和价值体现在个性化互动的智慧教学、协同高效的校园管理、无处不在的校园学习、全面感知的校园环境和轻松便捷的校园生活等方面。通过智慧校园的建设,可以促进教育资源的均衡化,提高教育质量和管理效率,同时保障校园安全和提升师生的学习体验。 总之,智慧校园解决方案通过整合现代信息技术,如云计算、大数据、物联网和人工智能,为教育行业带来了革命性的变革。它不仅提高了教育的质量和效率,还为师生创造了一个更加安全、便捷和富有智慧的学习与生活环境。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值