Android九宫格游戏

Android九宫格游戏

这个文档是我根据书本中的知识,然后写的一个总结,为什么要写这个呢?

主要是因为我的那个项目已经很长时间了,关于他的一些东西我也已经忘记了差不多了。所以有必要来重新整理一下的!好了。当然在开始这篇文章之前我对android的知识也已经了解了一点。

好了我们开始吧!当然我刚刚把这些初步功能完成了!

那么我们接下来看看我们该从何来完善这些,并适当添加一些好的布局。

首先我们要的是一个初始的界面的activity这个activity是我们的mainactivity,他使用了我一个main的布局。下面我们给出代码:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:background="@color/background" android:orientation="horizontal"

    android:layout_width="fill_parent" android:layout_height="fill_parent"

    android:padding="30dip">

    <LinearLayout android:orientation="vertical"

       android:layout_width="fill_parent" android:layout_height="wrap_content"

       android:layout_gravity="center">

       <!-- <TextView android:layout_width="fill_parent" android:layout_height="wrap_content"

           android:text="@string/hello" /> -->

 

       <TextView android:id="@+id/text_Id" android:layout_width="wrap_content"

           android:layout_height="wrap_content" android:layout_gravity="center"

           android:layout_marginBottom="25dip" android:textSize="24.5px"

           android:text="@string/hello" />

       <TableLayout android:layout_width="wrap_content"

           android:layout_height="wrap_content" android:stretchColumns="*"

           android:layout_gravity="center">

           <TableRow>

              <Button android:id="@+id/button_Id1" android:layout_width="fill_parent"

                  android:layout_height="wrap_content" android:text="@string/b1label" />

              <Button android:id="@+id/button_Id2" android:layout_width="fill_parent"

                  android:layout_height="wrap_content" android:text="@string/b1labe2" />

           </TableRow>

           <TableRow>

              <Button android:id="@+id/button_Id3" android:layout_width="fill_parent"

                  android:layout_height="wrap_content" android:text="@string/b1labe3" />

              <Button android:id="@+id/button_Id4" android:layout_width="fill_parent"

                  android:layout_height="wrap_content" android:text="@string/b1labe4" />

           </TableRow>

       </TableLayout>

    </LinearLayout>

</LinearLayout>

 

 

android:layout_marginBottom="25dip" android:textSize="24.5px"上面的代码中第一个标签是说明这个所属的控件与下面的一个控件的间距。第二个是指定文字大小。上面还有一个table的应用。

图1.主界面

这个开始的界面完成了,那们下面我们就是来确定这每个按键的响应的事件了。好的,我们先来简单的,首先是about这个按钮。选中这个按钮时,我们跳转到另一个activity这个只是用来显示一些最基本的信息。我们把它放在了About.java中,这个activity其实很简单只是用到了一个布局文件。

<?xml version="1.0" encoding="utf-8"?>

<ScrollView

  xmlns:android="http://schemas.android.com/apk/res/android"

  android:layout_width="fill_parent"

  android:layout_height="fill_parent"

  android:padding="10dip">

  <TextView

  android:layout_width="wrap_content"

  android:layout_height="wrap_content"

  android:text="@string/about"></TextView>

</ScrollView>

 

图2.about界面

 

当然为达到这样的效果,我们还要求在配置文件中配置activity时如下的代码:

<activity android:name=".About" android:label="about"

           android:theme="@android:style/Theme.Dialog"></activity>

在配置完成这个之后,我们在显示这个activity时就会自动把他变成我们想到的那种样子。

 

之后我们就是最后一个叫做退出的按钮了。这个简单,我们只要调用一个finish方法就可以完成。

最重要的就是,开始新游戏的那个方法,那么下面我们来重点实现这个方法。

点击他,我们调转到的首先不是一个警告框,来帮用户选择难度。那们我们就这个警告框,我们该如何实现呢?下面来介绍。我们用不用的是一个内部类。

