拼图小游戏"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(),重新生成初始化的排列,然后继续判断,直到倒置数之和为偶数
- 拼图小游戏"ST--拼图“开发篇之主要功能实现(一)
- 拼图小游戏”ST--拼图“开发篇之主要功能的实现(二)
- 拼图小游戏“ST--拼图”开发篇之主要功能的实现(三)
- 拼图小游戏"ST--拼图"开发篇之开始界面的功能实现
- 拼图小游戏“ST--拼图”开发篇之后期功能完善
- 拼图小游戏"ST--拼图"开发篇之开始界面UI布局
- iOS之拼图小游戏
- 拼图小游戏
- 拼图小游戏
- 【Android小游戏】安卓小游戏开发--拼图
- 【Demo】拼图小游戏 winform (一) 简单的拖动拼图
- 平面设计之拼图篇
- java拼图小游戏
- JS数字拼图小游戏
- JavaScript拼图小游戏
- swift 拼图小游戏
- android 美女拼图小游戏
- VS,C#--拼图小游戏
- spring4 test
- birt修改sql
- Learn Python The Hard Way 总结与勘误
- 【Java】CGlib动态代理
- 模仿playnext网站hover后抖动的效果
- 拼图小游戏"ST--拼图“开发篇之主要功能实现(一)
- php实战之使用curl抓取网站数据
- u-boot 分析(转自360doc)
- 多线程锁和反射的再次理解
- iOS关于RunLoop和Timer
- VS项目属性的配置总结
- jQuery源码分析之ajaxPrefilters方法
- hot and cold observable
- jquery表单验证