Android實(shí)現(xiàn)拼圖小游戲
本文實(shí)例為大家分享了Android實(shí)現(xiàn)拼圖小游戲的具體代碼,供大家參考,具體內(nèi)容如下
目標(biāo)效果:
1.activity_main.xml頁(yè)面:
<?xml version="1.0" encoding="utf-8"?> <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.vivinia.puzzle.MainActivity"> <GridLayout android:id="@+id/gl_main_game" android:layout_width="match_parent" android:layout_height="match_parent" android:rowCount="3" android:columnCount="5"> </GridLayout> </RelativeLayout>
2.MainActivity.java頁(yè)面:
package com.example.vivinia.puzzle; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; import android.view.animation.Animation; import android.view.animation.TranslateAnimation; import android.widget.GridLayout; import android.widget.ImageView; import android.widget.Toast; public class MainActivity extends AppCompatActivity { /** * 當(dāng)前動(dòng)畫(huà)是否正在執(zhí)行 */ private boolean isAnimRun=false; /** *判斷游戲是否開(kāi)始*/ private boolean isGameStart=false; /** *利用二維數(shù)組創(chuàng)建若干個(gè)游戲小方塊 */ private ImageView[][] iv_game_arr = new ImageView[3][5]; /** *游戲主界面 */ private GridLayout gl_main_game; /** *當(dāng)前空方塊的實(shí)例保存 */ private ImageView iv_null_ImageView; /** *當(dāng)前手勢(shì) */ private GestureDetector mDetector; //非圖片位置可以進(jìn)行手勢(shì)滑動(dòng) @Override public boolean onTouchEvent(MotionEvent event) { return mDetector.onTouchEvent(event); //手勢(shì)監(jiān)聽(tīng) } //在圖片上可以進(jìn)行手勢(shì)滑動(dòng) @Override public boolean dispatchTouchEvent(MotionEvent ev) { mDetector.onTouchEvent(ev); return super.dispatchTouchEvent(ev); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mDetector=new GestureDetector(this, new GestureDetector.OnGestureListener() { @Override public boolean onDown(MotionEvent motionEvent) { return false; } @Override public void onShowPress(MotionEvent motionEvent) { } @Override public boolean onSingleTapUp(MotionEvent motionEvent) { return false; } @Override public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) { return false; } @Override public void onLongPress(MotionEvent motionEvent) { } /** *一瞬間執(zhí)行的方法 */ @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float v, float v1) { int type=getDirByGes(e1.getX(),e1.getY(),e2.getX(),e2.getY()); changeByDir(type); return false; } }); setContentView(R.layout.activity_main); //初始化游戲的若干個(gè)小方塊 Bitmap bigBm=((BitmapDrawable)getResources().getDrawable(R.drawable.puzzle_bg)).getBitmap(); int everyWidth=bigBm.getWidth()/5; //每個(gè)游戲小方塊的寬和高 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(bigBm,j*everyWidth,i*everyWidth,everyWidth,everyWidth);//根據(jù)行列來(lái)切成若干個(gè)游戲小圖片 iv_game_arr[i][j]=new ImageView(this); iv_game_arr[i][j].setImageBitmap(bm); //設(shè)置每一個(gè)游戲小方塊圖案 iv_game_arr[i][j].setPadding(2,2,2,2);//設(shè)置方塊之間的間距 iv_game_arr[i][j].setTag(new GameData(i,j,bm)); //綁定自定義的數(shù)據(jù) iv_game_arr[i][j].setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { boolean flag=isHasByNullImageView((ImageView)view); if(flag){ changeDataByImageView((ImageView)view); } } }); } } //初始化游戲主界面,并添加若干個(gè)小方塊 gl_main_game = (GridLayout) findViewById(R.id.gl_main_game); for(int i=0;i<iv_game_arr.length;i++){ for(int j=0;j<iv_game_arr[0].length;j++){ gl_main_game.addView(iv_game_arr[i][j]); } } /** *設(shè)置最后一個(gè)方塊為空的 */ setNullImageView(iv_game_arr[2][4]); /** *初始化隨機(jī)打亂順序 */ randomMove(); isGameStart=true; //開(kāi)始狀態(tài) } public void changeByDir(int type){ changeByDir(type,true); } /** * 根據(jù)手勢(shì)的方向,獲取空方塊相應(yīng)的相鄰位置如果存在方塊,那么進(jìn)行數(shù)據(jù)交換 * @param type 1:上,2:下,3:左,4:右 * @param isAnim true:有動(dòng)畫(huà),false:無(wú)動(dòng)畫(huà) */ public void changeByDir(int type,boolean isAnim){ /** *獲取當(dāng)前空方塊的位置 */ GameData mNullGameData= (GameData) iv_null_ImageView.getTag(); /** * 根據(jù)方向,設(shè)置相應(yīng)的相鄰的位置的坐標(biāo) */ int new_x=mNullGameData.x; int new_y=mNullGameData.y; if(type==1){ //要移動(dòng)的方塊在當(dāng)前空方塊的下邊 new_x++; }else if(type==2){ //要移動(dòng)的方塊在當(dāng)前空方塊的下邊 new_x--; }else if(type==3){ //要移動(dòng)的方塊在當(dāng)前空方塊的下邊 new_y++; } else if(type==4){ //要移動(dòng)的方塊在當(dāng)前空方塊的下邊 new_y--; } /** *判斷這個(gè)新坐標(biāo),是否存在 */ if(new_x>=0&&new_x<iv_game_arr.length&&new_y>=0&&new_y<iv_game_arr[0].length){ if(isAnim) { /** *存在的話(huà),開(kāi)始移動(dòng) */ changeDataByImageView(iv_game_arr[new_x][new_y]); }else{ changeDataByImageView(iv_game_arr[new_x][new_y],isAnim); } }else{ //什么也不做 } } /** *判斷游戲結(jié)束的方法 */ public void isGameOver(){ boolean isGameOver=true; //要便利每個(gè)游戲小方塊 for(int i=0;i<iv_game_arr.length;i++){ for(int j=0;j<iv_game_arr[0].length;j++){ //為空的方塊數(shù)據(jù)不判斷跳過(guò) if(iv_game_arr[i][j]==iv_null_ImageView){ continue; } GameData mGameData= (GameData) iv_game_arr[i][j].getTag(); if(!mGameData.isTrue()){ isGameOver=false; break; } } } //根據(jù)一個(gè)開(kāi)關(guān)變量決定游戲是否結(jié)束,結(jié)束時(shí)給提示 if(isGameOver){ Toast.makeText(this,"游戲結(jié)束",Toast.LENGTH_LONG).show(); } } /** * 手勢(shì)判斷,是向左還是向右 * @param start_x 手勢(shì)的起始點(diǎn)x * @param start_y 手勢(shì)的起始點(diǎn)y * @param end_x 手勢(shì)的終止點(diǎn)x * @param end_y 手勢(shì)的起始點(diǎn)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; } } } /** * 隨機(jī)打亂順序 */ public void randomMove(){ //打亂的次數(shù) for(int i=0;i<10;i++){ //根據(jù)手勢(shì)開(kāi)始交換,無(wú)動(dòng)畫(huà) int type=(int)(Math.random()*4)+1; changeByDir(type,false); } } public void changeDataByImageView(final ImageView mImageView) { changeDataByImageView(mImageView,true); } /** * 利用動(dòng)畫(huà)結(jié)束之后,交換兩個(gè)方塊的數(shù)據(jù) * @param mImageView 點(diǎn)擊的方塊 * @param isAnim true:有動(dòng)畫(huà),false:無(wú)動(dòng)畫(huà) */ public void changeDataByImageView(final ImageView mImageView,boolean isAnim){ if(isAnimRun){ //如果動(dòng)畫(huà)已經(jīng)開(kāi)始,則不做交換操作 return; } if(!isAnim){ //如果沒(méi)有動(dòng)畫(huà) GameData mGameData= (GameData) mImageView.getTag(); iv_null_ImageView.setImageBitmap(mGameData.bm); GameData mNullGameData= (GameData) iv_null_ImageView.getTag(); mNullGameData.bm=mGameData.bm; mNullGameData.p_x=mGameData.p_x; mNullGameData.p_y=mGameData.p_y; setNullImageView(mImageView); //設(shè)置當(dāng)前點(diǎn)擊的是空方塊 if(isGameStart) { isGameOver(); //成功時(shí)談一個(gè)toast } return; } /** *創(chuàng)建一個(gè)動(dòng)畫(huà),設(shè)置好方向,移動(dòng)的距離 */ TranslateAnimation translateAnimation = null; if(mImageView.getX()>iv_null_ImageView.getX()){ //當(dāng)前點(diǎn)擊的方塊在空方塊下邊 //往上移動(dòng) translateAnimation=new TranslateAnimation(0.1f,-mImageView.getWidth(),0.1f,0.1f); }else if(mImageView.getX()<iv_null_ImageView.getX()){ //當(dāng)前點(diǎn)擊的方塊在空方塊下邊 //往下移動(dòng) translateAnimation=new TranslateAnimation(0.1f,mImageView.getWidth(),0.1f,0.1f); } else if(mImageView.getX()>iv_null_ImageView.getY()){ //當(dāng)前點(diǎn)擊的方塊在空方塊下邊 //往左移動(dòng) translateAnimation=new TranslateAnimation(0.1f,0.1f,0.1f,-mImageView.getWidth()); } else if(mImageView.getX()<iv_null_ImageView.getY()){ //當(dāng)前點(diǎn)擊的方塊在空方塊下邊 //往右移動(dòng) translateAnimation=new TranslateAnimation(0.1f,0.1f,0.1f,mImageView.getWidth()); } /** * 設(shè)置動(dòng)畫(huà)的時(shí)長(zhǎng) */ translateAnimation.setDuration(70); /** * 設(shè)置動(dòng)畫(huà)結(jié)束之后是否停留 */ translateAnimation.setFillAfter(true); /** * 設(shè)置動(dòng)畫(huà)結(jié)束之后真正的交換數(shù)據(jù) */ translateAnimation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { isAnimRun=true; //動(dòng)畫(huà)開(kāi)始 } @Override public void onAnimationEnd(Animation animation) { isAnimRun=false; //動(dòng)畫(huà)結(jié)束 /** *結(jié)束之后,清除動(dòng)畫(huà) */ mImageView.clearAnimation(); GameData mGameData= (GameData) mImageView.getTag(); iv_null_ImageView.setImageBitmap(mGameData.bm); GameData mNullGameData= (GameData) iv_null_ImageView.getTag(); mNullGameData.bm=mGameData.bm; mNullGameData.p_x=mGameData.p_x; mNullGameData.p_y=mGameData.p_y; setNullImageView(mImageView); //設(shè)置當(dāng)前點(diǎn)擊的是空方塊 if(isGameStart) { isGameOver(); //成功時(shí)談一個(gè)toast } } @Override public void onAnimationRepeat(Animation animation) { } }); /** * 執(zhí)行動(dòng)畫(huà) */ mImageView.startAnimation(translateAnimation); } /** * 設(shè)置某個(gè)方塊為空方塊 * @param mImageView 當(dāng)前要設(shè)置為空的方塊的實(shí)例 */ public void setNullImageView(ImageView mImageView){ mImageView.setImageBitmap(null); //設(shè)置為空 iv_null_ImageView=mImageView; } /** * 判斷當(dāng)前點(diǎn)擊的方塊,是否與空方塊的位置關(guān)系是相鄰關(guān)系 * @param mImageView 所點(diǎn)擊的方塊 * @return true:相鄰;false:不相鄰 */ public boolean isHasByNullImageView(ImageView mImageView){ /** *分別獲取當(dāng)前空方塊的位置與點(diǎn)擊方塊的位置,通過(guò)x,y兩邊都差1的方式判斷 */ GameData mNullGameData= (GameData) iv_null_ImageView.getTag(); //空方塊身上的數(shù)據(jù) GameData mGameData= (GameData)mImageView.getTag(); //點(diǎn)擊方塊身上的數(shù)據(jù) if(mNullGameData.y==mGameData.y&&mGameData.x+1==mNullGameData.x){ //當(dāng)前點(diǎn)擊的方塊在空方塊的上邊 return true; }else if(mNullGameData.y==mGameData.y&&mGameData.x-1==mNullGameData.x){ //當(dāng)前點(diǎn)擊的方塊在空方塊的下邊 return true; }else if(mNullGameData.y==mGameData.y+1&&mGameData.x==mNullGameData.x){ //當(dāng)前點(diǎn)擊的方塊在空方塊的左邊 return true; }else if(mNullGameData.y==mGameData.y-1&&mGameData.x+1==mNullGameData.x){ //當(dāng)前點(diǎn)擊的方塊在空方塊的右邊 return true; } return false; } /** * 每個(gè)游戲小方塊上要綁定的數(shù)據(jù) */ class GameData{ /** *每個(gè)小方塊的實(shí)際位置x */ public int x=0; /** *每個(gè)小方塊的實(shí)際位置x */ public int y=0; /** *每個(gè)小方塊的圖片 */ public Bitmap bm; /** *每個(gè)小方塊的圖片的位置 */ public int p_x=0; /** *每個(gè)小方塊的圖片的位置 */ public int p_y=0; public GameData(int x, int y, Bitmap bm) { this.x = x; this.y = y; this.bm = bm; this.p_x = x; this.p_y = y; } /** * 每個(gè)小方塊的位置是否正確 * @return true:正確,false:不正確 */ public boolean isTrue() { if(x==p_x&&y==p_y) { return true; } return false; } } }
3.設(shè)置去掉標(biāo)題欄樣式
styles.xml頁(yè)面:
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> <style name="MyAppTheme" parent="AppTheme"> <item name="windowNoTitle">true</item> <item name="windowActionBar">false</item> <item name="android:windowFullscreen">true</item> <item name="android:windowContentOverlay">@null</item> </style> </resources>
4.清單文件中使用該樣式
AndroidManifest.xml頁(yè)面:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.vivinia.puzzle"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/MyAppTheme"> <activity android:name=".MainActivity" android:screenOrientation="landscape"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
源碼下載:點(diǎn)擊打開(kāi)鏈接
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 基于Android平臺(tái)實(shí)現(xiàn)拼圖小游戲
- Android實(shí)現(xiàn)美女拼圖游戲詳解
- Android實(shí)現(xiàn)九宮格拼圖游戲
- Android自定義View實(shí)現(xiàn)拼圖小游戲
- Android利用ViewDragHelper輕松實(shí)現(xiàn)拼圖游戲的示例
- Android拼圖游戲 玩轉(zhuǎn)從基礎(chǔ)到應(yīng)用手勢(shì)變化
- Android實(shí)現(xiàn)滑塊拼圖驗(yàn)證碼功能
- Android 簡(jiǎn)單的實(shí)現(xiàn)滑塊拼圖驗(yàn)證碼功能
- Android Studio做超好玩的拼圖游戲 附送詳細(xì)注釋源碼
- Android實(shí)現(xiàn)九格智能拼圖算法
相關(guān)文章
android使用viewpager計(jì)算偏移量實(shí)現(xiàn)選項(xiàng)卡功能
這篇文章主要為大家詳細(xì)介紹了android使用viewpager計(jì)算偏移量實(shí)現(xiàn)選項(xiàng)卡功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12Kotlin創(chuàng)建一個(gè)好用的協(xié)程作用域
這篇文章主要介紹了Kotlin創(chuàng)建一個(gè)好用的協(xié)程作用域,kotlin中使用協(xié)程,是一定要跟協(xié)程作用域一起配合使用的,否則可能協(xié)程的生命周期無(wú)法被準(zhǔn)確控制,造成內(nèi)存泄漏或其他問(wèn)題2022-07-07解決Android Studio 格式化快捷鍵和QQ 鎖鍵盤(pán)快捷鍵沖突問(wèn)題
每次打開(kāi)qq使用android studio格式化的快捷鍵Ctrl + Alt +L時(shí),總是出現(xiàn)qq鎖鍵盤(pán)提示,怎么回事呢?下面小編給大家?guī)?lái)了android studio格式化的快捷鍵和qq快捷鍵之間的沖突的處理方法,需要的朋友參考下吧2017-12-12Android開(kāi)發(fā)之微信底部菜單欄實(shí)現(xiàn)的幾種方法匯總
這篇文章主要介紹了Android開(kāi)發(fā)之微信底部菜單欄實(shí)現(xiàn)的幾種方法,下面小編把每種方法通過(guò)實(shí)例逐一給大家介紹,需要的朋友可以參考下2016-09-09Android Tween動(dòng)畫(huà)之RotateAnimation實(shí)現(xiàn)圖片不停旋轉(zhuǎn)效果實(shí)例介紹
Android中如何使用rotate實(shí)現(xiàn)圖片不停旋轉(zhuǎn)的效果,下面與大家共同分析下Tween動(dòng)畫(huà)的rotate實(shí)現(xiàn)旋轉(zhuǎn)效果,感興趣的朋友可以參考下哈2013-05-05Android仿簡(jiǎn)書(shū)搜索框效果的示例代碼
本篇文章主要介紹了Android仿簡(jiǎn)書(shū)搜索框效果的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10Kotlin編程基礎(chǔ)數(shù)據(jù)類(lèi)型示例詳解
這篇文章主要為大家介紹了Kotlin編程基礎(chǔ)數(shù)據(jù)類(lèi)型示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08Android 實(shí)現(xiàn)可任意拖動(dòng)的懸浮窗功能(類(lèi)似懸浮球)
這篇文章主要介紹了Android 可任意拖動(dòng)的懸浮窗(類(lèi)似懸浮球),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05