欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android实现拼图小游戏

程序员文章站 2023-10-22 18:07:28
本文实例为大家分享了android实现拼图小游戏的具体代码,供大家参考,具体内容如下 目标效果:   1.activity_main.xml页面:...

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

目标效果:

 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>

源码下载:点击打开链接

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