美女拼图小游戏

来源:互联网 发布:禁止自启动软件 编辑:程序博客网 时间:2024/05/21 10:42

先看一下效果然后贴代码
这里写图片描述

最上面是自定义的ActionBar,布局里面有两个TextView。一个用于显示level,一个用于显示倒计时
下面就是自定义的RelativeLayout。用于显示九个一打乱的bitmap

接下来就是代码:
首先是将图片分割的工具类
ImageUtil.java

package com.example.util;import java.util.ArrayList;import java.util.List;import android.graphics.Bitmap;public class ImageUtil {    /*     * 将图片分成piece*piece份小图片,每份就是ImagePiece,存在imgList里面     */    public static List<ImagePiece> splitImage(Bitmap bitmap, int piece) {        List<ImagePiece> imgList = new ArrayList<ImagePiece>();        //每张图片的宽高        int pieceWidth = bitmap.getWidth() / piece;        int pieceHeight = bitmap.getHeight() / piece;        for (int i = 0; i < piece; i++) {            for (int j = 0; j < piece; j++) {                ImagePiece imagePiece = new ImagePiece();                imagePiece.setIndex(j + i * piece);                int x = j * pieceWidth;                int y = i * pieceHeight;                imagePiece.setBitmap(Bitmap.createBitmap(bitmap, x, y,                        pieceWidth, pieceHeight));                imgList.add(imagePiece);            }        }        return imgList;    }}

分割后的每一个ImagePiece的实体类
ImagePiece.java

package com.example.util;import android.graphics.Bitmap;public class ImagePiece {    private int index;//每小张图片的编号    private Bitmap bitmap;    public ImagePiece() {}    public ImagePiece(int index, Bitmap bitmap) {        this.index = index;        this.bitmap = bitmap;    }    public int getIndex() {        return index;    }    public void setIndex(int index) {        this.index = index;    }    public Bitmap getBitmap() {        return bitmap;    }    public void setBitmap(Bitmap bitmap) {        this.bitmap = bitmap;    }    @Override    public String toString() {        return "ImagePiece [index=" + index + ", bitmap=" + bitmap + "]";    }}

接下来是自定义的GameLayout.java

package com.example.view;import java.util.Collections;import java.util.Comparator;import java.util.List;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Color;import android.os.Handler;import android.os.Message;import android.util.AttributeSet;import android.util.TypedValue;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.ImageView;import android.widget.RelativeLayout;import android.widget.Toast;import com.example.pintu.R;import com.example.util.ImagePiece;import com.example.util.ImageUtil;public class GameLayout extends RelativeLayout implements OnClickListener {    private int GameLayoutWidth;    private int GameLayoutHeight;    private int column;    private int padding;// 类似于xml中的android:padding    private int margin;// 类似于xml中的android:layout_margin    private ImageView[] gameItem;    private int itemWidth;    private int itemHeight;    private Bitmap bitmap;    private List<ImagePiece> imgList;    private boolean once;    public GameLayout(Context context) {        super(context);        init();    }    public GameLayout(Context context, AttributeSet attrs) {        super(context, attrs);        init();    }    public GameLayout(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        init();    }    // 初始化参数    private void init() {        column = 3;        margin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,                2, getResources().getDisplayMetrics());        padding = min(getPaddingLeft(), getPaddingRight(), getPaddingTop(),                getPaddingBottom());        once = false;    }    private int min(int... params) {        int min = params[0];        for (int param : params) {            min = Math.min(min, param);        }        return min;    }    @Override    // onMeasure和onLayout会多次调用,所有要有once标识符    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        if (!once) {            GameLayoutHeight = getMeasuredHeight();            GameLayoutWidth = getMeasuredWidth();            // 进行切图,并打乱次序            initBitmap();            // 九宫格的绘制            initItem();            // 判断是否开启时间            checkTimeEnable();            once = true;        }        setMeasuredDimension(GameLayoutWidth, GameLayoutHeight);    }    // 进行切图,并排序    private void initBitmap() {        // 获取bitmap,然后转化为和屏幕一样大小        if (bitmap == null) {            bitmap = BitmapFactory.decodeResource(getResources(),                    R.drawable.girl);            bitmap = Bitmap.createScaledBitmap(bitmap, GameLayoutWidth,                    GameLayoutHeight, true);        }        // 切图        imgList = ImageUtil.splitImage(bitmap, column);        // 使用sort打乱次序        Collections.sort(imgList, new Comparator<ImagePiece>() {            @Override            public int compare(ImagePiece lhs, ImagePiece rhs) {                return Math.random() > 0.5 ? 1 : -1;            }        });    }    // 九宫格的绘制    private void initItem() {        // 设置gameItem的宽高        itemWidth = (GameLayoutWidth - padding * 2 - margin * (column - 1))                / column;        itemHeight = (GameLayoutHeight - padding * 2 - margin * (column - 1))                / column;        gameItem = new ImageView[column * column];        // 设置九宫格中每个格子对应的Bitmap,id和tag以及LayoutParams        // 最后添加到GameLayout中        for (int i = 0; i < gameItem.length; i++) {            ImageView item = new ImageView(getContext());            item.setImageBitmap(imgList.get(i).getBitmap());            item.setId(i + 1);// **********************************            // index是本质编号,id是打乱后的编号            item.setTag(i + "_" + imgList.get(i).getIndex());            item.setOnClickListener(this);// 实现图片的交换            gameItem[i] = item;            RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(                    itemWidth, itemHeight);            // 设置横向间距,通过leftMargin。如果不是第一列            if ((i % column) != 0) {                lp.leftMargin = margin;                lp.addRule(RelativeLayout.RIGHT_OF, gameItem[i - 1].getId());            }            // 设置横向间距。如果不是第一行,设置topMargin和rule            if ((i + 1) > column) {                lp.topMargin = margin;                lp.addRule(RelativeLayout.BELOW, gameItem[i - column].getId());                // anchor------The id of another view to use as an anchor,                // or a boolean value(represented as RelativeLayout.TRUE) for                // true                // or 0 for false). For verbs that don't refer to another                // sibling                // (for example, ALIGN_WITH_PARENT_BOTTOM) just use -1.                // 注意,后面的参数不能为0(0 for false),所以打星号的地方要+1            }            addView(item, lp);        }    }    private int time;    private boolean isTimeEnabled = false;// 默认不开启时间    private void checkTimeEnable() {        if (isTimeEnabled) {            // 根据当前等级设置时间            time = (int) Math.pow(3.0, column);            myHandler.sendEmptyMessage(TIME_CHANGED);        }    }    private ImageView mFirst;    private ImageView mSecond;    private boolean isAnimation = false;    // 实现图片的交换    @Override    public void onClick(View v) {        // 防止用户疯狂的点        if (isAnimation) {            return;        }        // 两次点击同一个item        if (mFirst == v) {            mFirst.setColorFilter(null);            mFirst = null;            return;        }        if (mFirst == null) {// 第一次点击的是新的图片            mFirst = (ImageView) v;            mFirst.setColorFilter(Color.parseColor("#55FF0000"));        } else {// 第二次点击也是新的图片            mSecond = (ImageView) v;            exchageView();// 交换图片        }    }    private RelativeLayout mAnimLayout;// 实现动画切换的变量    // 交换图片    private void exchageView() {        mFirst.setColorFilter(null);        final String firstTag = (String) mFirst.getTag();        final String secondTag = (String) mSecond.getTag();        final Bitmap firstBitmap = imgList.get(getImageIdByTag(firstTag))                .getBitmap();        final Bitmap secondBitmap = imgList.get(getImageIdByTag(secondTag))                .getBitmap();        // 构造动画层        if (mAnimLayout == null) {            mAnimLayout = new RelativeLayout(getContext());            addView(mAnimLayout);        }        // 构造图片交换动画        final ImageView first = new ImageView(getContext());        first.setImageBitmap(firstBitmap);        LayoutParams lp = new LayoutParams(itemWidth, itemHeight);        lp.leftMargin = mFirst.getLeft() - padding;        lp.topMargin = mFirst.getTop() - padding;        first.setLayoutParams(lp);        mAnimLayout.addView(first);        final ImageView second = new ImageView(getContext());        second.setImageBitmap(secondBitmap);        LayoutParams lp2 = new LayoutParams(itemWidth, itemHeight);        lp2.leftMargin = mSecond.getLeft() - padding;        lp2.topMargin = mSecond.getTop() - padding;        second.setLayoutParams(lp2);        mAnimLayout.addView(second);        TranslateAnimation animation = new TranslateAnimation(0,                mSecond.getLeft() - mFirst.getLeft(), 0, mSecond.getTop()                        - mFirst.getTop());        animation.setDuration(300);        animation.setFillAfter(true);        first.startAnimation(animation);        TranslateAnimation animation2 = new TranslateAnimation(0,                mFirst.getLeft() - mSecond.getLeft(), 0, mFirst.getTop()                        - mSecond.getTop());        animation2.setDuration(300);        animation2.setFillAfter(true);        second.startAnimation(animation2);        animation.setAnimationListener(new AnimationListener() {            @Override            public void onAnimationStart(Animation animation) {                isAnimation = true;                mFirst.setVisibility(View.INVISIBLE);                mSecond.setVisibility(View.INVISIBLE);            }            @Override            public void onAnimationRepeat(Animation animation) {            }            @Override            public void onAnimationEnd(Animation animation) {                // 交换图片(注意tag也要交换)                isAnimation = false;                mFirst.setImageBitmap(secondBitmap);                mSecond.setImageBitmap(firstBitmap);                mFirst.setTag(secondTag);                mSecond.setTag(firstTag);                mFirst.setVisibility(View.VISIBLE);                mSecond.setVisibility(View.VISIBLE);                mFirst = mSecond = null;                mAnimLayout.removeAllViews();                checkSuccess();// 判断是否过关            }        });    }    private int getImageIdByTag(String tag) {        String[] split = tag.split("_");        return Integer.parseInt(split[0]);    }    // item.setTag(i + "_" + imgList.get(i).getIndex());    private int getImageIndexByTag(String tag) {        String[] split = tag.split("_");        return Integer.parseInt(split[1]);    }    // 判断是否过关。过关条件就是0到8有序排列    private void checkSuccess() {        boolean isSuccess = true;        for (int i = 0; i < gameItem.length; i++) {            ImageView imageView = gameItem[i];            if (getImageIndexByTag((String) imageView.getTag()) != i) {                isSuccess = false;            }        }        if (isSuccess) {            isGameSuccess = true;            myHandler.removeMessages(TIME_CHANGED);            Toast.makeText(getContext(), "Success ! Level Up !",                    Toast.LENGTH_SHORT).show();            myHandler.sendEmptyMessage(NEXT_LEVEL);// 进入下一关        }    }    private static final int NEXT_LEVEL = 0x001;    private static final int TIME_CHANGED = 0x002;    private boolean isGameSuccess;    private boolean isGameOver;    private Handler myHandler = new Handler() {        public void handleMessage(Message msg) {            switch (msg.what) {            case NEXT_LEVEL:// 进入下一关                column++;                if (mListener != null) {                    mListener.nextLevel(column);                }                break;            case TIME_CHANGED:                if (isGameSuccess || isGameOver || isPause)                    return;                if (mListener != null) {                    mListener.timeChanged(time);                    if (time == 0) {                        isGameOver = true;                        mListener.gameOver();                        return;                    }                }                time--;                myHandler.sendEmptyMessageDelayed(TIME_CHANGED, 1000);                break;            }        };    };    public void nextLevel() {        this.removeAllViews();        mAnimLayout = null;        isGameSuccess = false;        checkTimeEnable();        initBitmap();        initItem();    };    public void restart() {        isGameOver = false;        nextLevel();    }    private boolean isPause;    public void pause(){        isPause = true;        myHandler.removeMessages(TIME_CHANGED);    }    public void resume(){        if(isPause){            isPause = false;            myHandler.sendEmptyMessage(TIME_CHANGED);        }    }    // 定义接口,用于通知主界面的level和time    public interface GameListener {        void nextLevel(int level);        void timeChanged(int currentTime);        void gameOver();    }    public GameListener mListener;    public void setOnGameListener(GameListener Listener) {        this.mListener = Listener;    }    public void setTimeEnabled(boolean isTimeEnabled) {        this.isTimeEnabled = isTimeEnabled;    }}

GameLayout实现如下几个功能
1.自定义容器
2.实现图片交换onCLickListener
3.实现过关逻辑interface GameListener
4.实现游戏的结束和暂停,这需要配合activity的onPause和onResume

接下来就是MainActivity.java

package com.example.pintu;import android.app.Activity;import android.app.AlertDialog;import android.content.DialogInterface;import android.content.DialogInterface.OnClickListener;import android.os.Bundle;import android.view.Window;import android.widget.TextView;import com.example.view.GameLayout;import com.example.view.GameLayout.GameListener;public class MainActivity extends Activity {    private GameLayout gameLayout;    private TextView levelView, timeView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        // 自定义ActionBar,        // 用法参考http://blog.csdn.net/jia20003/article/details/12966489        requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);        setContentView(R.layout.main);        getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.title);        levelView = (TextView) findViewById(R.id.id_level);        levelView.setText("level 1");        timeView = (TextView) findViewById(R.id.id_time);        gameLayout = (GameLayout) findViewById(R.id.pintu);        gameLayout.setTimeEnabled(true);        gameLayout.setOnGameListener(new GameListener() {            @Override            public void timeChanged(int currentTime) {                timeView.setText("" + currentTime);            }            @Override            public void nextLevel(int level) {                new AlertDialog.Builder(MainActivity.this).setTitle("LEVEL UP")                        .setPositiveButton("next level", new OnClickListener() {                            @Override                            public void onClick(DialogInterface dialog,                                    int which) {                                gameLayout.nextLevel();                            }                        }).show();                // 3*3对应level 1;4*4对应level 2                levelView.setText("level " + (level - 2));            }            @Override            public void gameOver() {                new AlertDialog.Builder(MainActivity.this)                        .setTitle("Game Over")                        .setPositiveButton("RESTART", new OnClickListener() {                            @Override                            public void onClick(DialogInterface dialog,                                    int which) {                                gameLayout.restart();                            }                        }).setNegativeButton("QUIT", new OnClickListener() {                            @Override                            public void onClick(DialogInterface dialog,                                    int which) {                                finish();                            }                        }).show();            }        });    }    @Override    protected void onPause() {        super.onPause();        gameLayout.pause();    }    @Override    protected void onResume() {        super.onResume();        gameLayout.resume();    }}

适合自定义ActionBar还要在styles.xml添加

<style name="MyTheme" parent="android:Theme.Light">      </style>  

以及修改AndroidManifest.xml

android:theme="@style/MyTheme"<!--         就算MyTheme和自动生成的AppBaseTheme一样,还是要重新定义 --><!--         因为ActionBar布局改变了 -->

最后给出两个布局
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="com.example.pintu.MainActivity" >    <com.example.view.GameLayout        android:id="@+id/pintu"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:padding="2dp" >    </com.example.view.GameLayout></RelativeLayout>

以及自定义的actionbar的布局title.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout 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"    android:orientation="horizontal"    tools:context=".MainActivity"    android:background="#FFFFFF" >    <TextView        android:id="@+id/id_level"        android:layout_width="0sp"        android:layout_weight="1"        android:gravity="left"        android:textSize="20sp"        android:layout_height="wrap_content" />    <TextView        android:id="@+id/id_time"        android:layout_width="0sp"        android:layout_weight="1"        android:gravity="right"        android:textSize="20sp"        android:layout_height="wrap_content" /></LinearLayout>
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 内裤洗了还有一股味道怎么办 月经下不来内裤上总有脏东西怎么办 夏天外衣薄露出内衣怎么办 金毛体味很重怎么办 直筒连衣裙太短怎么办 托班社会下雨了怎么办 托班下雨了怎么办教案 吃鸡界面有鼠标怎么办 老年机成英语了怎么办 手机成了英语了怎么办 塑料袋融化粘到衣服上怎么办 厕所被卫生纸堵了怎么办 钻石画的胶不粘了怎么办 客厅沙发选大了怎么办 连衣裙腰大了怎么办呀 憋尿后出现尿急尿涨怎么办 脚有酸酸的味道怎么办 三星手机home键失灵怎么办 三星s6返回键失灵怎么办 三星s7屏幕漏液怎么办 三星s8出现蓝框怎么办 三星手机短信图标没了怎么办 ps没有足够的ram怎么办 ps性能调不了是怎么办 苹果6p照相模糊怎么办 相框玻璃碎了怎么办 word文档加密后忘记密码怎么办 手机wps密码忘了怎么办 苹果手表忘了密码怎么办 苹果系统忘了密码怎么办 ps画板建小了怎么办 wps表格密码忘了怎么办 word文档变成虚的怎么办 wps论文中表格跨页怎么办 word文档复制过来有边框怎么办 wps表格跨页断开怎么办 锅的铆钉老是松怎么办 文胸不知道怎么染色了怎么办 未后的信息我该怎么办? 做leep手术后大出血怎么办 眼线笔出不了水怎么办