charspan
2016-08-05 08:26
打乱顺序的时候,我不能交换,用了Toast,发现我交换的两个小方块的坐标是一样的,但是他们数组的i,j是不一样的,这是怎么回事呢,现在还没解决。。。。?
package com.charspan.pintu;
import java.util.Random;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
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.GridLayout;
import android.widget.ImageView;
import android.widget.Toast;
public class MainActivity extends Activity {
private int rowsNum = 3;
private int colsNum = 5;
/**
* 利用二维数组创建若干个游戏小方块
*/
private ImageView[][] iv_game_arr;
/**
* 当前空方块的实例
*/
private ImageView iv_null;
/**
* 游戏主界面
*/
private GridLayout gl_main_game;
/**
* 当前手势
*/
private GestureDetector mDetector;
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
return mDetector.onTouchEvent(event);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDetector = new GestureDetector(this, new OnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
@Override
public void onShowPress(MotionEvent e) {
// TODO Auto-generated method stub
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
// TODO Auto-generated method stub
return false;
}
@Override
public void onLongPress(MotionEvent e) {
// TODO Auto-generated method stub
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
// TODO Auto-generated method stub
int dir = getDirByGes(e1.getX(), e1.getY(), e2.getX(), e2.getY());
// Toast.makeText(MainActivity.this, "" + dir, Toast.LENGTH_SHORT).show();
changeByDir(dir);
return false;
}
@Override
public boolean onDown(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
});
setContentView(R.layout.activity_main);
iv_game_arr = new ImageView[rowsNum][colsNum];
// Bitmap bigBm =(
// (BitmapDrawable)getResources().getDrawable(R.drawable.pic_1)).getBitmap();
// 获取一张大图
Bitmap bigBm = BitmapFactory.decodeResource(getResources(), R.drawable.pic_1);
// 计算每个小方块的宽和高
int tuWandH = bigBm.getWidth() / colsNum;
// 初始化游戏小方块
for (int i = 0; i < rowsNum; i++) {
for (int j = 0; j < colsNum; j++) {
Bitmap bm = Bitmap.createBitmap(bigBm, j * tuWandH, i * tuWandH, tuWandH, tuWandH);
iv_game_arr[i][j] = new ImageView(this);
iv_game_arr[i][j].setImageBitmap(bm);
// 设置方块之间的间距
iv_game_arr[i][j].setPadding(2, 2, 2, 2);
// 绑定自定义的数据
iv_game_arr[i][j].setTag(new ImageViewData(i, j, bm));
iv_game_arr[i][j].setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
boolean flag = isNearByNull((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 < rowsNum; i++) {
for (int j = 0; j < colsNum; j++) {
gl_main_game.addView(iv_game_arr[i][j]);
}
}
// 设置最后一个方块为空
setNullImageView(iv_game_arr[rowsNum - 1][colsNum - 1]);
randomMove();
}
/**
* 根据手势方向获取与空方块相邻的位置,如果存在方块就进行数据交换
*
* @param dir
*/
public void changeByDir(int dir) {
// 获取空方块位置
ImageViewData data = (ImageViewData) iv_null.getTag();
// 根据手势方向,设置相邻位置坐标
int new_x = data.x;
int new_y = data.y;
if (dir == 1) {//
new_x++;
} else if (dir == 2) {
new_x--;
} else if (dir == 3) {
new_y++;
} else if (dir == 4) {
new_y--;
}
// Toast.makeText(MainActivity.this, data.x+" :: "+data.y,Toast.LENGTH_SHORT).show();
// 判断新坐标是否存在
if (new_x >= 0 && new_x < rowsNum && new_y >= 0 && new_y < colsNum) {
// Toast.makeText(MainActivity.this, new_x+" : "+new_y,Toast.LENGTH_SHORT).show();
// 存在的话开始移动
changeDataByImageView(iv_game_arr[new_x][new_y]);
}
}
/**
* 手势的判断
*
* @param sx
* @param sy
* @param ex
* @param ey
* @return 上下左右 1 2 3 4
*/
public int getDirByGes(float sx, float sy, float ex, float ey) {
// 左右:横向距离大于竖直距离
boolean isLeftOrRight = Math.abs(sx - ex) > Math.abs(sy - ey);
if (isLeftOrRight) {// 左右
// 左 :终点x小于起点x
boolean isLeft = sx > ex;
if (isLeft) {
return 3;
} else {
return 4;
}
} else {// 上下
// 上:终点y大于起点y
boolean isUp = sy > ey;
if (isUp) {
return 1;
} else {
return 2;
}
}
}
//随机打乱顺序
public void randomMove(){
changeByDir(2);
// //打乱次数
// for (int i = 0; i < 3; i++) {
// int dir=(int)(Math.random()*4)+1;
// changeByDir(dir);
// }
// //开始交换,无动画
}
/**
* 动画结束后,交换两个方块的数据
*
* @param mImageView
* 点击的方块
*/
public void changeDataByImageView(final ImageView mImageView) {
ImageViewData nullD=(ImageViewData) iv_null.getTag();
ImageViewData mD=(ImageViewData) mImageView.getTag();
// Toast.makeText(MainActivity.this, nullD.x+" :.. "+mD.x, Toast.LENGTH_SHORT).show();
// Toast.makeText(MainActivity.this, nullD.y+" :.. "+mD.y, Toast.LENGTH_SHORT).show();
Toast.makeText(MainActivity.this, mImageView.getX()+" :.. "+iv_null.getX(), Toast.LENGTH_SHORT).show();
Toast.makeText(MainActivity.this, mImageView.getY()+" : "+iv_null.getY(), Toast.LENGTH_SHORT).show();
// 创建一个动画,设置放心,移动距离
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 = new TranslateAnimation(0.1f, mImageView.getWidth(), 0.1f, 0.1f);
// 设置动画时长
translateAnimation.setDuration(70);
// 设置动画结束后是否停留
translateAnimation.setFillAfter(true);
// 动画结束后交换数据对象
translateAnimation.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
mImageView.clearAnimation();
ImageViewData data1 = (ImageViewData) mImageView.getTag();
ImageViewData data2 = (ImageViewData) iv_null.getTag();
iv_null.setImageBitmap(data1.imageView);
data2.imageView = data1.imageView;
data2.p_x = data1.p_x;
data2.p_y = data2.p_y;
// 设置当前点击的是空方块
setNullImageView(mImageView);
}
});
mImageView.startAnimation(translateAnimation);
}
/**
* 设置某个方块为空方块
*
* @param imageView
* 当前需要设置为空的方块实例
*/
public void setNullImageView(ImageView imageView) {
imageView.setImageBitmap(null);
iv_null = imageView;
}
/**
* 判断点击方块是否和空方块相邻
*
* @param imageView
* 点击的方块
* @return true:相邻,false:不相邻
*/
public boolean isNearByNull(ImageView imageView) {
// 点击方块和当前空方块的x或y只差一个单位就是相邻
ImageViewData mNullImageViewData = (ImageViewData) iv_null.getTag();
ImageViewData mImageViewData = (ImageViewData) imageView.getTag();
if (mNullImageViewData.y == mImageViewData.y && mImageViewData.x + 1 == mNullImageViewData.x) {// 点击方块在空方块上面
return true;
} else if (mNullImageViewData.y == mImageViewData.y && mImageViewData.x - 1 == mNullImageViewData.x) {// 点击方块在空方块下面
return true;
} else if (mNullImageViewData.y == mImageViewData.y + 1 && mImageViewData.x == mNullImageViewData.x) {// 点击方块在空方块左边
return true;
} else if (mNullImageViewData.y == mImageViewData.y - 1 && mImageViewData.x == mNullImageViewData.x) {// 点击方块在空方块右边
return true;
}
return false;
}
/**
* 小方块上绑定的数据
*/
class ImageViewData {
/** 小方块的原始位置 **/
public int x = 0;
public int y = 0;
/** 小方块的图片 **/
public Bitmap imageView;
/** 小方块的当前位置 **/
public int p_x;
public int p_y;
public ImageViewData(int x, int y, Bitmap imageView) {
super();
this.x = x;
this.y = y;
this.imageView = imageView;
this.p_x = x;
this.p_y = y;
}
}
}
1、onCreate中的所有代码及其子代码执行完成之前,里面设置的所有View是获取不到坐标的。
即:没到运行状态,view.getX()获取不到,结果都是0。(如果debug会发现,在oncreate中,即使走过了代码添加addView(),但此时界面并没有绘制View)
所以要判断,首次运行的时候,可以交换ImageView图片方块的内容,但是不能走动画,因为动画是通过getX()这种方法实现的。
我这边设置的是isAnim变量,首次不加载动画(达到了首次不会执行getX()这个效果)
private boolean isAnim = false;
onCreate(){ //…… //随机打乱顺序,这时onCreate还没有执行完,getX()肯定是0,但是默认isAnim是false,可以直接交换。 isAnim = false;//在整个onCreate最后写,已经过了首次,以后可以执行动画了 }
public void changeDataByImageView(final ImageView mImageView) { if(!isAnim){//不要执行动画,算是首次运行,直接开始交换 ImageViewData data1 = (ImageViewData) mImageView.getTag(); ImageViewData data2 = (ImageViewData) iv_null.getTag(); iv_null.setImageBitmap(data1.imageView); data2.imageView = data1.imageView; data2.p_x = data1.p_x; data2.p_y = data2.p_y; // 设置当前点击的是空方块 setNullImageView(mImageView); return; } //…… }
2、发现一个bug,移动时的效果动画都是从左向右的,需要去掉多余的代码。
====================修改后如下=================
package com.charspan.pintu; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.view.GestureDetector; import android.view.GestureDetector.OnGestureListener; 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.GridLayout; import android.widget.ImageView; import android.widget.Toast; public class MainActivity extends Activity { private int rowsNum = 3; private int colsNum = 5; private boolean isAnim = false; /** * 利用二维数组创建若干个游戏小方块 */ private ImageView[][] iv_game_arr; /** * 当前空方块的实例 */ private ImageView iv_null; /** * 游戏主界面 */ private GridLayout gl_main_game; /** * 当前手势 */ private GestureDetector mDetector; @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub return mDetector.onTouchEvent(event); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mDetector = new GestureDetector(this, new OnGestureListener() { @Override public boolean onSingleTapUp(MotionEvent e) { // TODO Auto-generated method stub return false; } @Override public void onShowPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // TODO Auto-generated method stub return false; } @Override public void onLongPress(MotionEvent e) { // TODO Auto-generated method stub } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { // TODO Auto-generated method stub int dir = getDirByGes(e1.getX(), e1.getY(), e2.getX(), e2.getY()); // Toast.makeText(MainActivity.this, "" + dir, // Toast.LENGTH_SHORT).show(); changeByDir(dir); return false; } @Override public boolean onDown(MotionEvent e) { // TODO Auto-generated method stub return false; } }); setContentView(R.layout.activity_main); iv_game_arr = new ImageView[rowsNum][colsNum]; // Bitmap bigBm =( // (BitmapDrawable)getResources().getDrawable(R.drawable.pic_1)).getBitmap(); // 获取一张大图 Bitmap bigBm = BitmapFactory.decodeResource(getResources(), R.drawable.pic_1); // 计算每个小方块的宽和高 int tuWandH = bigBm.getWidth() / colsNum; // 初始化游戏小方块 for (int i = 0; i < rowsNum; i++) { for (int j = 0; j < colsNum; j++) { Bitmap bm = Bitmap.createBitmap(bigBm, j * tuWandH, i * tuWandH, tuWandH, tuWandH); iv_game_arr[i][j] = new ImageView(this); iv_game_arr[i][j].setImageBitmap(bm); // 设置方块之间的间距 iv_game_arr[i][j].setPadding(2, 2, 2, 2); // 绑定自定义的数据 iv_game_arr[i][j].setTag(new ImageViewData(i, j, bm)); iv_game_arr[i][j].setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub boolean flag = isNearByNull((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 < rowsNum; i++) { for (int j = 0; j < colsNum; j++) { gl_main_game.addView(iv_game_arr[i][j]); } } // 设置最后一个方块为空 setNullImageView(iv_game_arr[rowsNum - 1][colsNum - 1]); randomMove(); isAnim = true; } /** * 根据手势方向获取与空方块相邻的位置,如果存在方块就进行数据交换 * * @param dir */ public void changeByDir(int dir) { // 获取空方块位置 ImageViewData data = (ImageViewData) iv_null.getTag(); // 根据手势方向,设置相邻位置坐标 int new_x = data.x; int new_y = data.y; if (dir == 1) {// new_x++; } else if (dir == 2) { new_x--; } else if (dir == 3) { new_y++; } else if (dir == 4) { new_y--; } // Toast.makeText(MainActivity.this, // data.x+" :: "+data.y,Toast.LENGTH_SHORT).show(); // 判断新坐标是否存在 if (new_x >= 0 && new_x < rowsNum && new_y >= 0 && new_y < colsNum) { // Toast.makeText(MainActivity.this, // new_x+" : "+new_y,Toast.LENGTH_SHORT).show(); // 存在的话开始移动 changeDataByImageView(iv_game_arr[new_x][new_y]); } } /** * 手势的判断 * * @param sx * @param sy * @param ex * @param ey * @return 上下左右 1 2 3 4 */ public int getDirByGes(float sx, float sy, float ex, float ey) { // 左右:横向距离大于竖直距离 boolean isLeftOrRight = Math.abs(sx - ex) > Math.abs(sy - ey); if (isLeftOrRight) {// 左右 // 左 :终点x小于起点x boolean isLeft = sx > ex; if (isLeft) { return 3; } else { return 4; } } else {// 上下 // 上:终点y大于起点y boolean isUp = sy > ey; if (isUp) { return 1; } else { return 2; } } } // 随机打乱顺序 public void randomMove() { // 打乱次数 for (int i = 0; i < 100; i++) { int dir = (int) (Math.random() * 4) + 1; changeByDir(dir); } // 开始交换,无动画 } /** * 动画结束后,交换两个方块的数据 * * @param mImageView * 点击的方块 */ public void changeDataByImageView(final ImageView mImageView) { if (!isAnim) {// 不要执行动画,算是首次运行,直接开始交换 ImageViewData data1 = (ImageViewData) mImageView.getTag(); ImageViewData data2 = (ImageViewData) iv_null.getTag(); iv_null.setImageBitmap(data1.imageView); data2.imageView = data1.imageView; data2.p_x = data1.p_x; data2.p_y = data2.p_y; // 设置当前点击的是空方块 setNullImageView(mImageView); return; } ImageViewData nullD = (ImageViewData) iv_null.getTag(); ImageViewData mD = (ImageViewData) mImageView.getTag(); // Toast.makeText(MainActivity.this, nullD.x+" :.. "+mD.x, // Toast.LENGTH_SHORT).show(); // Toast.makeText(MainActivity.this, nullD.y+" :.. "+mD.y, // Toast.LENGTH_SHORT).show(); Toast.makeText(MainActivity.this, mImageView.getX() + " :.. " + iv_null.getX(), Toast.LENGTH_SHORT).show(); Toast.makeText(MainActivity.this, mImageView.getY() + " : " + iv_null.getY(), Toast.LENGTH_SHORT).show(); // 创建一个动画,设置放心,移动距离 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 = new TranslateAnimation(0.1f, // mImageView.getWidth(), 0.1f, 0.1f); // 设置动画时长 translateAnimation.setDuration(70); // 设置动画结束后是否停留 translateAnimation.setFillAfter(true); // 动画结束后交换数据对象 translateAnimation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { mImageView.clearAnimation(); ImageViewData data1 = (ImageViewData) mImageView.getTag(); ImageViewData data2 = (ImageViewData) iv_null.getTag(); iv_null.setImageBitmap(data1.imageView); data2.imageView = data1.imageView; data2.p_x = data1.p_x; data2.p_y = data2.p_y; // 设置当前点击的是空方块 setNullImageView(mImageView); } }); mImageView.startAnimation(translateAnimation); } /** * 设置某个方块为空方块 * * @param imageView * 当前需要设置为空的方块实例 */ public void setNullImageView(ImageView imageView) { imageView.setImageBitmap(null); iv_null = imageView; } /** * 判断点击方块是否和空方块相邻 * * @param imageView * 点击的方块 * @return true:相邻,false:不相邻 */ public boolean isNearByNull(ImageView imageView) { // 点击方块和当前空方块的x或y只差一个单位就是相邻 ImageViewData mNullImageViewData = (ImageViewData) iv_null.getTag(); ImageViewData mImageViewData = (ImageViewData) imageView.getTag(); if (mNullImageViewData.y == mImageViewData.y && mImageViewData.x + 1 == mNullImageViewData.x) {// 点击方块在空方块上面 return true; } else if (mNullImageViewData.y == mImageViewData.y && mImageViewData.x - 1 == mNullImageViewData.x) {// 点击方块在空方块下面 return true; } else if (mNullImageViewData.y == mImageViewData.y + 1 && mImageViewData.x == mNullImageViewData.x) {// 点击方块在空方块左边 return true; } else if (mNullImageViewData.y == mImageViewData.y - 1 && mImageViewData.x == mNullImageViewData.x) {// 点击方块在空方块右边 return true; } return false; } /** * 小方块上绑定的数据 */ class ImageViewData { /** 小方块的原始位置 **/ public int x = 0; public int y = 0; /** 小方块的图片 **/ public Bitmap imageView; /** 小方块的当前位置 **/ public int p_x; public int p_y; public ImageViewData(int x, int y, Bitmap imageView) { super(); this.x = x; this.y = y; this.imageView = imageView; this.p_x = x; this.p_y = y; } } }
<br>
怎么发那么好看的代码。。。
快速实现不一样的移动拼图
15576 学习 · 67 问题
相似问题