❤️手把手教你用Android Studio做一个超好玩的拼图游戏,0基础Android小白也能包你学会,附送超详细注释的源码,建议收藏!❤️

Posted 振华OPPO

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了❤️手把手教你用Android Studio做一个超好玩的拼图游戏,0基础Android小白也能包你学会,附送超详细注释的源码,建议收藏!❤️相关的知识,希望对你有一定的参考价值。

一、项目概述

之前有不少粉丝私信我说,能不能用android原生的语言开发一款在手机上运行的游戏呢?

说实话,使用java语言直接开发游戏这个需求有点难,因为一些比较复杂的游戏都是通过cocos2D或者Unity3D等游戏引擎开发出来的,然后再移植到Android手机当中,使用完整的游戏引擎开发的过程比较简单,而且界面比较流畅,观感和体验度都很好。

所以直接使用java开发的游戏并不多。当然,虽说不多但也有。简单些的比如:2048、拼图游戏、贪吃蛇、推箱子等,复杂点的比如:斗地主,这些都可以用java语言开发。因为这些游戏刷新界面次数比较少,是可以用java开发出来的。

所以在这篇博客里面,我们就来开发一款简单的拼图游戏,这款拼图游戏就和我们小时候玩的游戏是一样的,这里面的涉及到的算法不多,可以很容易学会,是作为入门Android的一个非常好的实例。

二、开发环境

三、需求分析

我们先来看下最终要实现的效果

可以看到游戏开始后,开始计时,然后下面是被打乱的九宫格图片,最后一块是空白的,因为要留出空间移动,中间是重新开始按钮,点击就会重新计时而且拼图碎片重新打乱,最底下是原图,方便大家对照着进行拼凑。当你拼图完成后,上面的第九块拼图会立刻显示出来补齐整张图片,然后弹出对话框,告诉你拼图成功,用时为多少多少秒,点击确认即可。

所以我们分为六个步骤来实现

  1. 拼图游戏布局绘制
  2. 拼图游戏时间计时
  3. 拼图游戏打乱显示
  4. 拼图游戏碎片位置切换
  5. 拼图游戏成功的条件
  6. 拼图游戏重新开始

我们来看下需要准备的图片素材

这里先是一张小熊的样图,命名就是yangtu。然后就是将它按九宫格裁剪成的九张图片,命名格式我来解释下:我们看第八张我选中的图片,它的名字为img_xiaoxiong_02x01。这里解释下为什么是02x01,这就可以看做一个三行三列的二维数组,排列方式就和下面一样。数组行和列下标都是从0开始,所以第八张就是在第2行第1列,所以就是02x01,其他的也以此类推。
大家可以自己选图片进行裁剪命名,当然也可以直接下载我的源码,里面就有这些图片。

下面我们就一起来实现这个拼图游戏吧~

四、实现过程

1、拼图游戏布局绘制

我们首先来分析下游戏的layout布局

再来看下最终实现的效果图,先分析一下怎么绘制布局,实现一个项目的第一步是将布局按照自己期望的样子完成。

因为这是一个上下结构,所以我们用一个线性布局(LinearLayout)来实现最合适,方向(orientation)设置为竖直方向(vertical)。可以看到这个拼图分为三行三列,所以我们直接将每一行分为一个小的LinearLayout,一共三个,然后在每个小的LinearLayout里面水平放三个图片按钮,这样就实现了,思路有了,我们来绘制吧。

我们来绘制游戏的layout布局

从上至下的第一个布局是显示时间的TextView,我们将它的id设置为pt_tv_time,layout_width和layout_height都设置为wrap_content,就是适应内容大小,然后text文本内容设为“时间:0”,这个是方便测试写上文本的,因为边写代码可以边看旁边的效果变化。

然后layout_gravity设置为"center",就是设置自己在父容器(顶层的LinearLayout)中居中,这里补充下知识点:

  • gravity是设置自身内部元素的对齐方式。比如一个TextView,则是设置内部文字的对齐方式。如果是ViewGroup组件如LinearLayout的话,则为设置它内部view组件的对齐方式。

  • layout_gravity是设置自身相当于父容器的对齐方式。比如,一个TextView设置layout_gravity属性,则表示这TextView相对于父容器的对齐方式。

再来改变下字体大小,设置textSize为20sp,sp是像素,补充下单位的知识点:

  • dp: device independent pixels(设备独立像素),不同设备有不同的显示效果,和设备硬件有关。
  • px: pixels(像素).,不同设备显示效果相同,这个用的比较多。
  • pt: point,是一个标准的长度单位,1pt=1/72英寸,用于印刷业,非常简单易用。
  • sp: scaled pixels(放大像素),主要用于字体显示best for textsize。

