一切从五子棋开始
2016-06-12 18:31
429 查看
题引:作为一个迫不及待想掌握一门养家糊口技能的大二新人,被一位前辈建议学习Java开发Android,他还说会写五子棋就能找到工作。
写五子棋的要点有两点:棋局展示、胜负判定。
一、棋局展示
忽略交互效果,仅以实现基本功能为目标,展示的方法可通过文本或图片实现。
使用文本展示可通过“o”表示白子,“x”表示黑子,“-”表示空位来进行最简单的展示。用TextView控件及其setText(CharSequence)方法即可实现棋子的更替。
使用图片展示可使交互更直观。最先想到的方法是在底部设置一张棋盘背景,落子后将对应位置的ImageView的显示图片更改为落子贴图。苦于没找到合适的棋盘背景,最后使用三张落子贴图分别代表白子、黑子、无子,在落子后将棋格贴图更改为对应落子贴图即可。
接下来就是如何显示这些贴图了,通过以下代码即可将ImageView控件的图片内容设置为资源文件内的图片。
光显示贴图还远远不够,我们需要将ImageView按棋盘进行定位布局。考虑到棋盘大小的易变性,控件的创建和定位都通过Java代码动态进行。
最后是添加交互事件,可以通过View的setOnClickListener(OnClickListener)方法实现点击事件。
这里需要注意的是,由于多个控件设置点击事件,我们需要在处理点击时识别所点击对象。标识点击对象的方法有很多种:
1、关键字final。
2、用回调view遍历比对控件数组。
3、通过view的setTag(Object)方法标记控件,使用回调view的getTag()方法获取唯一标识。
4、继承OnClickListener类,提供两个int型数据进行初始化的构造器。添加新抽象方法onClick(int,int),原抽象方法onClick(View)通过构造传入的int数据调用新抽象方法。
以下代码通过关键字final实现标识。
二、胜负判定
正在进行的棋局只会因下一次落子导致结束,因此胜负判定在每次落子后根据落子位置进行判定即可。
判定思路为由落子位置向四个方向延伸,任意方向连通总量大于五子则落子方获胜。需要注意的是五子棋还存在和棋的可能性,在获胜判定后需统计落子总量,若棋盘已满则产生和局。以下代码为落点胜负判定。
最后再搭配上棋盘的复位功能,一个Android的简单五子棋程序就完成了。(当然现在还存在一个严重的交互问题,在小屏手机上触控容易点错位置,后来我的解决方案是添加了棋盘的双指缩放和单指挪动,这里就不进行详细描述了)
写五子棋的要点有两点:棋局展示、胜负判定。
一、棋局展示
忽略交互效果,仅以实现基本功能为目标,展示的方法可通过文本或图片实现。
使用文本展示可通过“o”表示白子,“x”表示黑子,“-”表示空位来进行最简单的展示。用TextView控件及其setText(CharSequence)方法即可实现棋子的更替。
使用图片展示可使交互更直观。最先想到的方法是在底部设置一张棋盘背景,落子后将对应位置的ImageView的显示图片更改为落子贴图。苦于没找到合适的棋盘背景,最后使用三张落子贴图分别代表白子、黑子、无子,在落子后将棋格贴图更改为对应落子贴图即可。
接下来就是如何显示这些贴图了,通过以下代码即可将ImageView控件的图片内容设置为资源文件内的图片。
mImageView.setImageResource(R.drawable.mImage);
光显示贴图还远远不够,我们需要将ImageView按棋盘进行定位布局。考虑到棋盘大小的易变性,控件的创建和定位都通过Java代码动态进行。
/** * 初始化布局 * @param count 棋盘行列数 * @return 棋格控件数组 */ private ImageView[][] initView(int count) { RelativeLayout container=new RelativeLayout(this); setContentView(container); ImageView[][] views=new ImageView[count][count]; int pWidth=getResources().getDisplayMetrics().widthPixels,pHeight=getResources().getDisplayMetrics().heightPixels; //获取屏幕宽高 int length=pWidth>pHeight?pHeight/count:pWidth/count; //计算棋格宽高 int left=pWidth>pHeight?(pWidth-pHeight)/2:0; //局中显示水平偏移 int top=pWidth>pHeight?0:(pHeight-pWidth)/2; //局中显示垂直偏移 for(int x=0;x<count;x++) { for(int y=0;y<count;y++) { ImageView iv=new ImageView(this); RelativeLayout.LayoutParams lp=new RelativeLayout.LayoutParams(length, length); lp.setMargins(left+x*length, top+y*length, 0, 0); iv.setLayoutParams(lp); container.addView(iv); views[x][y]=iv; } } return views; }
最后是添加交互事件,可以通过View的setOnClickListener(OnClickListener)方法实现点击事件。
这里需要注意的是,由于多个控件设置点击事件,我们需要在处理点击时识别所点击对象。标识点击对象的方法有很多种:
1、关键字final。
2、用回调view遍历比对控件数组。
3、通过view的setTag(Object)方法标记控件,使用回调view的getTag()方法获取唯一标识。
4、继承OnClickListener类,提供两个int型数据进行初始化的构造器。添加新抽象方法onClick(int,int),原抽象方法onClick(View)通过构造传入的int数据调用新抽象方法。
以下代码通过关键字final实现标识。
private ImageView[][] mViews; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mViews=initView(15); for(int x=0;x<mViews.length;x++) { for(int y=0;y<mViews[0].length;y++) { final int finalX=x; final int finalY=y; mViews[x][y].setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub handleClick(finalX, finalY); } }); } } } private void handleClick(int x, int y) { //这里处理点击逻辑 }
二、胜负判定
正在进行的棋局只会因下一次落子导致结束,因此胜负判定在每次落子后根据落子位置进行判定即可。
判定思路为由落子位置向四个方向延伸,任意方向连通总量大于五子则落子方获胜。需要注意的是五子棋还存在和棋的可能性,在获胜判定后需统计落子总量,若棋盘已满则产生和局。以下代码为落点胜负判定。
private int[][] mArgs; //棋盘数据数组 private int pieceCount; //棋盘已落子量 private int chessSize; //棋盘行列数 /** * 胜负判定 * @param x 落子横坐标 * @param y 落子纵坐标 * @return */ private int win(int x, int y) { if(getItemCount(x,y,0,1)+getItemCount(x,y,0,-1)+1>=5) return 1; //落子方获胜 if(getItemCount(x,y,1,0)+getItemCount(x,y,-1,0)+1>=5) return 1; //落子方获胜 if(getItemCount(x,y,1,1)+getItemCount(x,y,-1,-1)+1>=5) return 1; //落子方获胜 if(getItemCount(x,y,1,-1)+getItemCount(x,y,-1,1)+1>=5) return 1; //落子方获胜 if(pieceCount>=chessSize*chessSize) return -1; //平局 return 0; //未分胜负 } /** * 连通量统计 * @param x 落子横坐标 * @param y 落子纵坐标 * @param i 延伸方向 * @param j 延伸方向 * @return */ private int getItemCount(int x, int y, int i, int j) { int itemCount=0; int mType=mArgs[x][y]; int readX=x+i; int readY=y+j; while(true) { if(readX<0||readX>=chessSize||readY<0||readY>=chessSize) break; if(mType==mArgs[readX][readY]) { itemCount++; readX+=i; readY+=j; } else break; } return itemCount; //返回该方向累计同色棋数 }
最后再搭配上棋盘的复位功能,一个Android的简单五子棋程序就完成了。(当然现在还存在一个严重的交互问题,在小屏手机上触控容易点错位置,后来我的解决方案是添加了棋盘的双指缩放和单指挪动,这里就不进行详细描述了)
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories