zoukankan      html  css  js  c++  java
  • 安卓---拼图---慕课网视频复原

      有一段时间没写安卓的代码,慢慢的有点忘了,这个按照视频一步一步来的复原

    主要步骤:

    1.把一张大图分成多个方块图,GridLayout实现

    2.设置某个方块为缺口(拼图是总有一个空白的方块)

    3.点击交换缺口与相邻方块的数据

    4.获取手势,手势交换缺口与相邻方块的数据

    5.打乱顺序

    6.判断结束

    按钮背景,放在drawable文件夹下,命名bg_btn

    <?xml version="1.0" encoding="utf-8"?>
    
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:state_pressed="true">
            <!-- 定义当button 处于pressed 状态时的形态。-->
            <shape>
                <gradient android:startColor="#8600ff" />
                <stroke android:width="2dp" android:color="#000000" />
                <corners android:radius="5dp" />
                <padding android:left="10dp" android:top="10dp"
                    android:bottom="10dp" android:right="10dp" />
            </shape>
        </item>
        
        <item android:state_pressed="false">
            <!-- 定义当button 处于pressed 状态时的形态。-->
            <shape>
                <gradient android:startColor="#aeaeae" android:endColor="#b0b0b0" />
                <stroke android:width="2dp" android:color="#333333" />
                <corners android:radius="5dp" />
                <padding android:left="10dp" android:top="10dp"
                    android:bottom="10dp" android:right="10dp" />
            </shape>
        </item>
        
    </selector>
    View Code

    布局文件activity_main.xml

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity" >
    
        <GridLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/gl_main_game"
            android:columnCount="4"
            android:rowCount="5"
            android:fillViewport="true"
            >
    
        </GridLayout>
        
        <Button
            android:id="@+id/btn_start"
            android:layout_width="120px"
            android:layout_height="60px"
            android:layout_marginRight="5px"
            android:layout_marginLeft="5px"
            android:layout_centerHorizontal="true"
            android:layout_alignParentBottom="true"
            android:layout_marginBottom="20px"
            android:background="@drawable/bg_btn"
            android:text="Start" />
        
        <Button
            android:id="@+id/btn_back"
               android:layout_width="120px"
            android:layout_height="60px"
            android:layout_toLeftOf="@+id/btn_start"
            android:layout_alignParentBottom="true"
            android:layout_marginBottom="20px"
            android:background="@drawable/bg_btn"
            android:text="Back" />
            
        <Button
            android:id="@+id/btn_select"
               android:layout_width="120px"
            android:layout_height="60px"
            android:layout_toRightOf="@+id/btn_start"
            android:layout_alignParentBottom="true"
            android:layout_marginBottom="20px"
            android:background="@drawable/bg_btn"
            android:text="Select" />
    
    </RelativeLayout>
    View Code

    主函数实现逻辑

    package com.example.jigsaw;
    
    import android.os.Bundle;
    import android.view.GestureDetector;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.animation.Animation;
    import android.view.animation.Animation.AnimationListener;
    import android.view.animation.TranslateAnimation;
    import android.widget.Button;
    import android.widget.GridLayout;
    import android.widget.ImageView;
    import android.widget.RelativeLayout;
    import android.widget.Toast;
    import android.app.Activity;
    import android.graphics.Bitmap;
    import android.graphics.drawable.BitmapDrawable;
    import android.view.GestureDetector.OnGestureListener;//手势监听包,不提示导入??
    
    public class MainActivity extends Activity {
    
        /**当前移动动画是否正在执行*/
        private boolean isAnimRun = false;
        /** 利用二维数组创建若干小方块 **/
        private ImageView[][] iv_game_arr = new ImageView[5][4];
        /** 游戏主界面 **/
        private GridLayout gl_main_game;
        /** 当前空方块的实例保存 **/
        private ImageView iv_null_ImageView;
        /** 当前手势 */
        private GestureDetector mDetector;
        /**判断游戏是否开始,默认没开始*/
        private boolean isGameStart = false;
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            // TODO Auto-generated method stub
            return mDetector.onTouchEvent(event);// 把界面监听换成手势监听
        }
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            // TODO Auto-generated method stub
            mDetector.onTouchEvent(ev);
            return super.dispatchTouchEvent(ev);
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mDetector = new GestureDetector(MainActivity.this,
                    new OnGestureListener() {
    
                        @Override
                        public boolean onSingleTapUp(MotionEvent arg0) {
                            // TODO Auto-generated method stub
                            return false;
                        }
    
                        @Override
                        public void onShowPress(MotionEvent arg0) {
                            // TODO Auto-generated method stub
    
                        }
    
                        @Override
                        public boolean onScroll(MotionEvent arg0, MotionEvent arg1,
                                float arg2, float arg3) {
                            // TODO Auto-generated method stub
                            return false;
                        }
    
                        @Override
                        public void onLongPress(MotionEvent arg0) {
                            // TODO Auto-generated method stub
    
                        }
    
                        @Override
                        public boolean onFling(MotionEvent arg0, MotionEvent arg1,
                                float arg2, float arg3) {
                            int type = getDirByGes(arg0.getX(), arg0.getY(),
                                    arg1.getX(), arg1.getY());// 判断手势返回int类型
                            // Toast.makeText(MainActivity.this, "" +
                            // type,Toast.LENGTH_SHORT).show();
                            changeByDir(type);// 移动换图
                            return false;
                        }
    
                        @Override
                        public boolean onDown(MotionEvent arg0) {
                            // TODO Auto-generated method stub
                            return false;
                        }
                    });
            setContentView(R.layout.activity_main);
            /** 初始化游戏的若干小方块 */
            // 获取一张大图片
            Bitmap bigBm = ((BitmapDrawable) getResources().getDrawable(
                    R.drawable.kenan1)).getBitmap();
            int tuWandW = bigBm.getWidth() / (iv_game_arr.length);// 每个游戏块的宽和高
            int tvWandH= this.getWindowManager().getDefaultDisplay().getWidth()/ (iv_game_arr.length-1);//小方块的宽度应为屏幕的平均值
            for (int i = 0; i < iv_game_arr.length; i++) {
                for (int j = 0; j < iv_game_arr[i].length; j++) {
                    Bitmap bm = Bitmap.createBitmap(bigBm, j * tuWandW,
                            i * tuWandW, tuWandW, tuWandW);// 根据行和列切成若干个游戏小图片
    
                    iv_game_arr[i][j] = new ImageView(this);
                    iv_game_arr[i][j].setImageBitmap(bm);// 设置每一个小方块的图片
                    iv_game_arr[i][j].setLayoutParams(new RelativeLayout.LayoutParams(tvWandH, tvWandH));//设置宽高
                    iv_game_arr[i][j].setPadding(2, 2, 2, 2);// 设置方块的间距
    
                    iv_game_arr[i][j].setTag(new GameData(i, j, bm));// 绑定自定义数据
                    // 设置点击监听,判断位置关系
                    iv_game_arr[i][j].setOnClickListener(new OnClickListener() {
    
                        @Override
                        public void onClick(View v) {
                            // TODO Auto-generated method stub
                            boolean flag = isHasByNullImageView((ImageView) v);
                            // Toast.makeText(MainActivity.this, "位置关系是否存在:"+flag,
                            // Toast.LENGTH_SHORT).show();
                            if (flag) {
                                changeDataByImageView((ImageView) v);
                            }
                        }
                    });
                }
            }
    
            // 初始化游戏界面,并添加若干小方块
            gl_main_game = (GridLayout) findViewById(R.id.gl_main_game);
            for (int i = 0; i < iv_game_arr.length; i++) {
                for (int j = 0; j < iv_game_arr[i].length; j++) {
                    gl_main_game.addView(iv_game_arr[i][j]);
                }
            }
            /** 设置第一个方块为空 */
            setNullIamgeView(iv_game_arr[0][0]);
            
            Button btnStart=(Button) findViewById(R.id.btn_start);//button点击之后打乱
            btnStart.setOnClickListener(new OnClickListener() {
                
                @Override
                public void onClick(View arg0) {
                    // TODO Auto-generated method stub
                    /** 初始化随机打乱顺序方块 */
                    randomMove();
                    isGameStart = true;//开始状态
                }
            });
    
        }
    
        /**
         * 根据手势的方向,获取空方块相应的相邻位置如果存在方块,那么进行数据交换
         * 
         * @param type
         *            1:上,2:下,3:左,4:右
         */
        public void changeByDir(int type) {
            changeByDir(type, true);
        }
    
        /**
         * 根据手势的方向,获取空方块相应的相邻位置如果存在方块,那么进行数据交换
         * 
         * @param type
         *            1:上,2:下,3:左,4:右
         * @param isAnim
         *            ture:有动画,false:无动画
         */
        public void changeByDir(int type, boolean isAnim) {
            // 获取当前空方块的位置
            GameData mNullGameData = (GameData) iv_null_ImageView.getTag();
            // 根据方向,设置相应的相邻的位置坐标
            int new_x = mNullGameData.x;
            int new_y = mNullGameData.y;
            if (type == 1) {
                new_x++;
            } else if (type == 2) {
                new_x--;
            } else if (type == 3) {
                new_y++;
            } else if (type == 4) {
                new_y--;
            }
            // 判断这个新坐标,是否存在
            if (new_x >= 0 && new_x < iv_game_arr.length && new_y >= 0
                    && new_y < iv_game_arr[0].length) {
                // 存在的话,开始移动
                if (isAnim) {// 有动画
                    changeDataByImageView(iv_game_arr[new_x][new_y]);
                } else {// 无动画
                    changeDataByImageView(iv_game_arr[new_x][new_y], isAnim);
                }
    
            } else {
                // 什么也不做
            }
        }
    
        /**
         * 判断游戏结束的方法
         */
        public void isGameOver(){
            boolean isGameOver = true;
            //要遍历每个游戏小方块
            for (int i = 0; i < iv_game_arr.length; i++) {
                for (int j = 0; j < iv_game_arr[0].length; j++) {
                    //为空的方块数据不判断
                    if(iv_game_arr[i][j]==iv_null_ImageView){
                        continue;
                    }
                    GameData mGameData = (GameData) iv_game_arr[i][j].getTag();
                    if (!mGameData.isTrue()) {
                        isGameOver=false;
                        break;
                    }
                }
            }
                
            //根据一个开关变量决定游戏是否结束,结束时给提
            if (isGameOver) {
                Toast.makeText(MainActivity.this, "游戏结束", Toast.LENGTH_SHORT).show();    
            }
        }
    
        /**
         * 手势判断,是向左,还是右
         * 
         * @param start_x
         *            手势的起始点x
         * @param start_y
         *            手势的起始点y
         * @param end_x
         *            手势的终止点x
         * @param end_y
         *            手势的终止点y
         * @return 1:上,2:下,3:左,4:右
         */
        public int getDirByGes(float start_x, float start_y, float end_x,
                float end_y) {
            boolean isLeftOrRight = (Math.abs(start_x - end_x) > Math.abs(start_y
                    - end_y)) ? true : false;// 是否是左右
            if (isLeftOrRight) {// 左右
                boolean isLeft = start_x - end_x > 0 ? true : false;// 判断左右
                if (isLeft) {
                    return 3;
                } else {
                    return 4;
                }
            } else {// 上下
                boolean isUp = start_y - end_y > 0 ? true : false;//
                if (isUp) {
                    return 1;
                } else {
                    return 2;
                }
            }
        }
    
        // 随机打乱顺序
        public void randomMove() {
            // 打乱的次数
            for (int i = 0; i < 100; i++) {
                // 根据手势开始交换,无动画
                int type = (int) (Math.random() * 4) + 1;// 随机数得到[0,4)之间的数,加上一就是移动的顺序
                changeByDir(type, false);
            }
        }
    
        /**
         * 利用动画结束之后,交换两个方块的数据
         * 
         * @param mImageView
         *            点击的方块
         */
        public void changeDataByImageView(final ImageView mImageView) {
            changeDataByImageView(mImageView, true);
        }
    
        /**
         * 利用动画结束之后,交换两个方块的数据
         * 
         * @param mImageView
         *            点击的方块
         * @param isAnim
         *            true 有动画,false 无动画
         */
        public void changeDataByImageView(final ImageView mImageView, boolean isAnim) {    
            if (isAnimRun) {//如果动画正在执行,不进行操作
                return;
            }
            if (!isAnim) {//判断是否有动画
                GameData mGameData = (GameData) mImageView.getTag();
                iv_null_ImageView.setImageBitmap(mGameData.bm);// 设置空方块为交换的图片
                GameData mNullGameData = (GameData) iv_null_ImageView.getTag();
                mNullGameData.bm = mGameData.bm;
                mNullGameData.p_x = mGameData.p_x;
                mNullGameData.p_y = mGameData.p_y;
                setNullIamgeView(mImageView);// 设置当前点击的为空模块
                if (isGameStart) {//开始后每一次移动都要判断是否结束
                    isGameOver();// 成功时会弹一个toast
                }    
                return;
            }
            // 创建一个动画,设置好方向,移动距离
            TranslateAnimation translateAnimation = null;
            if (mImageView.getX() > iv_null_ImageView.getX()) {// 当前点击的方块在空方块的下面
                // 往上移
                translateAnimation = new TranslateAnimation(0.1f,
                        -mImageView.getWidth(), 0.1f, 0.1f);
            } else if (mImageView.getX() < iv_null_ImageView.getX()) {
                // 往下移
                translateAnimation = new TranslateAnimation(0.1f,
                        mImageView.getWidth(), 0.1f, 0.1f);
            } else if (mImageView.getY() > iv_null_ImageView.getY()) {
                // 往左移
                translateAnimation = new TranslateAnimation(0.1f, 0.1f, 0.1f,
                        -mImageView.getWidth());
            } else if (mImageView.getY() < iv_null_ImageView.getY()) {
                // 往右移
                translateAnimation = new TranslateAnimation(0.1f, 0.1f, 0.1f,
                        mImageView.getWidth());
            }
            // 设置动画的的时长
            translateAnimation.setDuration(70);
            // 设置动画结束之后时候是否停留
            translateAnimation.setFillAfter(true);
            // 设置动画结束之后要真正的把数据交换了
            translateAnimation.setAnimationListener(new AnimationListener() {
    
                @Override
                public void onAnimationStart(Animation arg0) {
                    // TODO Auto-generated method stub
                    isAnimRun = true;
                }
    
                @Override
                public void onAnimationRepeat(Animation arg0) {
                    // TODO Auto-generated method stub
    
                }
    
                @Override
                public void onAnimationEnd(Animation arg0) {
                    // TODO Auto-generated method stub
                    isAnimRun = false;
                    mImageView.clearAnimation();
                    GameData mGameData = (GameData) mImageView.getTag();
                    iv_null_ImageView.setImageBitmap(mGameData.bm);// 设置空方块为交换的图片
                    GameData mNullGameData = (GameData) iv_null_ImageView.getTag();
                    mNullGameData.bm = mGameData.bm;
                    mNullGameData.p_x = mGameData.p_x;
                    mNullGameData.p_y = mGameData.p_y;
                    setNullIamgeView(mImageView);// 设置当前点击的为空模块
                    if (isGameStart) {//开始后每一次移动都要判断是否结束
                        isGameOver();// 成功时会弹一个toast
                    }
                }
            });
            // 执行动画
            mImageView.startAnimation(translateAnimation);
        }
    
        /**
         * 设置某个方块为空
         * 
         * @param mImageView
         *            当前要设置为空的方块实例
         */
        public void setNullIamgeView(ImageView mImageView) {
            mImageView.setImageBitmap(null);
            // mImageView.setBackgroundColor(10);//设置空的背景色
            iv_null_ImageView = mImageView;
        }
    
        /**
         * 判断当前点击的方块,是否与空方块的位置关系是否相邻
         * 
         * @param mImageView
         *            点击的方块实例
         * @return true:相邻,false:不相邻
         */
        public boolean isHasByNullImageView(ImageView mImageView) {
            // 分别获取当前空方块的位置与点击方块的位置,通过x,y两边都差一的方式判断
            GameData mNullGameData = (GameData) iv_null_ImageView.getTag();
            GameData mGameData = (GameData) mImageView.getTag();
            if (mNullGameData.y == mGameData.y
                    && mGameData.x + 1 == mNullGameData.x) {// 当前点击的方块在空方块的上边
                return true;
            } else if (mNullGameData.y == mGameData.y
                    && mGameData.x - 1 == mNullGameData.x) {// 当前点击的方块在空方块的下边
                return true;
            } else if (mNullGameData.y == mGameData.y + 1
                    && mGameData.x == mNullGameData.x) {// 当前点击的方块在空方块的左边
                return true;
            } else if (mNullGameData.y == mGameData.y - 1
                    && mGameData.x == mNullGameData.x) {// 当前点击的方块在空方块的右边
                return true;
            }
            return false;
        }
    
        /**
         * 每个游戏小方块上要绑定的数据
         */
        class GameData {        
            /** 每个小方块的实际位置x */
            public int x = 0;
            /** 每个小方块的实际位置y */
            public int y = 0;
            /** 每个小方块的图片 */
            public Bitmap bm;
            /** 每个小方块的图片的位置x */
            public int p_x = 0;
            /** 每个小方块的图片的位置y */
            public int p_y = 0;
    
            public GameData(int x, int y, Bitmap bm) {
                super();
                this.x = x;
                this.y = y;
                this.bm = bm;
                this.p_x = x;
                this.p_y = y;
            }
            /**
             * 每个小方块的位置是否正确
             * @return true:正确,false:不正确
             */
            public boolean isTrue(){
                if (x==p_x && y==p_y) {
                    return true;
                }
                return false;
            }
    
        }
    }
    View Code

    效果如下:

  • 相关阅读:
    <转>反调试技巧总结原理和实现
    MFC CListCtrl 表格
    <转>汇编指令
    c++ builder 简单读、分析网页数据
    <转>CProcessData : A template class to ease up SendMessage calls across processes
    <转>Running console applications silently
    遍历电脑打印机、设置默认打印机、EnumPrinters ,SetDefaultPrinter,GetDefaultPrinter
    <转>运算符巧妙原理解析
    遍历 进程
    Enterprise Library5.0 Unity 试用.
  • 原文地址:https://www.cnblogs.com/rainday1/p/5726079.html
Copyright © 2011-2022 走看看