溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Android如何實現(xiàn)拼圖小游戲

發(fā)布時間:2021-04-16 10:09:23 來源:億速云 閱讀:189 作者:小新 欄目:移動開發(fā)

小編給大家分享一下Android如何實現(xiàn)拼圖小游戲,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

具體內(nèi)容如下

目標效果:

 Android如何實現(xiàn)拼圖小游戲

1.activity_main.xml頁面:

<?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頁面:

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 {
 
 /**
 * 當前動畫是否正在執(zhí)行
 */
 private boolean isAnimRun=false;
 /**
 *判斷游戲是否開始*/
 private boolean isGameStart=false;
 /**
 *利用二維數(shù)組創(chuàng)建若干個游戲小方塊
 */
 private ImageView[][] iv_game_arr = new ImageView[3][5];
 /**
 *游戲主界面
 */
 private GridLayout gl_main_game;
 /**
 *當前空方塊的實例保存
 */
 private ImageView iv_null_ImageView;
 /**
 *當前手勢
 */
 private GestureDetector mDetector;
 
 //非圖片位置可以進行手勢滑動
 @Override
 public boolean onTouchEvent(MotionEvent event) {
 return mDetector.onTouchEvent(event); //手勢監(jiān)聽
 }
 
 //在圖片上可以進行手勢滑動
 @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);
 //初始化游戲的若干個小方塊
 Bitmap bigBm=((BitmapDrawable)getResources().getDrawable(R.drawable.puzzle_bg)).getBitmap();
 int everyWidth=bigBm.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(bigBm,j*everyWidth,i*everyWidth,everyWidth,everyWidth);//根據(jù)行列來切成若干個游戲小圖片
 iv_game_arr[i][j]=new ImageView(this);
 iv_game_arr[i][j].setImageBitmap(bm); //設(shè)置每一個游戲小方塊圖案
 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);
 }
 }
 });
 }
 }
 //初始化游戲主界面,并添加若干個小方塊
 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è)置最后一個方塊為空的
 */
 setNullImageView(iv_game_arr[2][4]);
 /**
 *初始化隨機打亂順序
 */
 randomMove();
 isGameStart=true; //開始狀態(tài)
 }
 
 
 
 public void changeByDir(int type){
 changeByDir(type,true);
 }
 
 /**
 * 根據(jù)手勢的方向,獲取空方塊相應(yīng)的相鄰位置如果存在方塊,那么進行數(shù)據(jù)交換
 * @param type 1:上,2:下,3:左,4:右
 * @param isAnim true:有動畫,false:無動畫
 */
 public void changeByDir(int type,boolean isAnim){
 /**
 *獲取當前空方塊的位置
 */
 GameData mNullGameData= (GameData) iv_null_ImageView.getTag();
 /**
 * 根據(jù)方向,設(shè)置相應(yīng)的相鄰的位置的坐標
 */
 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) {
 /**
 *存在的話,開始移動
 */
 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;
 //要便利每個游戲小方塊
 for(int i=0;i<iv_game_arr.length;i++){
 for(int j=0;j<iv_game_arr[0].length;j++){
 //為空的方塊數(shù)據(jù)不判斷跳過
 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ù)一個開關(guān)變量決定游戲是否結(jié)束,結(jié)束時給提示
 if(isGameOver){
 Toast.makeText(this,"游戲結(jié)束",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 randomMove(){
 //打亂的次數(shù)
 for(int i=0;i<10;i++){
 //根據(jù)手勢開始交換,無動畫
 int type=(int)(Math.random()*4)+1;
 changeByDir(type,false);
 }
 }
 public void changeDataByImageView(final ImageView mImageView) {
 changeDataByImageView(mImageView,true);
 }
 
 /**
 * 利用動畫結(jié)束之后,交換兩個方塊的數(shù)據(jù)
 * @param mImageView 點擊的方塊
 * @param isAnim true:有動畫,false:無動畫
 */
 public void changeDataByImageView(final ImageView mImageView,boolean isAnim){
 if(isAnimRun){ //如果動畫已經(jīng)開始,則不做交換操作
 return;
 }
 if(!isAnim){ //如果沒有動畫
 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è)置當前點擊的是空方塊
 if(isGameStart) {
 isGameOver(); //成功時談一個toast
 }
 return;
 }
 /**
 *創(chuàng)建一個動畫,設(shè)置好方向,移動的距離
 */
 TranslateAnimation translateAnimation = null;
 if(mImageView.getX()>iv_null_ImageView.getX()){ //當前點擊的方塊在空方塊下邊
 //往上移動
 translateAnimation=new TranslateAnimation(0.1f,-mImageView.getWidth(),0.1f,0.1f);
 }else if(mImageView.getX()<iv_null_ImageView.getX()){ //當前點擊的方塊在空方塊下邊
 //往下移動
 translateAnimation=new TranslateAnimation(0.1f,mImageView.getWidth(),0.1f,0.1f);
 }
 else if(mImageView.getX()>iv_null_ImageView.getY()){ //當前點擊的方塊在空方塊下邊
 //往左移動
 translateAnimation=new TranslateAnimation(0.1f,0.1f,0.1f,-mImageView.getWidth());
 }
 else if(mImageView.getX()<iv_null_ImageView.getY()){ //當前點擊的方塊在空方塊下邊
 //往右移動
 translateAnimation=new TranslateAnimation(0.1f,0.1f,0.1f,mImageView.getWidth());
 }
 /**
 * 設(shè)置動畫的時長
 */
 translateAnimation.setDuration(70);
 /**
 * 設(shè)置動畫結(jié)束之后是否停留
 */
 translateAnimation.setFillAfter(true);
 /**
 * 設(shè)置動畫結(jié)束之后真正的交換數(shù)據(jù)
 */
 translateAnimation.setAnimationListener(new Animation.AnimationListener() {
 @Override
 public void onAnimationStart(Animation animation) {
 isAnimRun=true; //動畫開始
 }
 
 @Override
 public void onAnimationEnd(Animation animation) {
 isAnimRun=false; //動畫結(jié)束
 /**
 *結(jié)束之后,清除動畫
 */
 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è)置當前點擊的是空方塊
 if(isGameStart) {
 isGameOver(); //成功時談一個toast
 }
 }
 
 @Override
 public void onAnimationRepeat(Animation animation) {
 }
 });
 /**
 * 執(zhí)行動畫
 */
 mImageView.startAnimation(translateAnimation);
 }
 
 /**
 * 設(shè)置某個方塊為空方塊
 * @param mImageView 當前要設(shè)置為空的方塊的實例
 */
 public void setNullImageView(ImageView mImageView){
 mImageView.setImageBitmap(null); //設(shè)置為空
 iv_null_ImageView=mImageView;
 }
 
 /**
 * 判斷當前點擊的方塊,是否與空方塊的位置關(guān)系是相鄰關(guān)系
 * @param mImageView 所點擊的方塊
 * @return true:相鄰;false:不相鄰
 */
 public boolean isHasByNullImageView(ImageView mImageView){
 /**
 *分別獲取當前空方塊的位置與點擊方塊的位置,通過x,y兩邊都差1的方式判斷
 */
 GameData mNullGameData= (GameData) iv_null_ImageView.getTag(); //空方塊身上的數(shù)據(jù)
 GameData mGameData= (GameData)mImageView.getTag(); //點擊方塊身上的數(shù)據(jù)
 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+1==mNullGameData.x){ //當前點擊的方塊在空方塊的右邊
 return true;
 }
 return false;
 }
 
 /**
 * 每個游戲小方塊上要綁定的數(shù)據(jù)
 */
 class GameData{
 /**
 *每個小方塊的實際位置x
 */
 public int x=0;
 /**
 *每個小方塊的實際位置x
 */
 public int y=0;
 /**
 *每個小方塊的圖片
 */
 public Bitmap bm;
 /**
 *每個小方塊的圖片的位置
 */
 public int p_x=0;
 /**
 *每個小方塊的圖片的位置
 */
 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;
 }
 
 /**
 * 每個小方塊的位置是否正確
 * @return true:正確,false:不正確
 */
 public boolean isTrue() {
 if(x==p_x&&y==p_y) {
 return true;
 }
 return false;
 }
 }
}

3.設(shè)置去掉標題欄樣式

styles.xml頁面:

<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頁面:

<?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>

以上是“Android如何實現(xiàn)拼圖小游戲”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI