android五子棋棋子资源,Android五子棋游戏源码详解

本文介绍了作者学习鸿洋大牛的五子棋教程后的分享,包括棋盘布局、自定义ChessView视图的详细代码,以及IsChessWin类用于判断胜负的逻辑。重点展示了如何在触屏事件中绘制棋子并检测游戏结束,提供了一次游戏重置的功能。
摘要由CSDN通过智能技术生成

最近看了鸿洋大牛的五子棋教程,受益匪浅,讲的非常好,关于五子棋的游戏原理非常清楚,并且学到了不少知识,在这里感谢鸿洋大神的分享。我觉得我的源码注释写的非常清楚了,希望能给你带来不少的收获。

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

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="@mipmap/bg"

android:paddingTop="80dp"

android:orientation="vertical"

tools:context="com.yaodan.fivechessdemo.MainActivity">

android:id="@+id/custon_chess_main"

android:layout_width="match_parent"

android:layout_height="match_parent" />

android:id="@+id/bt_restart"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center"

android:text="再来一局"/>

自定义View的工具类package com.yaodan.fivechessdemo.view;import android.app.AlertDialog;import android.content.Context;import android.content.DialogInterface;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Point;import android.os.Bundle;import android.os.Parcelable;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import com.yaodan.fivechessdemo.R;import com.yaodan.fivechessdemo.contral.IsChessWin;import java.util.ArrayList;/**

* Created by swk on 2016/12/5.

*/public class ChessView extends View {    private int mPanelWith; //棋盘的宽度(棋盘使方形的)

private float mLineHeigth;  //棋盘每一个空格的高度

private int MAX_LINE = 10;    //棋盘的行数

private Paint mPint = new Paint();    //创建画笔

private Bitmap wPieces;     //白棋

private Bitmap bPieces;     //黑棋

private ArrayList wPoints = new ArrayList<>();   //白棋坐标的集合

private ArrayList bPoints = new ArrayList<>();   //黑棋坐标的集合

private float radioPoeces = 1.0f * 3 / 4;    //棋子与棋格的大小比例

private boolean mIsWitch = true;  //判断是否白子画在棋盘上

private boolean isGameOver = false;  //判读是否游戏结束

private Context mContext;    private IsChessWin isChessWin;  //一个用来处理胜利与否的逻辑

private String TAG = "CHESSVIEW";    public ChessView(Context context) {        super(context);

mContext = context;

init();

}    public ChessView(Context context, AttributeSet attrs) {        super(context, attrs);

mContext = context;

init();

}    public ChessView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);

mContext = context;

init();

}    /**

* 再来一局方法

*/

public void myreStart() {

wPoints.clear();

bPoints.clear();

isGameOver = false;

Log.i(TAG, "myreStart: " + wPoints.size() + ":::" + bPoints.size());

invalidate();

}    /**

* 初始化

*/

public void init() {        //设置画笔的颜色

mPint.setColor(Color.BLACK);        //设置抗锯齿功能(图像边缘相对清晰一点,锯齿痕迹不那么明显)

mPint.setAntiAlias(true);        //设置防抖动功能(使图像更柔和一点)

mPint.setDither(true);        //设置画笔的风格为空心

mPint.setStyle(Paint.Style.STROKE);        //获取棋子的资源文件

wPieces = BitmapFactory.decodeResource(getResources(), R.drawable.stone_w2);

bPieces = BitmapFactory.decodeResource(getResources(), R.drawable.stone_b1);

}    @Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        /**

* 获取view的宽度和mode

* mode分为:

* EXACTLY:EXACTLY是精确尺寸,当我们将控件的layout_width或layout_height指定为具体数值时如andorid:layout_width="50dip",或者为FILL_PARENT是,都是控件大小已经确定的情况,都是精确尺寸。

* AT_MOST:最大尺寸,当控件的layout_width或layout_height指定为WRAP_CONTENT时,控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸只要不超过父控件允许的最大尺寸即可。因此,此时的mode是AT_MOST,size给出了父控件允许的最大尺寸。

* UNSPECIFIED:未指定尺寸,这种情况不多,一般都是父控件是AdapterView,通过measure方法传入的模式

*/

