4、界面设计说明
4.1、程序描述
主要功能:用于为玩家提供可视化的游戏界面,增加了游戏的可玩性。
可扩展性:能够适应应用要求的变化和修改,具有灵活的可扩充性。
4.2、功能界面演示
1、生成游戏界面,生成进度条。如下图:
4.21
由此图可知:time 控制游戏的进度
连连看的主界面及变形(refresh)和求助 图标按钮。
2、下图为过关时的效果界面:
4.22 图中为“失败”界面
4.23图中为胜利过关信息界面:
图中有:关闭、重玩、下一关 等按钮选项
如上图4.24 为是否退出游戏提示框
4.3、算法
- //定义游戏视图类
- public class GameView extends View
- //存储素材图片
- public int[] p_w_picpathType
- //保存所有小格子中的图片
- public int[][] grid = new int[row][col];
- //初始化加载图片的类型
- public void initType() {
- //总共要加载的图片
- int size = (row-2)*(col-2); //64
- //每类图片加载的次数(张数) 要为偶数
- int count=size/p_w_picpathType.length; //p_w_picpathType.length=16 即,16种图片
- for(int i=0; i<p_w_picpathType.length; i++){
- for(int j=0; j<count;j++){
- type.add(p_w_picpathType[i]);
- }
- }
- }
- //初始化网格的设计
- private void initGrid() {
- Random r = new Random();
- for(int i=0; i<row;i++){
- for(int j=0; j<col;j++){
- if(i==0 || i==row-1 || j==0 ||j==col-1){
- grid[i][j]=0; //四周不设置图片
- }else{
- int index=r.nextInt(type.size());
- grid[i][j]=type.get(index);
- type.remove(index);
- }
- }
- }
- }
- //设置位图的大小
- private void ititmBitmap(Context context) {
- int typeLength=p_w_picpathType.length;
- p_w_picpath=new Bitmap[typeLength];
- //重新绘制
- for(int i=0;i<typeLength;i++){
- //创建一个Bitmap的对象
- Bitmap bitmap=Bitmap.createBitmap((int)width, (int)height, Bitmap.Config.ARGB_8888);
- //对Bitmap进行绘制
- Canvas canvas = new Canvas(bitmap);
- Drawable dwr = context.getResources().getDrawable(p_w_picpathType[i]);
- dwr.setBounds(1, 1, 30, 30);
- dwr.draw(canvas);
- p_w_picpath[i]=bitmap;
- }
- }
- //在OnDraw函数中画出框格,每次进行重绘操作
- //设置背景颜色:
- Paint backGround = new Paint();
- backGround.setColor(Color.WHITE);
- //画一个矩形
- canvas.drawRect(0, 0, getWidth(), getHeight(), backGround);
- //设置网格线条的颜色
- Paint higth= new Paint();
- higth.setColor(Color.BLUE);
- //画网格
- for(int i=0;i<10;i++){
- //画横线、纵线
- canvas.drawLine(0, height*i, getWidth(), height*i, higth);
- canvas.drawLine(width*i, 0, width*i, getHeight(), higth);
- }
- //画p_w_picpath图片
- boolean test=true; //检测图片是否肖完
- for(int i=0;i<row;i++){
- for(int j=0;j<col;j++){
- if(grid[i][j]!=0){
- canvas.drawBitmap(p_w_picpath[Arrays.binarySearch(p_w_picpathType, grid[i][j])],
- i*width, j*height, null);
- test=false; ////还有图片,说明未赢
- }
- }
- }
5、主要显示及算法设计说明
5.1、程序描述
主要功能:完成图片的消除功能,消除时画线功能,重新排列功能。
可扩展性:能够适应应用要求的变化和修改,具有灵活的可扩充性。
5.2、显示界面 无
5.3、算法
5.3.1、图片的连接判断
对于选中的两个方块的销毁,它们必须符合下面3个条件:
1、选中的两个方块图案相同。
2、选中的两个方块之间没有障碍物阻碍的情况下,可以用若干个垂直的直线线段连接起来。
3、这些将它们连接起来的直线线段的折点不超过两个(连接线由x轴和y轴的平行线组成)。
我们进行分情况分析:
无拐点、一个拐点、两个拐点,设置flag进行标记这三种情况。
以下是相关代码:
- //获得一个点可向上下左右走的范围
- public int[] extend(Point a){
- int i;
- int[] aLoc = new int[4];
- //向上
- for(i=a.y-1;i>=0 && grid[a.x][i]==0;i--){
- }
- aLoc[0]=i+1;
- //向下
- for(i=a.y+1;i<row && grid[a.x][i]==0;i++){
- }
- aLoc[1]=i-1;
- //向左
- for(i=a.x-1;i>=0 && grid[i][a.y]==0;i--){
- }
- aLoc[2]=i+1;
- //向右
- for(i=a.x+1;i<col && grid[i][a.y]==0;i++){
- }
- aLoc[3]=i-1;
- return aLoc;
- }
- //用于判断水平方向是否连通
- private boolean horizon(Point a, Point b){
- if(a.x == b.x && a.y == b.y) //如果点击的是同一个图案,直接返回false
- return false;
- int x_start = a.x <= b.x ? a.x : b.x;
- int x_end = a.x <= b.x ? b.x : a.x;
- for(int x = x_start + 1; x < x_end; x++)//只要一个不是-1,直接返回false
- if(grid[x][a.y] != 0){
- return false;
- }
- return true;
- }
- //用于判断垂直方向是否连通
- private boolean vertical(Point a, Point b){
- if(a.x == b.x && a.y == b.y)
- return false;
- int y_start = a.y <= b.y ? a.y : b.y;
- int y_end = a.y <= b.y ? b.y : a.y;
- for(int y = y_start + 1; y < y_end; y++)
- if(grid[a.x][y] != 0)
- return false;
- return true;
- }
- //只有一个拐点的情况
- private boolean oneCorner(Point a, Point b){
- Point c = new Point(a.x, b.y);
- Point d = new Point(b.x, a.y);
- if(grid[c.x][c.y] == 0){
- boolean method1 = horizon(b, c) && vertical(a, c);
- if(method1){
- corner=new Point(c.x, c.y);
- }
- return method1;
- }
- if(grid[d.x][d.y] == 0){
- boolean method2 = horizon(a, d) && vertical(b, d);
- if(method2){
- corner=new Point(d.x, d.y);
- }
- return method2;
- }else{
- return false;
- }
- }
- //有两个拐点的情况
- private boolean twoCorner(Point a, Point b)
- {
- ll = scan(a, b);
- if(ll.isEmpty())
- return false;
- for(int index = 0; index < ll.size(); index++){
- Line line = (Line)ll.get(index);
- if(line.direct == 1){
- if(horizon(a, line.a) && horizon(b, line.b)){
- corner=new Point(line.a);
- corner2=new Point(line.b);
- return true;
- }
- } else{
- if(vertical(a, line.a) && vertical(b, line.b)){
- corner=new Point(line.a);
- corner2=new Point(line.b);
- return true;
- }
- }
- }
- return false;
- }
- //上面设计了一个类来判断两个拐点的情况
- //类的定义,构造函数如下
- class Line{
- public Point a;
- public Point b;
- public int direct;
- public Line(){
- a = new Point();
- b = new Point();
- }
- public Line(int direct, Point a, Point b){
- this.direct = direct;
- this.a = a;
- this.b = b;
- }
- }
- //对两个拐点的情况进行扫描,将扫描线放入Line类型的数组中
- private LinkedList scan(Point a, Point b){
- ll = new LinkedList<Line>();
- //Point c = new Point(a.x, b.y);
- //Point d = new Point(b.x, a.y);
- for(int y = a.y; y >= 0; y--)
- if(grid[a.x][y] == 0 && grid[b.x][y] == 0 && horizon(new Point(a.x, y), new Point(b.x, y)))
- ll.add(new Line(0, new Point(a.x, y), new Point(b.x, y)));
- for(int y = a.y; y < row; y++)
- if(grid[a.x][y] == 0 && grid[b.x][y] == 0 && horizon(new Point(a.x, y), new Point(b.x, y)))
- ll.add(new Line(0, new Point(a.x, y), new Point(b.x, y)));
- for(int x = a.x; x >= 0; x--)
- if(grid[x][a.y] == 0 && grid[x][b.y] == 0 && vertical(new Point(x, a.y), new Point(x, b.y)))
- ll.add(new Line(1, new Point(x, a.y), new Point(x, b.y)));
- for(int x = a.x; x < col; x++)
- if(grid[x][a.y] == 0 && grid[x][b.y] == 0 && vertical(new Point(x, a.y), new Point(x, b.y)))
- ll.add(new Line(1, new Point(x, a.y), new Point(x, b.y)));
- return ll;
- }
- //最后做总体判断,flag表示拐点的数目
- public boolean checkLink(Point a,Point b){
- if(grid[a.x][a.y] != grid[b.x][b.y])//如果图案不同,直接为false
- return false;
- if(a.y == b.y && horizon(a, b)){
- flag=0;
- return true;
- }
- if(a.x == b.x && vertical(a, b)){
- flag=0;
- return true;
- }
- if(oneCorner(a, b)){
- flag=1;
- return true;
- }
- if(twoCorner(a, b)){
- flag=2;
- return true;
- }else{
- return false;
- }
- }
5.3.2、图片消除的画线
根据flag的值分情况分析:
Flag=0时,从起点到终点画一条线即可
Flag=1时,从起点到拐点,从拐点到终点画两条线
Flag=2时,从起点到拐点,从拐点到拐点,从拐点到终点画三条线。
在做连接判断时就将路径保存下来。
//画线操作写在OnDraw函数中,corner、corner2保存拐点坐标
//每次都sleep(50)后重绘
- switch(flag){
- case 0:
- canvas.drawLine(width*(former.x + 0.5f), height*(former.y+0.5f),
- width*(current.x+ 0.5f), height*(current.y + 0.5f), p);
- flag=-1;
- SystemClock.sleep(50);
- invalidate();
- break;
- case 1:
- canvas.drawLine(width*(former.x + 0.5f), height*(former.y+0.5f),
- width*(corner.x+ 0.5f), height*(corner.y + 0.5f), p);
- canvas.drawLine(width*(corner.x + 0.5f), height*(corner.y+0.5f),
- width*(current.x+ 0.5f), height*(current.y + 0.5f), p);
- flag=-1;
- SystemClock.sleep(50);
- invalidate();
- break;
- case 2:
- canvas.drawLine(width*(former.x + 0.5f), height*(former.y+0.5f),
- width*(corner.x + 0.5f), height*(corner.y + 0.5f), p);
- canvas.drawLine(width*(corner.x + 0.5f), height*(corner.y+0.5f),
- width*(corner2.x+ 0.5f), height*(corner2.y + 0.5f), p);
- canvas.drawLine(width*(corner2.x + 0.5f), height*(corner2.y+0.5f),
- width*(current.x+ 0.5f), height*(current.y + 0.5f), p);
- flag=-1;
- SystemClock.sleep(50);
- invalidate();
- break;
- default:
- break;
- }
5.3.3、重新排列
隔一段时间后,将原有的排列随机打乱,进行重新排列
//对当前界面中的图片进行重新排列
- public void reDraw(){
- Random r = new Random();
- type= new ArrayList<Integer>();
- for(int i=0;i<row; i++){
- for(int j=0; j <col;j++){
- if(grid[i][j]!=0){
- type.add(grid[i][j]);
- }
- }
- }
- for(int i=0;i<row; i++){
- for(int j=0; j <col;j++){
- if(grid[i][j]!=0){
- int index = r.nextInt(type.size());
- grid[i][j] = type.get(index);
- type.remove(index);
- }
- }
- }
- former_i=former_j=0;
- former.x=former.y=0;
- invalidate();
- }
- //重新排列界面中的图片
- private void reStart() {
- GameActivity.refresh=true;
- initType();
- initGrid();
- invalidate();
- }