拼图小游戏"ST--拼图“开发篇之主要功能实现(一)

来源:互联网 发布:ubuntu 漏洞提权 编辑:程序博客网 时间:2024/05/22 10:47

距离上次发博客好久了,主要是最近太忙,一直再忙着学习各种高级的控件知识以及找工作之类的,所以十分抱歉,刚好抽今天周末,把后面的补上。废话不多说,咱们开始进入正题。


前面两个帖子吧登陆界面和开始界面介绍完了,现在开始写咱们的主要功能实现代码,因为我所用的思路在“简单”,“一般”,“困难”三个不同关卡都差不多,只是其中的参数发生了一些改变,所以这里直接拿”简单“关卡来做介绍


首先呢,我想获取一个效果,就是界面上面的ActionBar是透明的,注意,这里并不是说用的是NoActionBar,而是将ActionBar的背景换成透明的

/** * Actionbar设置 */private void initActionBar() {// TODO Auto-generated method stub// 获取ActionBaractionBar = getActionBar();Resources r = getResources();// 将ActionBar的背景更换Drawable myDrawable = r.getDrawable(R.drawable.actionbar);actionBar.setBackgroundDrawable(myDrawable);// 设置主键按钮能否被点击actionBar.setHomeButtonEnabled(true);// 返回的图标是否显示actionBar.setDisplayHomeAsUpEnabled(true);}

其中的actionbar是一张透明的图片,所以说,会使用简单的PS来作图对于变成学习还是很有用到的

当然,仅仅这样还是不行的,还需要在添加布局文件之前添上这样一行代码,即:

// 将ActionBar悬浮在布局之上<span style="white-space:pre"></span>getWindow().requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY);<span style="white-space:pre"></span>setContentView(R.layout.activity_easy);<span style="white-space:pre"></span>initActionBar();
文中也注释到了,
getWindow().requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY);

这句话的作用是将ActionBar悬浮在布局之上

接下来就是添加整体布局了,对于游戏的界面,我使用的线性布局,将布局先简单的画出来,然后再去搭UI,虽然可能步骤觉得繁琐但是在搭UI的时候,会发现有了一个简单的草图,UI搭起来很方便


<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/ll"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="@drawable/background13"    android:orientation="vertical" >    <LinearLayout        android:layout_width="match_parent"        android:layout_height="48dp"        android:gravity="bottom" >        <ImageView            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:src="@drawable/partition" />    </LinearLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="20dp"        android:orientation="horizontal" >        <LinearLayout            android:layout_width="0dp"            android:layout_height="match_parent"            android:layout_weight="1"            android:gravity="center_vertical"            android:orientation="horizontal" >            <TextView                android:id="@+id/easy_tv1"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_marginLeft="10dp" />        </LinearLayout>        <LinearLayout            android:layout_width="0dp"            android:layout_height="match_parent"            android:layout_weight="1"            android:gravity="center_vertical|right"            android:orientation="horizontal" >            <TextView                android:id="@+id/easy_tv2"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_marginRight="10dp"                android:text="@string/hello" />        </LinearLayout>    </LinearLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_marginLeft="15sp"        android:layout_marginRight="15dp"        android:layout_marginTop="0dp"        android:layout_weight="8"        android:orientation="horizontal" >        <LinearLayout            android:layout_width="0dp"            android:layout_height="match_parent"            android:layout_weight="1"            android:orientation="vertical" >            <LinearLayout                android:layout_width="match_parent"                android:layout_height="0dp"                android:layout_weight="1"                android:orientation="horizontal" >                <ImageView                    android:id="@+id/easy_1"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:layout_margin="2dp"                    android:scaleType="fitXY"                    android:src="@drawable/img1" />            </LinearLayout>            <LinearLayout                android:layout_width="match_parent"                android:layout_height="0dp"                android:layout_weight="1"                android:orientation="horizontal" >                <ImageView                    android:id="@+id/easy_4"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:layout_margin="2dp"                    android:scaleType="fitXY"                    android:src="@drawable/img4" />            </LinearLayout>            <LinearLayout                android:layout_width="match_parent"                android:layout_height="0dp"                android:layout_weight="1"                android:orientation="horizontal" >                <ImageView                    android:id="@+id/easy_7"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:layout_margin="2dp"                    android:scaleType="fitXY"                    android:src="@drawable/img7" />            </LinearLayout>        </LinearLayout>        <LinearLayout            android:layout_width="0dp"            android:layout_height="match_parent"            android:layout_weight="1"            android:orientation="vertical" >            <LinearLayout                android:layout_width="match_parent"                android:layout_height="0dp"                android:layout_weight="1"                android:orientation="horizontal" >                <ImageView                    android:id="@+id/easy_2"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:layout_margin="2dp"                    android:scaleType="fitXY"                    android:src="@drawable/img2" />            </LinearLayout>            <LinearLayout                android:layout_width="match_parent"                android:layout_height="0dp"                android:layout_weight="1"                android:orientation="horizontal" >                <ImageView                    android:id="@+id/easy_5"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:layout_margin="2dp"                    android:scaleType="fitXY"                    android:src="@drawable/img5" />            </LinearLayout>            <LinearLayout                android:layout_width="match_parent"                android:layout_height="0dp"                android:layout_weight="1"                android:orientation="horizontal" >                <ImageView                    android:id="@+id/easy_8"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:layout_margin="2dp"                    android:scaleType="fitXY"                    android:src="@drawable/img8" />            </LinearLayout>        </LinearLayout>        <LinearLayout            android:layout_width="0dp"            android:layout_height="match_parent"            android:layout_weight="1"            android:orientation="vertical" >            <LinearLayout                android:layout_width="match_parent"                android:layout_height="0dp"                android:layout_weight="1"                android:orientation="horizontal" >                <ImageView                    android:id="@+id/easy_3"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:layout_margin="2dp"                    android:scaleType="fitXY"                    android:src="@drawable/img3" />            </LinearLayout>            <LinearLayout                android:layout_width="match_parent"                android:layout_height="0dp"                android:layout_weight="1"                android:orientation="horizontal" >                <ImageView                    android:id="@+id/easy_6"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:layout_margin="2dp"                    android:scaleType="fitXY"                    android:src="@drawable/img6" />            </LinearLayout>            <LinearLayout                android:layout_width="match_parent"                android:layout_height="0dp"                android:layout_weight="1"                android:orientation="horizontal" >                <ImageView                    android:id="@+id/easy_9"                    android:layout_width="wrap_content"                    android:layout_height="wrap_content"                    android:layout_margin="2dp"                    android:scaleType="fitXY"                    android:src="@drawable/img9" />            </LinearLayout>        </LinearLayout>    </LinearLayout>    <LinearLayout        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_weight="2"        android:gravity="center" >        <Button            android:id="@+id/easy_bt1"            android:layout_width="200dp"            android:layout_height="wrap_content"             android:background="@drawable/select"            android:gravity="center"            android:onClick="onclick"            android:text="重新开始" />    </LinearLayout></LinearLayout>