int widthSize = MeasureSpec.getSize(widthMeasureSpec);        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        //由于棋盘是正方形,所以要从长和宽选取最短的

int width = Math.min(widthSize, heightSize);        //如果上方有一个是UNSPECIFIED,相对应的有一个尺寸是0,如果有一个是0,那么width就是0显示不出来

if (widthMode == MeasureSpec.UNSPECIFIED) {

width = heightSize;

} else if (heightMode == MeasureSpec.UNSPECIFIED) {

width = widthSize;

}        //设置实际的长和宽设置上去

setMeasuredDimension(width, width);

}    /**

* 当view的尺寸改变时,会回掉这个方法

*

* @param w

* @param h

* @param oldw

* @param oldh

*/

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);

mPanelWith = w;

mLineHeigth = mPanelWith * 1.0f / MAX_LINE;        int piecesWidth = (int) (mLineHeigth * radioPoeces);        //按照以前存在的位图按照一定的比例构建一个新的位图

wPieces = Bitmap.createScaledBitmap(wPieces, piecesWidth, piecesWidth, true);

bPieces = Bitmap.createScaledBitmap(bPieces, piecesWidth, piecesWidth, true);

}    /**

* 获取坐标的集合

*

* @param event

* @return

*/

@Override

public boolean onTouchEvent(MotionEvent event) {

isGameOver = isChessWin.isGameOverMethod(wPoints, bPoints);        if (isGameOver) {

showDialog();            return false;

}        int action = event.getAction();        if (action == MotionEvent.ACTION_UP) {            int x = (int) event.getX();            int y = (int) event.getY();

Point point = getSimulatePoint(x, y);            //如果黑棋的集合或者白棋的集合包含这个坐标,那么返回false

//contains和eequals比较的不是内存空间的地址,而是x,y值是否一致

if (wPoints.contains(point) || bPoints.contains(point)) {                return false;

}            if (mIsWitch) {

wPoints.add(point);

} else {

bPoints.add(point);

}

mIsWitch = !mIsWitch;            //刷新View

invalidate();            return true;

}        return true;

}    /**

* 根据真实的坐标模拟出绝对值坐标

*

* @param x

* @param y

* @return

*/

public Point getSimulatePoint(int x, int y) {        return new Point((int) (x / mLineHeigth), (int) (y / mLineHeigth));

}    /**

* 显示白棋或者黑棋获胜的提示的对话框

*/

public void showDialog() {

String successText = isChessWin.isWhiteWinFlag() ? "白棋获胜!" : "黑棋获胜!";        new AlertDialog.Builder(mContext)

.setMessage("恭喜" + successText + ",是否再来一局?")

.setCancelable(false)

.setPositiveButton("确定", new DialogInterface.OnClickListener() {                    @Override

public void onClick(DialogInterface dialogInterface, int i) {

myreStart();

}

})

.setNegativeButton("取消", new DialogInterface.OnClickListener() {                    @Override

public void onClick(DialogInterface dialogInterface, int i) {

}

})

.show();

}    @Override

protected void onDraw(Canvas canvas) {        super.onDraw(canvas);

drawBoard(canvas);

drawPieces(canvas);        //下面的实例用来判断是否胜利

isChessWin = new IsChessWin(mContext);

isGameOver = isChessWin.isGameOverMethod(wPoints, bPoints);        //判断是否结束游戏

if(isGameOver){

showDialog();

}

}    /**

* 画棋盘的线

*

* @param canvas

*/