new AlertDialog.Builder(this).setTitle(R.string.arrayname).setItems(R.array.diffcult, new DialogInterface.OnClickListener() {

             

              publicvoid onClick(DialogInterface dialog, int which) {

                  Log.d("tag", "click"+which);

                  Intent intent=new Intent(MainActivity.this, Game.class);

                  intent.putExtra("DIFFCULT", which);

                  startActivity(intent);                

              }

           }).show();

<string name="settings_label">setting...</string>

    <string name="settings_shortcut">s</string>

    <string name="easy">easy</string>

    <string name="normal">normal</string>

    <string name="hard">hard</string>

    <string name="arrayname">Diffcult</string>

 

<?xml version="1.0" encoding="utf-8"?>

<resources>

<array name="diffcult">

<item>@string/easy</item>

<item>@string/normal</item>

<item>@string/hard</item>

</array>

</resources>

 

我们用上面的代码,我们就可以实现了,很简单,我们可以理解,在android中有一个alertDialog的类中的一个内部类,使用这个类的一些方法,我们为这个设置标题,和内容,然后,我们再为他实现响应事件。这时我们会传入你按的那个itemid值。我们根据这个值,可以进一步的操作。当然在这里我们还有一个menu的设置。我们来看一下,这里的menu是如何实现的,与上一次的我们的那个mp3的项目有什么区别?

在这里他主要重载实现了两个方法:

//这里也是一个重载的方法来显示用户按下手机中自带的菜单钮时所有的视图,将本menu传入

    @Override

    publicboolean onCreateOptionsMenu(Menu menu) {

       //得到本menu的设置类

       MenuInflater inflater = getMenuInflater();

       //设置menu

       inflater.inflate(R.menu.menu, menu);

       returntrue;

    }

<?xml version="1.0" encoding="utf-8"?>

<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:id="@+id/settings" android:title="@string/settings_label"

        android:alphabeticShortcut="@string/settings_shortcut" />

       <!--  <item android:title="ettings_label"></item>-->

</menu>

 

//这里是menu时的item,其中每个Item都有各自的视图,我们可以根据menu中选择的来显示

    @Override

    publicboolean onMenuItemSelected(int featureId, MenuItem item) {

       switch (item.getItemId()) {

       case R.id.settings:

           //这里用到了另一个activity来显示item的具体视图,写到这里我们想到,

           //为什么menu的那个视图不用activity当然原则上是可以的,但这可能已经被android

           //所内置了,因为这个钮在机子上已经是有的了,如果每个用户都要为这个按钮确定

           //外观,那么就会出现了很烦,且意义不大,所以只提供了item的显示方法,而且

           //也是根据activtiy来实现的,见下

           startActivity(new Intent(this, Prefs.class));

           returntrue;

       default:

           returnfalse;

       }

 

    }

<?xml version="1.0" encoding="utf-8"?>

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

    <CheckBoxPreference android:key="music"

       android:title="music_title" android:summary="music_summary"

       android:defaultValue="true" />

    <CheckBoxPreference android:key="hints"

       android:title="hints_title" android:summary="hints_summary"

       android:defaultValue="true" />

</PreferenceScreen>

 

那们我们再看下,我们的mp3中的那个项目是如何实现的,有什么异同点:

//在用户按下菜单按钮的时候会自动调用这个方法来创建我们需要的按钮

    @Override

    publicboolean onCreateOptionsMenu(Menu menu) {

       // TODO Auto-generated method stub

       menu.add(0, UPDATE, 1, R.string.mp3list_updata);

       menu.add(0, ABOUT, 2, R.string.mp3list_about);

           }

//

    //在用户点击了你的menu中的item时会触发这个函数

    @Override

    publicboolean onOptionsItemSelected(MenuItem item) {

       // TODO Auto-generated method stub

//     System.out.println("item"+item.getItemId());

       if(item.getItemId()==UPDATE){

           updateList();

       }elseif(item.getItemId()==ABOUT){

           //用户点击了关于按钮

       }

       returnsuper.onOptionsItemSelected(item);

    }

