本文实例为大家分享了Android实现拼图小游戏的具体代码,供大家参考,具体内容如下

目标效果:

 

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 {
 
 /**
 * 当前动画是否正在执行
 */
 private boolean isAnimRun=false;
 /**
 *判断游戏是否开始*/
 private boolean isGameStart=false;
 /**
 *利用二维数组创建若干个游戏小方块
 */
 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); //手势监听
 }
 
 //在图片上可以进行手势滑动
 @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) {
 
 }
 
 /**
 *一瞬间执行的方法
 */
 @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);//根据行列来切成若干个游戏小图片
 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 GameData(i,j,bm)); //绑定自定义的数据
 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]);
 }
 }
 /**
 *设置最后一个方块为空的
 */
 setNullImageView(iv_game_arr[2][4]);
 /**
 *初始化随机打乱顺序
 */
 randomMove();
 isGameStart=true; //开始状态
 }
 
 
 
 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_ImageView.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) {
 /**
 *存在的话,开始移动
 */
 changeDataByImageView(iv_game_arr[new_x][new_y]);
 }else{
 changeDataByImageView(iv_game_arr[new_x][new_y],isAnim);
 }
 }else{
 //什么也不做
 }
 }
 /**
 *判断游戏结束的方法
 */
 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  ){
 //为空的方块数据不判断跳过
 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;
 }
 }
 }
 //根据一个开关变量决定游戏是否结束,结束时给提示
 if(isGameOver){
 Toast.makeText(this,"游戏结束",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(){
 //打乱的次数
 for(int i=0;i<10;i  ){
 //根据手势开始交换,无动画
 int type=(int)(Math.random()*4) 1;
 changeByDir(type,false);
 }
 }
 public void changeDataByImageView(final ImageView mImageView) {
 changeDataByImageView(mImageView,true);
 }
 
 /**
 * 利用动画结束之后,交换两个方块的数据
 * @param mImageView 点击的方块
 * @param isAnim true:有动画,false:无动画
 */
 public void changeDataByImageView(final ImageView mImageView,boolean isAnim){
 if(isAnimRun){ //如果动画已经开始,则不做交换操作
 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); //设置当前点击的是空方块
 if(isGameStart) {
 isGameOver(); //成功时谈一个toast
 }
 return;
 }
 /**
 *创建一个动画,设置好方向,移动的距离
 */
 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());
 }
 /**
 * 设置动画的时长
 */
 translateAnimation.setDuration(70);
 /**
 * 设置动画结束之后是否停留
 */
 translateAnimation.setFillAfter(true);
 /**
 * 设置动画结束之后真正的交换数据
 */
 translateAnimation.setAnimationListener(new Animation.AnimationListener() {
 @Override
 public void onAnimationStart(Animation animation) {
 isAnimRun=true; //动画开始
 }
 
 @Override
 public void onAnimationEnd(Animation animation) {
 isAnimRun=false; //动画结束
 /**
 *结束之后,清除动画
 */
 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); //设置当前点击的是空方块
 if(isGameStart) {
 isGameOver(); //成功时谈一个toast
 }
 }
 
 @Override
 public void onAnimationRepeat(Animation animation) {
 }
 });
 /**
 * 执行动画
 */
 mImageView.startAnimation(translateAnimation);
 }
 
 /**
 * 设置某个方块为空方块
 * @param mImageView 当前要设置为空的方块的实例
 */
 public void setNullImageView(ImageView mImageView){
 mImageView.setImageBitmap(null); //设置为空
 iv_null_ImageView=mImageView;
 }
 
 /**
 * 判断当前点击的方块,是否与空方块的位置关系是相邻关系
 * @param mImageView 所点击的方块
 * @return true:相邻;false:不相邻
 */
 public boolean isHasByNullImageView(ImageView mImageView){
 /**
 *分别获取当前空方块的位置与点击方块的位置,通过x,y两边都差1的方式判断
 */
 GameData mNullGameData= (GameData) iv_null_ImageView.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 1==mNullGameData.x){ //当前点击的方块在空方块的右边
 return true;
 }
 return false;
 }
 
 /**
 * 每个游戏小方块上要绑定的数据
 */
 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.设置去掉标题栏样式

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>

源码下载:点击打开链接

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持Devmax。

