XMl布局:
<RelativeLayout xmlns:android="http://schemas.android.com/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;
@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);
setContentView(R.layout.activity_main);
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
Log.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;
}
@Override
public boolean onDown(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
});
/*初始化游戏的若干个小方块*/
//获取一张大图
Bitmap bitmap = ((BitmapDrawable)getResources().getDrawable(R.drawable.pic1)).getBitmap();
int wh = bitmap.getWidth()/5;
//小方块的宽高是整个屏幕的宽除以5
int 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() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
boolean 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() {
@Override
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
isAnimRun = true;
}
@Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationEnd(Animation animation) {
// TODO Auto-generated method stub
isAnimRun = 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;
}
}
}
源码下载