搭出来的效果就是这样

其中的每一个ImageView都是一张小图,我是把一张完整的大图切出来的,当然,这是一个大工程,不过如果你会使用Ps,使用里面的批量切图,会节省很多精力


布局搭好之后,就可以获取控件了


/** * 通过findViewById找到控件位置 *  */public void findId() {action_showimage = (ImageView) findViewById(R.id.action_showimage);ll = (LinearLayout) findViewById(R.id.ll);tv1 = (TextView) findViewById(R.id.easy_tv1);tv2 = (TextView) findViewById(R.id.easy_tv2);iv_group = new ImageView[3][3];iv_group[0][0] = (ImageView) findViewById(R.id.easy_1);iv_group[0][1] = (ImageView) findViewById(R.id.easy_2);iv_group[0][2] = (ImageView) findViewById(R.id.easy_3);iv_group[1][0] = (ImageView) findViewById(R.id.easy_4);iv_group[1][1] = (ImageView) findViewById(R.id.easy_5);iv_group[1][2] = (ImageView) findViewById(R.id.easy_6);iv_group[2][0] = (ImageView) findViewById(R.id.easy_7);iv_group[2][1] = (ImageView) findViewById(R.id.easy_8);iv_group[2][2] = (ImageView) findViewById(R.id.easy_9);}

然后就可以把图片添加到布局上了


<span style="font-size:18px;">/** *  * 将图片添到布局 */public void initGame() {for (int i = 0; i < 3; i++) {for (int j = 0; j < 3; j++) {if (j + i == 4) {iv_group[i][j].setImageResource(number[8]);} else {iv_group[i][j].setImageResource(number[i * 3 + j]);}}}}</span>
接下来就可以初始化界面了,这里尤其有一点要特别注意,就是做拼图的时候,会涉及一个很经典的数学逻辑问题,需要在初始化的时候做判断,不然的话,你的程序完成之后,总会有百分之五十的概率是最后两张图片无法完成,这就是经典的15puzzle算法问题。

这里会涉及几个概念:

1,行数

2,空白控件位于从底部往上数第几个控件

3,倒置数之和


首先,第一个行数就不用解释了吧,像我们的这个简单关卡是3*3的模式,所以行数就是3

