Android五子棋游戏,自定义棋盘,线条,棋子,游戏状态存储

sw

一.棋盘

我们一看就知道,我们必须自定义View,这里我们定义一个GameView来做游戏主类,第一步,先测量,我们这里不难知道,五子棋他的棋盘是一个正方形,所以我们需要去测量

/**

*测量

*

*@paramwidthMeasureSpec

*@paramheightMeasureSpec

*/

@Override

protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){

//获取高宽值

intwidthSize=(widthMeasureSpec);

intwidthMode=(widthMeasureSpec);

inthightSize=(heightMeasureSpec);

inthightMode=(heightMeasureSpec);

//拿到宽和高的最小值,也就是宽

intwidth=(widthSize,heightMeasureSpec);

//根据测量模式细节处理

if(widthMode==){

width=hightSize;

}elseif(hightMode==){

width=widthSize;

}

//设置这样就是一个正方形了

setMeasuredDimension(width,width);

}

这里的逻辑还是十分简单的,我们拿到长和宽去比较一下,设置这个View的长宽Wie最小值,就是一个正方形了,所以我们的layout_是这样写的

?xmlversion="1.0"encoding="utf-8"?

LinearLayoutxmlns:android=""

xmlns:tools=""

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

android:background="@drawable/main_bg"

android:layout_width="match_parent"

android:layout_height="match_parent"/

/LinearLayout

这里我在构造方法中设置了一个半透明的红色背景,是在我们调试的时候可以更加清晰的看清楚GameView的大小,所以,运行的结果

二.线条

这个应该也算是棋盘的一部分吧,就是棋盘上的线条,我们应该怎么去画,首先,我们要去定义一些属性

//线条数量

privatestaticfinalintMAX_LINE=10;

//线条的宽度

privateintmPanelWidth;

//线条的高度

privatefloatmLineHeight;

然后,我们要去确定大小

/**

*测量大小

*

*@paramw

*@paramh

*@paramoldw

*@paramoldh

*/

@Override

protectedvoidonSizeChanged(intw,inth,intoldw,intoldh){

(w,h,oldw,oldh);

//拿到宽

mPanelWidth=w;

//分割

mLineHeight=mPanelWidth*1.0f/MAX_LINE;

}