最后设置字体颜色为#FF0000,即红色。一般是通过colors.xml资源来引用,这里因为红色比较好表示就直接设置了。

TextView代码如下:

<TextView
        android:id="@+id/pt_tv_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="时间 : 0"
        android:layout_gravity="center"
        android:textSize="20sp"
        android:textColor="#FF0000"/>

设置完成后,我们来看下效果图:

接着我们来绘制九宫格拼图,先设置第一行这三个小图片的外布局,依然是LinearLayout,设置它的id="@+id/pt_line1",就表示第一行。

orientation选择的是水平方向,因为每一行是水平放置的,layout_gravity设置为"center",表示居中,代码如下。

<LinearLayout
        android:id="@+id/pt_line1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_gravity="center">
        
</LinearLayout>

设置第一张图片,选择的控件是ImageButton,顾名思义:图片按钮,正常按钮就规规矩矩的,而图片按钮就很好看,一张图片也可以进行点击,这里设置它的id="@+id/pt_ib_00x00",方便在MainActivity里面调用。

00x00不用我多说了吧,上面解释过了,将九宫格看成3X3的二维数组,那么行列下标就是0行0列,这里每行数和列数都用2位数字表示而已。

设置src="@mipmap/img_xiaoxiong_00x00",就是将我们刚刚准备的图片资源复制到这个mipmap文件夹中进行引用,每个id编号和图片的名称是对应的。

再设置个onClick方法,方法名为"onClick",我们后面会在MainActivity里面进行编写点击事件。第一张图片的代码如下:

<ImageButton
            android:id="@+id/pt_ib_00x00"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/img_xiaoxiong_00x00"
            android:padding="0dp"
            android:onClick="onClick"/>

依次类推,第二张和第三张图片,我只要改下id和src就可以了,所以直接放上第一个小LinearLayout的代码:

<LinearLayout
        android:id="@+id/pt_line1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_gravity="center">
        <ImageButton
            android:id="@+id/pt_ib_00x00"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/img_xiaoxiong_00x00"
            android:padding="0dp"
            android:onClick="onClick"/>
        <ImageButton
            android:id="@+id/pt_ib_00x01"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/img_xiaoxiong_00x01"
            android:padding="0dp"
            android:onClick="onClick"/>
        <ImageButton
            android:id="@+id/pt_ib_00x02"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/img_xiaoxiong_00x02"
            android:padding="0dp"
            android:onClick="onClick"/>
    </LinearLayout>

来看下显示效果:

那第二行和第三行是不是也一样照葫芦画瓢,没错,直接复制第一行的代码,然后修改id和src就行。这里直接给出三个LinearLayout的代码:

<LinearLayout
        android:id="@+id/pt_line1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_gravity="center">
        <ImageButton
            android:id="@+id/pt_ib_00x00"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/img_xiaoxiong_00x00"
            android:padding="0dp"
            android:onClick="onClick"/>
        <ImageButton
            android:id="@+id/pt_ib_00x01"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/img_xiaoxiong_00x01"
            android:padding="0dp"
            android:onClick="onClick"/>
        <ImageButton
            android:id="@+id/pt_ib_00x02"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/img_xiaoxiong_00x02"
            android:padding="0dp"
            android:onClick="onClick"/>
    </LinearLayout>

    <LinearLayout
        android:id="@+id/pt_line2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_gravity="center">
        <ImageButton
            android:id="@+id/pt_ib_01x00"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/img_xiaoxiong_01x00"
            android:padding="0dp"
            android:onClick="onClick"/>
        <ImageButton
            android:id="@+id/pt_ib_01x01"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/img_xiaoxiong_01x01"
            android:padding="0dp"
            android:onClick="onClick"/>
        <ImageButton
            android:id="@+id/pt_ib_01x02"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/img_xiaoxiong_01x02"
            android:padding="0dp"
            android:onClick="onClick"/>
    </LinearLayout>

    <LinearLayout
        android:id="@+id/pt_line3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_gravity="center">
        <ImageButton
            android:id="@+id/pt_ib_02x00"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/img_xiaoxiong_02x00"
            android:padding="0dp"
            android:onClick="onClick"/>
        <ImageButton
            android:id="@+id/pt_ib_02x01"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/img_xiaoxiong_02x01"
            android:padding="0dp"
            android:onClick="onClick"/>
        <ImageButton
            android:id="@+id/pt_ib_02x02"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/img_xiaoxiong_02x02"
            android:padding="0dp"
            android:onClick="onClick"
            android:visibility="invisible"/>
    </LinearLayout>

有一点需要注意的,不知道有没有同学发现——第三行的第三张图片,也就是右下角的那张图片,它有个属性,其他的图片都没有:visibility=“invisible”,这是干什么的呢?