第二个空白控件,值得就是像我们3*3的模式中,游戏中,只会显示出来8张图片,有一个空白的是用来移动的,这就是那个空白控件

第三个是倒置数,我们举个例子说明一下,我们是3*3的游戏模式,会出现8张图片,正确排列的时候是

012

345

67

这时它们的顺序就是0,1,2,3,4,5,6,7

但是我们初始化的时候肯定会把顺序打乱,这个可以是随机的那么它的顺序可能是这样的

461

270

35

那么这是它们的顺序就是4,6,1,2,7,0,3,5

那么他们的倒置数就是:4,5,1,1,3,

这里的倒置数就是指一个数组,先拿第一个数跟它后面的数比较,有A个比这个数小的数,那么这组数的第一个倒置数就是A,接着拿第二个数跟第二个数后面的数比较下去,依次下去,如果一个数后面的数都比这个数大,则记为0


相信这样解释大家都明白倒置数是什么了吧,至于倒置数之和,指的就是这些倒置数相加的和


接着咱们就需要来了解这个判断规则了:

1,当行数是偶数时,无论怎样,拼图最后都完成,不会出现最后两张图片异位的现象(这个是我之前找到博友的一篇帖子上提到的,之前并没有怎么验证,但是,当我仔细验证的时候,发现就算行数是偶数的时候,依旧会出现图片异位现象,所以,这句应该是不正确的,也希望广大博友们都试试,大家一起讨论出结果)

2,当行数是奇数时:

a,当空白控件距离底部的距离有奇数个控件时,倒置数之和为奇数,不会出现最后两张图片异位的现象

b,当空白控件距离底部的距离有偶数个控件时,倒置数之和为偶数,不会出现最后两张图片异位的现象

这点可能和我之前的一篇专门讲图片异位问题的博客描述有所不同,是因为之前并没有仔细的去验证,所以并没有发现问题所在,这里跟大家说声抱歉

咱们还是拿例子来说明一下,3*3和5*5肯定有百分之五十的概率出现图片异位的现象,而且4*4也可能出现这种情况,所以我们就需要判断了,因为我们指定的空白控件在出现的时候是出现在最右下角位置,那么空白控件距离底部的距离为0,则空白控件距离底部的距离有偶数个控件,我们只需判定导致数之和是否为偶数即可


代码如下

/** * 初始化图片 */public void initView() {// 获取图片for (int i = 0; i < number.length; i++) {number[i] = gameover[i];}// 将图片随机化for (int i = 0; i < number.length - 4; i++) {int temp = number[i];int index = (int) (Math.random() * (number.length - 5));number[i] = number[index];number[index] = temp;}// 将图片添加到布局initGame();// 设置步数socer = 0;tv2.setText("当前移动了 " + String.valueOf(socer) + " 步");// 获取随机化图片之后图片的顺序getlist();// 判断生成是否有解if (canSolve(data)) {return;} else {initView();}}/** *  * 将图片添到布局 */public void initGame() {for (int i = 0; i < 3; i++) {for (int j = 0; j < 3; j++) {if (j + i == 4) {iv_group[i][j].setImageResource(number[8]);} else {iv_group[i][j].setImageResource(number[i * 3 + j]);}}}}/** * 获取data *  */public void getlist() {data = new ArrayList<Integer>();for (int i = 0; i < number.length - 4; i++) {for (int j = 0; j < number.length - 4; j++) {if (number[i] == gameover[j]) {data.add(j);}}}System.out.println("============" + data.toString());}/** * 该数据是否有解 因为是奇数,而且设置的空白格的初始位置是最下面一行, 所以只需要判断倒置数 getInversions(data)是否为偶数 *  * @param data * @return 该数据是否有解 */public boolean canSolve(List<Integer> data) {// 可行性原则return getInversions(data) % 2 == 0;}/** * 计算倒置和算法 *  * @param data * @return 该序列的倒置和 倒置数:每个数与后面的数比较,看有几个比该数小的数,有一个便加一,以此类推 *  */public static int getInversions(List<Integer> data) {int inversions = 0;int inversionCount;for (int i = 0; i < data.size(); i++) {inversionCount = 0;for (int j = i + 1; j < data.size(); j++) {int index = data.get(i);if (data.get(j) < index) {inversionCount++;}}inversions += inversionCount;inversionCount = 0;}System.out.println("******" + data.toString() + inversions);return inversions;}


这样在初始化的时候,会进行判断,如果倒置数是偶数,怎会赋值成功,如果倒置数不是偶数,那么会重新调用initView(),重新生成初始化的排列,然后继续判断,直到倒置数之和为偶数




0 0
原创粉丝点击