首先,他们实现的两个方法就不同,首先onCreateOptionsMenu()这个方法是都需要的,只有他的存在,我们按那个menu才会有反应。在第一个中,我们用到了布局文件,而第二种则不需要。这里面的区别是什么呢?第一个,在我们按下meun中的某一个时,我们会继续选择的也就是会到另一个界面,而第二个,我们就直接操作了。所以第一个,我们实现的是onMenuItemSelected,因为这里面才会真正操作。而第二个是onOptionsItemSelected,因为每一个就会是一个操作了。第一个,我们的那个界面是用activity实现的。而第一种较为复杂,第二种简单点,都不会用到布局文件,当然第一种会更加的绚丽点了。

 

 

好了讲完了这些,最后重点的,我们就明天开始再讲吧。

好了,上次说好明天来讲的,可一晃也就后天了,今天开始把我们主要的一个功能,就是九宫格的主要功能来说明一下。

因为我们在开始主界面的游戏的时候,我们设置了一个游戏的选项。也就是游戏的难度,我们在上文中也已经说过了。好了,现在主要的就是游戏了,关于游戏,我们就涉及到了另一个功能,也就是在手机界面上画图象的方法,首先我们来看一下,我们开始游戏时,会跳转到的游戏界面。

图2.游戏界面

 

这也就是我们的界面。当然在难度级别的选择的时候,我们为这个activity的intend对象传入了一个叫做DIFFCULT的对象,这个对象的级别是我们选择的item的id号。这样,我们可以利用这个传入的id来确定我们的游戏的难度。

privatefinal String easyPuzzle =

       "360000000004230800000004200" +

       "070460003820000014500013020" +

       "001900000007048300000000045" ;

       privatefinal String mediumPuzzle =

       "650000070000506000014000005" +

       "007009000002314700000700800" +

       "500000630000201000030000097" ;

       privatefinal String hardPuzzle =

       "009000000080605020501078000" +

       "000000700706040102004000000" +

       "000720903090301080000000600" ;

       public  int[] puzzle;

这是我们在game.clas中的一些字符的设置,首先就是难度的一些字符。和一个数组。

publicvoid onCreate(Bundle savedInstanceState)

    {

   

       super.onCreate(savedInstanceState);

       PuzzleView pv=new PuzzleView(this);

       setContentView(pv);

       puzzle=getPuzzle(getIntent().getIntExtra("DIFFCULT", 0));

    }

这是我们这个activityonCreate对象,跟我们以前有不同的一个重要特点是什么在?是我们在setContentView()这个方法之中传入的不现是我们的R资源中的一些布局的id号了。而是我们设置的一个PuzzleView当然这个对象也肯定是一个我view,那我们才能设置,而且,我们必须自己来画。好了,我们先来看看我们应该怎么画吧。

在代码中我们已经做了比较详细的说明。在这里我介绍一些最基本的用法,对于我们想展示自己画的界面时,我们需要继承一个view然后在他的onDraw中自己写上自己画的内容。onSizeChange中我们对一些在格局改变时需要改变的一些量。而在onKeyPrease方法中,我们每次的执行都会调用onDraw这个方法。在这里我发现了一个问题,那就是在我自己改变这个界面中的数字时,我发现只有我移动过之后,我的数字才会实现。也就是说我们虽然在那个数字数组之中增加了我们写的数字,但是这个onDraw方法并没有调用。我们要显示调用。但是我们在我们的数组添加代码之中显示调用之后还是没有发现有什么改变!这是为什么?留待以后解决吧。我们在试验之后终于发现了这个原因,在我们想重新画界面的时候,我们是不能显示调用这个onDraw的方法这个方法是android系统自己会为我们调用的,而我们想在程序运行期间主动的改变界面,android系统为我们提供了一个方法,他可以把我们想要改变的界面范围找出来,使用一个叫做invalidate()的方法,传入一个叫做dirtyrect我们就可以重新调用到onDraw这个方法了:

Mark the the area defined by dirty as needing to be drawn. If the view is visible, onDraw(Canvas) will be called at some point in the future. This must be called from a UI thread. To call from a non-UI thread, call postInvalidate(). WARNING: This method is destructive to dirty.

上面是我们这个invalidate的英文注释,在其中我们可以很清楚的看到,他说明了,只要我们想改变的这个界面范围中是可见的。那我们onDraw方法将会called.

好了,我们的游戏的基本逻辑功能已经完成了。在这其中我们遇到了一点问题特别是一些下标的问题,但是,根据一些方法,我们也是能正确找得到这些下标,从而来进行来判断。在下标的选择中,横坐标是很容易,但纵坐标是需要累加的,而那9个大的九宫格,就比较复杂了,我采用的是什么方法呢?我们用的是根据你要填的那个数,来确定你所在的那个大的九宫格。然后根据一些公式。得到第一个数的下标(在大的九宫格)。然后最后的尾部的一些处理过程,就是每次在重新载入的时候判断一下是不是全部完成了。为什么这么说呢?很简单,因为在填数字的时候,我们已经严格定义了条件了,所以如果全部填完就必定是按这个规则来完成的。这就说明你成功了。游戏也结束了。还有一些外表的处理。下次再说!

今天准备的说有点高兴吧,因为自己的android的学习想告一段落了吧,那么下来来说说自己上文说过的对于一些外表的重新表现吧。

首先我对于我的这个程序的的图标做了修改了,关于修改很简单只到在我们的配置文件中,对相应的标签android:icon="@drawable/icon2" 做相应的指定就可以了。

然后就是对于上次留下的一个continue按钮的事件的响应。关于这个响应的事件有一个缺点就是我们在已经开始一段游戏的时候,我们想继续开始这个游戏的时候我们发现,我们使用这个按钮是不能回到我们的原来的状态的。在这些操作中,我们有一个点是什么呢?就是我们在实现那个游戏主界面的游戏的时候,那是个activity,然后我们返回之后也就是离开这个界面时,我们能不能把这时已经完成的状态保存下来呢?

然后就是我们游戏的主界面的图片,我们也换过了。我们使用this.setBackgroundDrawable(this.getResources().getDrawable(R.drawable.mbac));这个方法要注意的是在我们使用这个方法的时候,我们在后来的操作过程中,我们不能再进行画界面的一些操作了。因为如果再画我们会覆盖我们的图片。

但我们在完成这个游戏的过程,也遇到了一些问题,什么问题呢?

比如说,我们在游戏之中,在某个小方框中写入了一个数字之后,我们不能够现重新的修改这个数字,这是什么原因呢,仔细考虑之后,我们发现了,我们是在对每一个字符输入之后,我们覆盖了新的字符,然后以这个新的字符来进行判断,那么我们填入的显然就不能重新修改了。所以我们应该始终按照系统给的数字来进行决断。

 

在完成了这个游戏之后了,我们要说的是另一个问题,那是对于系统开始给我们的数字中,我们是没有权利进行修改的。我们可以进行坐标来,判定相应的字符是不是为0,如果是我们才有权利进行修改,如果不是0说明这个坐标的数字是系统已经指定的,我们是没有权利进行修改的。

小结

那最后一个问题就是对于我们能够写入的数字的提示功能,这是出于什么考虑呢?因为这个九宫格的游戏数字很多,如果没有良好的提示功能,我们自己来找数字将会显得很复杂,也是费力,所以如果由系统自动提示用户进行操作,那么就会容易的许多,那么用户也将有更多的时候专注于游戏本身而不是一堆数字了。由于上面的判断操作中我们已经得到了横排,竖排,小九宫格的数字字符串,那么我们只要拼接这些数据,然后进行从123456789这些数据中减去就可以了。关于这些操作我们有些小问题,虽然我现在已经完成了这些功能,但我清楚的知道我对这些的操作效率并不是很高。还有代码的条理性也没有我想像中的清楚。

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值