public void drawBoard(Canvas canvas) {        int w = mPanelWith;        float lineHeight = mLineHeigth;        //画十条线

for (int i = 0; i 

int startX = (int) (lineHeight / 2);            //设置终点X横坐标为宽度减去半个lineHeight(棋盘空格宽度)

int endX = (int) (w - lineHeight / 2);            int y = (int) ((0.5 + i) * lineHeight);            //画横线

canvas.drawLine(startX, y, endX, y, mPint);            //画纵线,坐标反过来

canvas.drawLine(y, startX, y, endX, mPint);

}

}    /**

* 画棋子

*/

public void drawPieces(Canvas canvas) {

Log.i(TAG, "drawPieces: " + wPoints.size() + ":::" + bPoints.size());        for (int i = 0; i 

Point point = wPoints.get(i);            //drawBitmap是将图片的右下角为坐标

canvas.drawBitmap(wPieces, ((point.x + (1 - radioPoeces) / 2) * mLineHeigth), (point.y + (1 - radioPoeces) / 2) * mLineHeigth, null);

}        for (int i = 0; i 

Point point = bPoints.get(i);

canvas.drawBitmap(bPieces, ((point.x + (1 - radioPoeces) / 2) * mLineHeigth), (point.y + (1 - radioPoeces) / 2) * mLineHeigth, null);

}

}    private static final String INSTANCE = "instance";    private static final String INSTANCE_GAMEOVER = "instance_gameover";    private static final String INSTANCE_WHITEARRAY = "instance_whitearray";    private static final String INSTANCE_BLACKARRAY = "instance_blackarray";    /**

* 当view因为某种原因(比如系统回收)销毁时,保存状态

*

* @return

*/

@Override

protected Parcelable onSaveInstanceState() {

Bundle bundle = new Bundle();        //保存系统默认状态

bundle.putParcelable(INSTANCE, super.onSaveInstanceState());        //保存是否游戏结束的值

bundle.putBoolean(INSTANCE_GAMEOVER, isGameOver);        //保存白棋的子数

bundle.putParcelableArrayList(INSTANCE_WHITEARRAY, wPoints);        //保存黑棋的子数

bundle.putParcelableArrayList(INSTANCE_BLACKARRAY, bPoints);        return bundle;

}    /**

* 取出保存的值

*

* @param state

*/

@Override

protected void onRestoreInstanceState(Parcelable state) {        if (state instanceof Bundle) {

Bundle bundle = (Bundle) state;

isGameOver = bundle.getBoolean(INSTANCE_GAMEOVER);

wPoints = bundle.getParcelableArrayList(INSTANCE_WHITEARRAY);

bPoints = bundle.getParcelableArrayList(INSTANCE_BLACKARRAY);            super.onRestoreInstanceState(bundle.getParcelable(INSTANCE));            return;

}        super.onRestoreInstanceState(state);

}

}

判断是否胜利的类package com.yaodan.fivechessdemo.contral;import android.content.Context;import android.graphics.Point;import java.util.List;/**

* Created by swk on 2016/12/5.

* 判断是否胜利类

*/public class IsChessWin {    private boolean isGameOver = false;   //判断是否游戏结束

private boolean isWhiteWin;     //判断是否白棋胜

private int MAX_NUMWIN = 5;  //设置5子连在一起胜利

private int CURRENT_NUM = 0;    private Context mContext;    private boolean isRestart=false;    public IsChessWin(Context context) {        super();

mContext = context;

}    /**

* 判断是否胜利

* @param whitePoints

* @param blackPoints

* @return

*/

public boolean isGameOverMethod(List whitePoints, List blackPoints) {        boolean whiteWin = isWhiteWin(whitePoints);        boolean blackWin = isBlackWin(blackPoints);        if (whiteWin || blackWin) {

isGameOver = true;

isWhiteWin = whiteWin;

}        return isGameOver;

}    /**

* 返回是否白棋取胜

* @return

*/

public boolean isWhiteWinFlag(){        return isWhiteWin;

}    /**

* 判断是否白棋取胜

* @param points

* @return

*/

private boolean isWhiteWin(List points) {        if (isFiveConnect(points)) {            return true;

}        return false;

}    /**

* 判断是否黑棋取胜

* @param points

* @return

*/

private boolean isBlackWin(List points) {        if (isFiveConnect(points)) {            return true;

}        return false;

}    /**

* 判断是否五子连珠

* @param points

* @return

*/

private boolean isFiveConnect(List points) {        for (Point p : points) {            int x = p.x;            int y = p.y;            if (isHorizontalFive(x, y, points)) {                return true;

} else if (isVerticalFive(x, y, points)) {                return true;

} else if (isSkewFive(x, y, points)) {                return true;

}

}        return false;

}    /**

* 判断是否横向五子连珠

* @param x

* @param y

* @param points

* @return

*/

private boolean isHorizontalFive(int x, int y, List points) {        //判断横向向右是否练成5子,points里面存的值为int类型,所以可以进行加一或者减一的运算

for (int i = 0; i 

CURRENT_NUM++;

} else {                break;

}

}        if (MAX_NUMWIN == CURRENT_NUM) {            return true;

} else {

CURRENT_NUM = 0;

}        //判断横向向左是否连成5子

for (int i = 0; i 

CURRENT_NUM++;

} else {                break;

}

}        if (MAX_NUMWIN == CURRENT_NUM) {            return true;

} else {

CURRENT_NUM = 0;

}        return false;

}    /**

* 判断是否竖直五子连珠

* @param x

* @param y

* @param points

* @return

*/

private boolean isVerticalFive(int x, int y, List points) {        for (int i = 0; i 

if (points.contains(new Point(x, y + i))) {

CURRENT_NUM++;

} else {                break;

}

}        if (MAX_NUMWIN == CURRENT_NUM) {            return true;

} else {

CURRENT_NUM = 0;

}        //判断向上是否5子连珠

for (int i = 0; i 

CURRENT_NUM++;                if (5 == CURRENT_NUM) {                    return true;

}

} else {

CURRENT_NUM = 0;                break;

}

}        if (MAX_NUMWIN == CURRENT_NUM) {            return true;

} else {

CURRENT_NUM = 0;

}        return false;

}    /**

* 判断斜着是否五子连珠

* @param x

* @param y

* @param points

* @return

*/

private boolean isSkewFive(int x, int y, List points) {        //判断左斜下是否5子连珠

for (int i = 0; i 

CURRENT_NUM++;

} else {                break;

}

}        if (MAX_NUMWIN == CURRENT_NUM) {            return true;

} else {

CURRENT_NUM = 0;

}        //判断左上是否5子连珠

for (int i = 0; i 

CURRENT_NUM++;

} else {                break;

}

}        if (MAX_NUMWIN == CURRENT_NUM) {            return true;

} else {

CURRENT_NUM = 0;

}        //判断右上是否5子连珠

for (int i = 0; i 

CURRENT_NUM++;

} else {                break;

}

}        if (MAX_NUMWIN == CURRENT_NUM) {            return true;

} else {

CURRENT_NUM = 0;

}        //判断右斜上是否5子连珠

for (int i = 0; i 

CURRENT_NUM++;

} else {                break;

}

}        if(MAX_NUMWIN==CURRENT_NUM){            return true;

}else{

CURRENT_NUM=0;

}        //判断右斜下是否5子连珠

for (int i = 0; i 

CURRENT_NUM++;

} else {                break;

}

}        if(MAX_NUMWIN==CURRENT_NUM){            return true;

}else{

CURRENT_NUM=0;

}        return false;

}

}

主方法的调用package com.yaodan.fivechessdemo;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import com.yaodan.fivechessdemo.view.ChessView;public class MainActivity extends AppCompatActivity implements View.OnClickListener {    private Button btn_reatart;    private ChessView chessView;    @Override

protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

btn_reatart = (Button) findViewById(R.id.bt_restart);

chessView= (ChessView) findViewById(R.id.custon_chess_main);

btn_reatart.setOnClickListener(this);

}    @Override

public void onClick(View view) {        switch (view.getId()) {            case R.id.bt_restart:

chessView.myreStart();                break;

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值