一切从五子棋开始

题引:作为一个迫不及待想掌握一门养家糊口技能的大二新人,被一位前辈建议学习Java开发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的简单五子棋程序就完成了。(当然现在还存在一个严重的交互问题,在小屏手机上触控容易点错位置,后来我的解决方案是添加了棋盘的双指缩放和单指挪动,这里就不进行详细描述了)


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值