不要着急,这些都只是一些准备的工作,我们画线条是必须要在onDraw(0方法里的,但是前期我们要准备一只画笔,对吧,所以我们要初始化画笔

/**

*初始化画笔

*/

privatevoidinitPaint(){

//设置颜色

(0x88000000);

//抗锯齿

(true);

//设置防抖动

(true);

//设置Style

();

}

现在我们可以去绘制了,我们在OnDraw(0方法里写一个drawLine方法来专门绘制线条

/**

*绘制棋盘的方法

*

*@paramcanvas

*/

privatevoiddrawLine(Canvascanvas){

//获取高宽

intw=mPanelWidth;

floatlineHeight=mLineHeight;

//遍历,绘制线条

for(inti=0;iMAX_LINE;i++){

//横坐标

intstartX=(int)(lineHeight/2);

intX=(int)(w-lineHeight/2);

//纵坐标

inty=(int)((0.5+i)*lineHeight);

//绘制横

(startX,y,X,y,mPaint);

//绘制纵

(y,startX,y,X,mPaint);

}

}

我们运行一下

好的,这里,注意一下,我在activity_中定义了一个

android:gravity="center"

属性,所以让他居中,同样的,我们在initPaint中加上点代码让我们看的更加直观一点

//设置颜色

();

//设置线条宽度

(3);

同样的,我们把构造法里的设置背景的测试代码注释掉

//测试代码

//setBackgroundColor(0x44ff0000);

这样,我们运行一下

得,我们现在有模有样了

三.棋子

棋子我们事先准备好了两张图片,但是这里我们要考虑他的大小的问题了,我们的思路是让他是行高的四分之三大小,所以先声明

//黑棋子

privateBitmapmBlack;

//白棋子

privateBitmapmWhite;

//比例,棋子的大小是高的四分之三

privatefloatrowSize=3*1.0f/4;

然后我们定义一个方法区初始化Bitmap

/**

*初始化棋子

*/

privatevoidinitBitmap(){

//拿到图片资源

mBlack=(getResources(),_black);

mWhite=(getResources(),_white);

}

拿到资源之后我们就可以设置大小了,我们在onSizeChanged()里面设置

//棋子宽度

intmWhiteWidth=(int)(mLineHeight*rowSize);

//修改棋子大小

mWhite=(mWhite,mWhiteWidth,mWhiteWidth,false);

mBlack=(mBlack,mWhiteWidth,mWhiteWidth,false);

privateListPointmWhiteArray=newArrayList();

privateListPointmBlackArray=newArrayList();

//标记,是执黑子还是白子,白棋先手

privatebooleanmIsWhite=true;

这样才和触摸事件相得映彰

/**

*触摸事件

*

*@paramevent

*@return

*/

@Override

publicbooleanonTouchEvent(MotionEventevent){

switch(()){

//按下事件

_UP:

intx=(int)();

inty=(int)();

//封装成一个Point

Pointp=getValidPoint(x,y);

//判断当前这个点是否有棋子了

if((p)||(p)){

returnfalse;

}

//判断如果是白子就存白棋集合,反之则黑棋集合

if(mIsWhite){

(p);

}else{

(p);

}

//刷新

invalidate();

//改变值

mIsWhite=!mIsWhite;

break;

}

returntrue;

}

这样,有几点是要说明一下的,首先我们newPoint的时候为了避免重复绘制我们是实现了一个方法

/**

*不能重复点击

*

*@paramx

*@paramy

*@return

*/

privatePointgetValidPoint(intx,inty){

returnnewPoint((int)(x/mLineHeight),(int)(y/mLineHeight));

}

/**

*绘制棋子的方法

*

*@paramcanvas

*/

privatevoiddrawPieces(Canvascanvas){

for(inti=0;();i++){

//获取白棋子的坐标

PointwhitePoint=(i);

(mBlack,(+(1-rowSize)/2)*mLineHeight,(+(1-rowSize)/2)*mLineHeight,null);

}

for(inti=0;();i++){

//获取黑棋子的坐标

PointblackPoint=(i);

(mWhite,(+(1-rowSize)/2)*mLineHeight,(+(1-rowSize)/2)*mLineHeight,null);

}

}

OK,我们实际运行一下

四.游戏逻辑

现在什么都有了,基本上都可用玩了,但是还少了重要的一点就是游戏结束,你到了五颗也需要判断是否胜利呀,对吧,我们写一个方法,在每次绘制完成之后就去判断是否有赢家

/**

*判断是否胜利

*/

privatevoidcheckWin(){

//判断白棋是否有五个相同的棋子相连

booleanmWhiteWin=checkFiveLine(mWhiteArray);

//判断黑棋是否有五个相同的棋子相连

booleanmBlackWin=checkFiveLine(mBlackArray);

//只要有一个胜利,游戏就结束

if(mWhiteWin||mBlackWin){

mIsGameOver=true;

mIsWhiteWin=mWhiteWin;

(getContext(),mIsWhiteWin?"白棋胜利":"黑棋胜利",_SHORT).show();

}

}

好的,我们重点逻辑就在checkFiveLine这个方法上了,这里,我们所知道的胜利有四种情况

我们先定义一个常量

//胜利棋子数量

privatestaticfinalintMAX_COUNT_IN_LINE=5;

OK,接下来我们可以实现以下胜利的逻辑了

/**

*//判断棋子是否有五个相同的棋子相连

*

*@parampoints

*@return

*/

privatebooleancheckFiveLine(ListPointpoints){

//遍历棋子

for(Pointp:points){

//拿到棋盘上的位置

intx=;

inty=;

/**

*四种情况胜利,横,竖,左斜,右斜

*/

//横

booleanwin=checkHorizontal(x,y,points);

if(win)returntrue;

//竖

win=checkVertical(x,y,points);

if(win)returntrue;

//左斜

win=checkLeft(x,y,points);

if(win)returntrue;

//右斜

win=checkRight(x,y,points);

if(win)returntrue;

}

returnfalse;

}

我们不管哪个方向只要返回true就返回true,然后弹Toast,这里,四个方向的逻辑

-横

/**

*判断横向的棋子

*

*@paramx

*@paramy

*@parampoints

*/

privatebooleancheckHorizontal(intx,inty,ListPointpoints){

//棋子标记,记录是否有五个=1是因为自身是一个

intcount=1;

//左

for(inti=1;iMAX_COUNT_IN_LINE;i++){

//如果有

if((newPoint(x-i,y))){

count++;

}else{

break;

}

}

//有五个就为true

if(count==MAX_COUNT_IN_LINE){

returntrue;

}

//右

for(inti=1;iMAX_COUNT_IN_LINE;i++){

//如果有

if((newPoint(x+i,y))){

count++;

}else{

break;

}

}

//有五个就为true

if(count==MAX_COUNT_IN_LINE){

returntrue;

}

returnfalse;

}

-横

/**

*判断纵向的棋子

*

*@paramx

*@paramy

*@parampoints

*/

privatebooleancheckVertical(intx,inty,ListPointpoints){

//棋子标记,记录是否有五个=1是因为自身是一个

intcount=1;

//上

for(inti=1;iMAX_COUNT_IN_LINE;i++){

//如果有

if((newPoint(x,y-i))){

count++;

}else{

break;

}

}

//有五个就为true

if(count==MAX_COUNT_IN_LINE){

returntrue;

}

//下

for(inti=1;iMAX_COUNT_IN_LINE;i++){

//如果有

if((newPoint(x,y+i))){

count++;

}else{

break;

}

}

//有五个就为true

if(count==MAX_COUNT_IN_LINE){

returntrue;

}

returnfalse;

}

-左斜

/**

*判断左斜向的棋子

*

*@paramx

*@paramy

*@parampoints

*/

privatebooleancheckLeft(intx,inty,ListPointpoints){

//棋子标记,记录是否有五个=1是因为自身是一个

intcount=1;

for(inti=1;iMAX_COUNT_IN_LINE;i++){

//如果有

if((newPoint(x-i,y+i))){

count++;

}else{

break;

}

}

//有五个就为true

if(count==MAX_COUNT_IN_LINE){

returntrue;

}

for(inti=1;iMAX_COUNT_IN_LINE;i++){

//如果有

if((newPoint(x+i,y-i))){

count++;

}else{

break;

}

}

//有五个就为true

if(count==MAX_COUNT_IN_LINE){

returntrue;

}

returnfalse;

}

-右斜

/**

*判断右斜向的棋子

*

*@paramx

*@paramy

*@parampoints

*/

privatebooleancheckRight(intx,inty,ListPointpoints){

//棋子标记,记录是否有五个=1是因为自身是一个

intcount=1;

for(inti=1;iMAX_COUNT_IN_LINE;i++){

//如果有

if((newPoint(x-i,y-i))){

count++;

}else{

break;

}

}

//有五个就为true

if(count==MAX_COUNT_IN_LINE){

returntrue;

}

for(inti=1;iMAX_COUNT_IN_LINE;i++){

//如果有

if((newPoint(x+i,y+i))){

count++;

}else{

break;

}

}

//有五个就为true

if(count==MAX_COUNT_IN_LINE){

returntrue;

}

returnfalse;

}

这样,我们运行一下

嘿嘿,好玩吧!

五.游戏状态存储

这个就是当我们游戏挂后台之后,再回来游戏就没了,我们应该存储他的状态,让他每一次进入的时候要是上一句没有下完接着下,那我们该怎么去实现呢?和Activity一样,我们View也有存储状态的方法

/**

*存储状态

*

*@return

*/

@Override

protectedParcelableonSaveInstanceState(){

Bundlebundle=newBundle();

(INSTANCE,());

(INSTANCE_GAMEOVER,mIsGameOver);

(INSTANCE_WHITE_ARRAY,mWhiteArray);

(INSTANCE_BLACK_ARRAY,mBlackArray);

returnbundle;

}

/**

*重新运行

*

*@paramstate

*/

@Override

protectedvoidonRestoreInstanceState(Parcelablestate){

//取值

if(stateinstanceofBundle){

Bundlebundle=(Bundle)state;

mIsGameOver=(INSTANCE_GAMEOVER);

mWhiteArray=(INSTANCE_WHITE_ARRAY);

mBlackArray=(INSTANCE_BLACK_ARRAY);

//调用

((INSTANCE));

return;

}

(state);

}

这样就可以了,但是,有一点要知道,不要忘记在布局文件上给控件加上ID,不然状态不会存储哦

android:id="@+id/mGameView"

android:layout_width="match_parent"

android:layout_height="match_parent"/

六.再来一局

既然我们的游戏逻辑差不多了,那我们应该考虑一下当你胜利的时候,你是不是应该再来一局,所以我们还要实现这个逻辑,这个很简单

/**

*再来一局

*/

publicvoidRestartGame(){

();

();

mIsGameOver=false;

mIsWhiteWin=false;

invalidate();

}

这样,我们就可以直接调用了,我们来看看MainActivity

;

;

;

;

;

/**

*五子棋游戏

*/

publicclassMainActivityextsAppCompatActivity{

//重来按钮

privateFloatingActionButtonfab;

//游戏

privateGameViewgame;

@Override

protectedvoidonCreate(BundlesavedInstanceState){

(savedInstanceState);

setContentView(_main);

game=(GameView)findViewById();

fab=(FloatingActionButton)findViewById();

((){

@Override

publicvoidonClick(Viewv){

();

}

});

}

}

OK,我们最终运行一下

OK,到这里,就算开发完成了Demo下载::555974449欢迎你加入!
文章版权声明:除非注明,否则均为虚境探索者原创文章,转载或复制请以超链接形式并注明出处。

上一个 回合制RPG游戏推荐 不容错过的经典大作

下一个 两只企鹅在游戏里秀恩爱的下场是什么?