Android实现拼图小游戏的更多相关文章

  1. html5 canvas合成海报所遇问题及解决方案总结

    这篇文章主要介绍了html5 canvas合成海报所遇问题及解决方案总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Html5 video标签视频的最佳实践

    这篇文章主要介绍了Html5 video标签视频的最佳实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  3. HTML5在微信内置浏览器下右上角菜单的调整字体导致页面显示错乱的问题

    HTML5在微信内置浏览器下,在右上角菜单的调整字体导致页面显示错乱的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

  4. ios – containerURLForSecurityApplicationGroupIdentifier:在iPhone和Watch模拟器上给出不同的结果

    我使用默认的XCode模板创建了一个WatchKit应用程序.我向iOSTarget,WatchkitAppTarget和WatchkitAppExtensionTarget添加了应用程序组权利.(这是应用程序组名称:group.com.lombax.fiveminutes)然后,我尝试使用iOSApp和WatchKitExtension访问共享文件夹URL:延期:iOS应用:但是,测试NSURL

  5. Ionic – Splash Screen适用于iOS,但不适用于Android

    我有一个离子应用程序,其中使用CLI命令离子资源生成的启动画面和图标iOS版本与正在渲染的启动画面完美配合,但在Android版本中,只有在加载应用程序时才会显示白屏.我检查了config.xml文件,所有路径看起来都是正确的,生成的图像出现在相应的文件夹中.(我使用了splash.psd模板来生成它们.我错过了什么?这是config.xml文件供参考,我觉得我在这里做错了–解决方法在config.xml中添加以下键:它对我有用!

  6. ios – 无法启动iPhone模拟器

    /Library/Developer/CoreSimulator/Devices/530A44CB-5978-4926-9E91-E9DBD5BFB105/data/Containers/Bundle/Application/07612A5C-659D-4C04-ACD3-D211D2830E17/ProductName.app/ProductName然后,如果您在Xcode构建设置中选择标准体系结构并再次构建和运行,则会产生以下结果:dyld:lazysymbolbindingFailed:Symbol

  7. Xamarin iOS图像在Grid内部重叠

    heyo,所以在Xamarin我有一个使用并在其中包含一对,所有这些都包含在内.这在Xamarin.Android中看起来完全没问题,但是在Xamarin.iOS中,图像与标签重叠.我不确定它的区别是什么–为什么它在Xamarin.Android中看起来不错但在iOS中它的全部都不稳定?

  8. 在iOS上向后播放HTML5视频

    我试图在iPad上反向播放HTML5视频.HTML5元素包括一个名为playbackRate的属性,它允许以更快或更慢的速率或相反的方式播放视频.根据Apple’sdocumentation,iOS不支持此属性.通过每秒多次设置currentTime属性,可以反复播放,而无需使用playbackRate.这种方法适用于桌面Safari,但似乎在iOS设备上的搜索限制为每秒1次更新–在我的情况下太慢了.有没有办法在iOS设备上向后播放HTML5视频?解决方法iOS6Safari现在支持playbackRat

  9. 使用 Swift 语言编写 Android 应用入门

    Swift标准库可以编译安卓armv7的内核,这使得可以在安卓移动设备上执行Swift语句代码。做梦,虽然Swift编译器可以胜任在安卓设备上编译Swift代码并运行。这需要的不仅仅是用Swift标准库编写一个APP,更多的是你需要一些框架来搭建你的应用用户界面,以上这些Swift标准库不能提供。简单来说,构建在安卓设备上使用的Swiftstdlib需要libiconv和libicu。通过命令行执行以下命令:gitclonegit@github.com:SwiftAndroid/libiconv-libi

  10. Android – 调用GONE然后VISIBLE使视图显示在错误的位置

    我有两个视图,A和B,视图A在视图B上方.当我以编程方式将视图A设置为GONE时,它将消失,并且它正下方的视图将转到视图A的位置.但是,当我再次将相同的视图设置为VISIBLE时,它会在视图B上显示.我不希望这样.我希望视图B回到原来的位置,这是我认为会发生的事情.我怎样才能做到这一点?编辑–代码}这里是XML:解决方法您可以尝试将两个视图放在RelativeLayout中并相对于彼此设置它们的位置.

随机推荐

  1. Flutter 网络请求框架封装详解

    这篇文章主要介绍了Flutter 网络请求框架封装详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Android单选按钮RadioButton的使用详解

    今天小编就为大家分享一篇关于Android单选按钮RadioButton的使用详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

  3. 解决android studio 打包发现generate signed apk 消失不见问题

    这篇文章主要介绍了解决android studio 打包发现generate signed apk 消失不见问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

  4. Android 实现自定义圆形listview功能的实例代码

    这篇文章主要介绍了Android 实现自定义圆形listview功能的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  5. 详解Android studio 动态fragment的用法

    这篇文章主要介绍了Android studio 动态fragment的用法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. Android用RecyclerView实现图标拖拽排序以及增删管理

    这篇文章主要介绍了Android用RecyclerView实现图标拖拽排序以及增删管理的方法,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下

  7. Android notifyDataSetChanged() 动态更新ListView案例详解

    这篇文章主要介绍了Android notifyDataSetChanged() 动态更新ListView案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

  8. Android自定义View实现弹幕效果

    这篇文章主要为大家详细介绍了Android自定义View实现弹幕效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. Android自定义View实现跟随手指移动

    这篇文章主要为大家详细介绍了Android自定义View实现跟随手指移动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. Android实现多点触摸操作

    这篇文章主要介绍了Android实现多点触摸操作,实现图片的放大、缩小和旋转等处理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部