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;
}
}
}
源碼下載