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

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


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


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

/**
	 * Actionbar设置
	 */
	private void initActionBar() {
		// TODO Auto-generated method stub
		// 获取ActionBar
		actionBar = 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(),重新生成初始化的排列,然后继续判断,直到倒置数之和为偶数




你可能感兴趣的:(游戏,android,布局,拼图,puzzle)