XMl布局:
<RelativeLayout xmlns:android="/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent" ><GridLayout android:id="@+id/jigsaw"android:layout_height="match_parent"android:layout_width="match_parent"android:columnCount="5"android:rowCount="3"/></RelativeLayout>
MainActivity代码:
public class MainActivity extends Activity {private boolean isAnimRun = false;/**判断游戏是否开始*/private boolean isGameStart = false;/**利用二维数组创建若干个游戏小方块**/private ImageView[][] iv_game_arr = new ImageView[3][5];/**游戏主界面**/private GridLayout gl_game;/**当前空方块的实例保存*/private ImageView iv_null;/**当前手势*/private GestureDetector mDetector;@Overridepublic boolean onTouchEvent(MotionEvent event) {// TODO Auto-generated method stubreturn mDetector.onTouchEvent(event);}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {// TODO Auto-generated method stubmDetector.onTouchEvent(ev);return super.dispatchTouchEvent(ev);}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mDetector = new GestureDetector(this, new OnGestureListener() {@Overridepublic boolean onSingleTapUp(MotionEvent e) {// TODO Auto-generated method stubreturn false;}@Overridepublic void onShowPress(MotionEvent e) {// TODO Auto-generated method stub}@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {// TODO Auto-generated method stubreturn false;}@Overridepublic void onLongPress(MotionEvent e) {// TODO Auto-generated method stub}@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {// TODO Auto-generated method stubLog.d("TAG", ""+getDirByGes(e1.getX(), e1.getY(), e2.getX(), e2.getY()));int type = getDirByGes(e1.getX(), e1.getY(), e2.getX(), e2.getY());changeByDir(type);return false;}@Overridepublic boolean onDown(MotionEvent e) {// TODO Auto-generated method stubreturn false;}});/*初始化游戏的若干个小方块*///获取一张大图Bitmap bitmap = ((BitmapDrawable)getResources().getDrawable(R.drawable.pic1)).getBitmap();int wh = bitmap.getWidth()/5;//小方块的宽高是整个屏幕的宽除以5int ivWH = getWindow().getWindowManager().getDefaultDisplay().getWidth()/5;for(int i = 0;i<iv_game_arr.length;i++){for(int j = 0;j<iv_game_arr[0].length;j++){//根据行和列来切成若干个游戏小图片Bitmap bm = Bitmap.createBitmap(bitmap,j*wh,i*wh,wh,wh);iv_game_arr[i][j] = new ImageView(this);iv_game_arr[i][j].setImageBitmap(bm);//设置每个小方块的图案iv_game_arr[i][j].setLayoutParams(new RelativeLayout.LayoutParams(ivWH,ivWH));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() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubboolean flag = isHasByNullImage((ImageView)v);if(flag){changeDataByImage((ImageView)v);}}});}}/*初始化游戏主界面,并添加若干个小方块*/gl_game = (GridLayout) findViewById(R.id.jigsaw);for(int i = 0;i<iv_game_arr.length;i++){for(int j = 0;j<iv_game_arr[0].length;j++){gl_game.addView(iv_game_arr[i][j]);}}/*设置最后一个方块为空方块*/setNullImage(iv_game_arr[2][4]);randomOrder();isGameStart = true;}/*** 根据手势的方向,获取空方块相应的相邻位置,如果存在方块,则进行数据狡猾* * @param type 1:上 2:下 3:左 4:右*/public void changeByDir(int type){changeByDir(type, true);}/*** 根据手势的方向,获取空方块相应的相邻位置,如果存在方块,则进行数据狡猾* * @param type 1:上 2:下 3:左 4:右* @param isAnim true:有动画 false:无动画*/public void changeByDir(int type,boolean isAnim){//获取当前空方块的位置GameData mNullGameData = (GameData) iv_null.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){changeDataByImage(iv_game_arr[new_x][new_y]);}else{changeDataByImage(iv_game_arr[new_x][new_y],false);}}else{//什么也不做}}/**** 判断游戏结束*/public void isGameOver(){boolean isOver = 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){continue;}GameData mGameData = (GameData) iv_game_arr[i][j].getTag();if(!mGameData.isTrue()){isOver = false;break;}}}//根据一个开关变量决定游戏是否结束,结束时给提示if(isOver){Toast.makeText(MainActivity.this, "GameOver", Toast.LENGTH_LONG).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 randomOrder(){//打乱的次数for (int i = 0; i < 100; i++) {//根据手势开始交换,无动画int type = (int)(Math.random()*4)+1;changeByDir(type, false);}}public void changeDataByImage(final ImageView mImageView){changeDataByImage(mImageView, true);}/*** 利用动画结束之后,交换亮给方块的数据* @param mImageView 点击的方块* @param isAnim true:有动画 false:无动画*/public void changeDataByImage(final ImageView mImageView,boolean isAnim){if(isAnimRun)return;if(!isAnim){GameData mGameData = (GameData) mImageView.getTag();iv_null.setImageBitmap(mGameData.bitmap);GameData mNullGameData = (GameData) iv_null.getTag();mNullGameData.bitmap = mGameData.bitmap;mNullGameData.p_x = mGameData.p_x;mNullGameData.p_y = mGameData.p_y;iv_null.setTag(mNullGameData);//设置当前点击的是空方块setNullImage(mImageView);return;}//创建一个动画,设置好方向,移动的距离TranslateAnimation translateAnimation = null;if(mImageView.getX()>iv_null.getX()){//当前点击方块在空方块的下面//往上移动translateAnimation = new TranslateAnimation(0.1f, -mImageView.getWidth(), 0.1f, 0.1f);}else if(mImageView.getX()<iv_null.getX()){//当前点击方块在空方块的上面//往下移动translateAnimation = new TranslateAnimation(0.1f, mImageView.getWidth(), 0.1f, 0.1f);}else if(mImageView.getY()>iv_null.getY()){//当前点击方块在空方块的右面//往左移动translateAnimation = new TranslateAnimation(0.1f, 0.1f, 0.1f, -mImageView.getWidth());}else if(mImageView.getY()<iv_null.getY()){//当前点击方块在空方块的左面//往右移动translateAnimation = new TranslateAnimation(0.1f,0.1f, 0.1f, mImageView.getWidth());}//设置动画的时长translateAnimation.setDuration(70);//设置动画结束之后是否停留translateAnimation.setFillAfter(true);//设置动画结束之后要真正的把数据交换了translateAnimation.setAnimationListener(new AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {// TODO Auto-generated method stubisAnimRun = true;}@Overridepublic void onAnimationRepeat(Animation animation) {// TODO Auto-generated method stub}@Overridepublic void onAnimationEnd(Animation animation) {// TODO Auto-generated method stubisAnimRun = false;mImageView.clearAnimation();GameData mGameData = (GameData) mImageView.getTag();iv_null.setImageBitmap(mGameData.bitmap);GameData mNullGameData = (GameData) iv_null.getTag();mNullGameData.bitmap = mGameData.bitmap;mNullGameData.p_x = mGameData.p_x;mNullGameData.p_y = mGameData.p_y;iv_null.setTag(mNullGameData);//设置当前点击的是空方块setNullImage(mImageView);if(isGameStart){isGameOver();//成功时会弹出一个Toas}}});//执行动画mImageView.startAnimation(translateAnimation);}/*** 设置某个空方块* mImageView当前要设置空方块的实例*/public void setNullImage(ImageView mImageView){mImageView.setImageBitmap(null);iv_null = mImageView;}/*** 判断当前点击的方块,是否与空方块的位置关系为相邻关系* @param mImageView 所点击的方块* @return true:相邻 false:不相邻*/public boolean isHasByNullImage(ImageView mImageView){//分别获取当前空方块的位置与点击方块的位置,通过x与y两边都差1的方式判断GameData mNullGameData = (GameData) iv_null.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;/**每个小方块的实际位置y*/public int y;/**每个小方块的图片*/public Bitmap bitmap;/**每个小方块的图片的位置x*/public int p_x;/**每个小方块的图片的位置y*/public int p_y;public GameData(int x, int y, Bitmap bitmap) {super();this.x = x;this.y = y;this.bitmap = bitmap;this.p_x = x;this.p_y = y;}public boolean isTrue(){if(x==p_x && y==p_y){return true;}return false;}}}
源码下载