这个其实就是设置控件是否可见,默认情况下控件都是可见的(visible),只有设置visibility="invisible"后,这个控件才不显示出来,我们来看下整体效果:

OK,九宫格完成后,下面是一个重新开始的Button。

这个比较简单了,主要设置了onClick=“restart”,这个后面会在MainActivity里面编写重新开始游戏的逻辑,还设置了android:layout_marginTop=“20dp”,这是设置此控件与上面控件边距相隔20dp,为了和九宫格保持一定间距,代码如下:

<Button
        android:id="@+id/pt_btn_restart"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="restart"
        android:layout_gravity="center"
        android:text="重新开始"
        android:layout_marginTop="20dp"/>

显示效果:

最后就是我们的样图了,有了我们上面的经验,这个应该很容易就画出来了,放置图片的控件我们一般使用ImageView,然后设置src="@mipmap/yangtu",就显示了我们的样图,最后为了保持距离美,设置layout_marginTop=“20dp”,代码如下:

    <ImageView
        android:id="@+id/pt_iv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:src="@mipmap/yangtu"
        android:layout_marginTop="20dp"/>

好了,我们来看下效果图:

至此,我们的布局就绘制完成了!

我们来编写下MainActivity的基本框架

可以先来看下什么都没有的MainActivity。里面只有onClick()和restart()两个新的方法,这是在上面布局中设置的方法,onClick是图片按钮的点击事件,restart是重新开始按钮的点击事件,这两个方法的具体实现逻辑会在下面讲到。

public class MainActivity extends AppCompatActivity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		   super.onCreate(savedInstanceState);
		// 设置要显示的视图
		   setContentView(R.layout.activity_main);
		}
	// 图片按钮的点击事件	    
	public void onClick(View view) {
	
	}
	/* 重新开始按钮的点击事件*/
    public void restart(View view) {
    
  	}
}	  	

这里我们要做的是把所有在布局中用到的控件定义好,然后初始化这些控件

先来定义九个图片按钮,命名方法也是00,01这样的横纵坐标,一个重启按钮和一个显示时间的文本框

//  定义九个图片按钮,命名方法也是00,01这样的横纵坐标
    ImageButton ib00,ib01,ib02,ib10,ib11,ib12,ib20,ib21,ib22;
//   一个重启按钮
    Button restartBtn;
//  一个显示时间的文本框
    TextView timeTv;

然后我们在onCreate中定义一个initView()方法,这个方法是用来初始化控件的

//      初始化layout控件的方法
        initView();

然后创建该方法,在该方法里面初始化定义的控件,通过findViewById()进行绑定控件,将声明的变量和layout中对应的控件进行绑定,实现引用的效果,代码如下:

/* 初始化控件:绑定9个图片按钮,1个显示时间的文本框,1个重启按钮*/
    private void initView() {
        ib00 = findViewById(R.id.pt_ib_00x00);
        ib01 = findViewById(R.id.pt_ib_00x01);
        ib02 = findViewById(R.id.pt_ib_00x02);
        ib10 = findViewById(R.id.pt_ib_01x00);
        ib11 = findViewById(R.id.pt_ib_01x01);
        ib12 = findViewById(R.id.pt_ib_01x02);
        ib20 = findViewById(R.id.pt_ib_02x00);
        ib21 = findViewById(R.id.pt_ib_02x01);
        ib22 = findViewById(R.id.pt_ib_02x02);
        timeTv = findViewById(R.id.pt_tv_time);
        restartBtn = findViewById(R.id.pt_btn_restart);
    }

初始化的完整代码,可以作为模板:

public class MainActivity extends AppCompatActivity {
//  定义九个图片按钮,命名方法也是00,01这样的横纵坐标
    ImageButton ib00,ib01,ib02,ib10,ib11,ib12,ib20,ib21,ib22;
//   一个重启按钮
    Button restartBtn;
//  一个显示时间的文本框
    TextView timeTv;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		   super.onCreate(savedInstanceState);
		// 设置要显示的视图
		   setContentView(R.layout.activity_main);
		   initView()10分钟手把手教你用Android手撸一个简易的个人记账App

☀️手把手教你用 C# 下载文件的十八般武艺☀️《❤️记得收藏❤️》

❤️python表白神器手把手教你用代码浪漫追求对象!❤️(附完整源码+讲解)

还不会搭建个人博客?手把手教你用Wordpress搭建只属于你的世界~(肝帝写近万字多图详解,全网最详细,建议收藏! ❤️)

前端手把手教你用TypeScript写一个简单的eslint插件

太棒了 | 手把手教你用Python做一个 “举牌小人” 生成器!