您的位置:首页 > 移动开发 > Android开发

Android 小游戏之五子棋 代码简单实现

2017-07-14 14:25 651 查看
鸿洋写的五子棋教程

public class WuZhiQiView extends View { //自定义的五子棋View
//画一个棋盘,在中间画一个一个的小正方形,主要实现在onDraw   method
//画棋子,主要实现在onDraw   method
//点击那里实现具体判断具体位置,在具体位置画棋子
//实现输赢判断机制
protected static int GRID_SIZE = 15;    //一排有几个格子 ,线要比实际多一条
protected static int GRID_WIDTH = 20;  //棋盘格的宽度 --下面做了自动适配屏幕 --这里数字无效
protected static int CHESS_DIAMETER = 16; // 棋的直径  --下面做了自动适配屏幕 --这里数字无效
protected static int mStartX;// 棋盘定位的左上角X
protected static int mStartY;// 棋盘定位的左上角Y
private static int[][] mGridArray; // 网格 ---进行标识棋子的位置 -- 用来画旗子和判断输赢
boolean key = false;//是否下棋了
int wbflag = 1; //该下白棋了=2,该下黑棋了=1. 这里先下黑棋(黑棋以后设置为机器自动下的棋子)
int mWinFlag = 0;//游戏赢了的标志 为1就是黑棋赢了 2为白棋子赢了
private final int BLACK = 1;//黑棋
private final int WHITE = 2;//白棋

int mGameState = GAMESTATE_RUN; //游戏阶段:0=尚未游戏,1=正在进行游戏,3=游戏结束
static final int GAMESTATE_PRE = 0;
static final int GAMESTATE_RUN = 1;
static final int GAMESTATE_PAUSE = 2;  //游戏暂停
static final int GAMESTATE_END = 3;  //游戏结束

private final Paint mPaint = new Paint();//是声明用来画棋子图片的笔,没用上

CharSequence mText;
CharSequence STRING_WIN = "白方棋子赢,按返回键重新开始";
CharSequence STRING_LOSE = "黑方棋子赢,按返回键重新来过";
CharSequence STRING_EQUAL = "Cool! You are equal! /n Press Fire Key to start new Game.";
private static Bitmap mBitmap;   //记录这一刻的画面 ---不用每次画棋盘和旗子
private Canvas mMCanvas; //在画布上操作mBitmap的画面 --- 进行给上次的bitmap添加一个旗子就可以了

public WuZhiQiView(Context context, AttributeSet attrs) {
super(context, attrs);
this.setFocusable(true);//设置获取焦点
setFocusableInTouchMode(true);//设置可以触摸
init();//画棋子
}

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
return super.dispatchTouchEvent(event);
}

private void init() {//画棋子等逻辑
mGameState = 1; //设置游戏为开始状态
wbflag = BLACK; //初始为先下黑棋
mWinFlag = 0;   //清空输赢标志。
mGridArray = new int[GRID_SIZE + 1][GRID_SIZE + 1];//初始化网格的大小
}

public TextView mStatusTextView; //  根据游戏状态设置显示的文字 --- 这里只是简单的显示谁赢了

public void setTextView(TextView tv) { //给外面的接口显示输赢信息 // TODO 可以自己修改
mStatusT
4000
extView = tv;
mStatusTextView.setVisibility(View.INVISIBLE);//显示输赢的textView
}

public  int dip2px(float dpValue) { //dp 转 px
final float scale = getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
GRID_WIDTH = w/GRID_SIZE-dip2px(2);//自行匹配屏幕
CHESS_DIAMETER =GRID_WIDTH -dip2px(5);//自行匹配棋子的宽度
mStartX = w / 2 - GRID_SIZE * GRID_WIDTH / 2;//棋盘定位的左上角X
mStartY = h / 2 - GRID_SIZE * GRID_WIDTH / 2;//棋盘定位的左上角Y
}

int x;//记录触摸最后棋子落子的位置(是在数据里的角标记录)
int y;//记录触摸最后棋子落子的位置

//触摸事件的处理
@Override
public boolean onTouchEvent(MotionEvent event) {//处理棋子落子后的逻辑
key = true;
switch (mGameState) {//游戏状态
case GAMESTATE_PRE://游戏未开始
break;
case GAMESTATE_RUN: {//游戏开始
float x0 = GRID_WIDTH - (event.getX() - mStartX) % GRID_WIDTH;//是否是触摸了网格上面的x
float y0 = GRID_WIDTH - (event.getY() - mStartY) % GRID_WIDTH;//是否是触摸了网格上面的y
if (x0 < GRID_WIDTH / 2) {//判断是否超过了网格线的一半
x = (int) ((event.getX() - mStartX) / GRID_WIDTH) + 1;//x为网格的线上
} else {
x = (int) ((event.getX() - mStartX) / GRID_WIDTH);//x为网格的线上 上一格
}
if (y0 < GRID_WIDTH / 2) {//判断是否超过了网格线的一半
y = (int) ((event.getY() - mStartY) / GRID_WIDTH) + 1;
} else {
y = (int) ((event.getY() - mStartY) / GRID_WIDTH);
}
if ((x >= 0 && x < GRID_SIZE + 1)
&& (y >= 0 && y < GRID_SIZE + 1)) {//是否是在网格线上
if (mGridArray[x][y] == 0) {//如果棋盘的点没有没赋值,就可以被下子
if (wbflag == BLACK) {//判断是黑棋 下棋
putChess(x, y, BLACK);//下子,给数组里的棋子赋值做标记
//this.mGridArray[x][y] = 1;
if (checkWin(BLACK)) { //如果是黑棋赢了,判断机制
mText = STRING_LOSE;//文本
mGameState = GAMESTATE_END;//标记游戏结束,不能下棋子
showTextView(mText);//显示文本
} else if (checkFull()) {//如果棋盘满了
mText = STRING_EQUAL;//文本
mGameState = GAMESTATE_END;//标记游戏结束,不能下棋子
showTextView(mText);//显示文本
}

wbflag = WHITE;//标记另一方下子
this.invalidate();//重画界面
} else if (wbflag == WHITE) { //判断是白棋下子
putChess(x, y, WHITE);
//this.mGridArray[x][y] = 2;
if (checkWin(WHITE)) {
mText = STRING_WIN;
mGameState = GAMESTATE_END;
showTextView(mText);
} else if (checkFull()) {//如果棋盘满了
mText = STRING_EQUAL;
mGameState = GAMESTATE_END;
showTextView(mText);
}
wbflag = BLACK;
this.invalidate();//重画界面
}
}
}

}

break;
case GAMESTATE_PAUSE://游戏暂停
break;
case GAMESTATE_END://游戏结束
break;
}
return true;

}

@Override
public boolean onKeyDown(int keyCode, KeyEvent msg) {//复写返回按钮,重新开始

if (keyCode == KeyEvent.KEYCODE_BACK) {
switch (mGameState) {
case GAMESTATE_PRE://游戏状态,游戏准备前
break;
case GAMESTATE_RUN:
break;
case GAMESTATE_PAUSE:
break;
case GAMESTATE_END: {//游戏结束后,按CENTER键继续
mGameState = GAMESTATE_RUN;//改变游戏状态
this.setVisibility(View.VISIBLE);//本view可见
this.mStatusTextView.setVisibility(View.INVISIBLE);//提示信息不可见
this.init();//重画棋子等,重走逻辑
flag = false;
this.invalidate();//重画
}
break;
}
}

return true;//复写方法,自己处理
}

boolean flag;

@Override
public void onDraw(Canvas canvas) {// 画棋盘
canvas.drawColor(Color.YELLOW);
if (flag == false) {//控制画棋盘的次数,只画一次棋盘,提高绘制效率
mBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
mMCanvas = new Canvas(mBitmap);
// 画棋盘
//画棋盘的外边框
mPaint.setColor(Color.GRAY);//设置画笔的颜色,灰色
mPaint.setStyle(Paint.Style.STROKE);//设置风格是描边
mPaint.setStrokeWidth(4);
mMCanvas.drawRect(mStartX, mStartY, mStartX + GRID_WIDTH * GRID_SIZE, mStartY + GRID_WIDTH * GRID_SIZE, mPaint);

mPaint.setStrokeWidth(2);//设置线条宽度
//画中间的格子
for (int i = 0; i < GRID_SIZE; i++) {//画线
for (int j = 0; j < GRID_SIZE; j++) {
int mLeft = i * GRID_WIDTH + mStartX;
int mTop = j * GRID_WIDTH + mStartY;
int mRright = mLeft + GRID_WIDTH;
int mBottom = mTop + GRID_WIDTH;
mMCanvas.drawRect(mLeft, mTop, mRright, mBottom, mPaint);//画一段一段小矩形,形成棋盘
}
}
flag = true;
}
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);  //设置风格是描边和填充
if (mGridArray[x][y] == BLACK) { //画黑棋子
mPaint.setColor(Color.BLACK);
mMCanvas.drawCircle(mStartX + x * GRID_WIDTH, mStartY + y * GRID_WIDTH, CHESS_DIAMETER / 2, mPaint);
} else if (mGridArray[x][y] == WHITE) { //画白棋
mPaint.setColor(Color.WHITE);
mMCanvas.drawCircle(mStartX + x * GRID_WIDTH, mStartY + y * GRID_WIDTH, CHESS_DIAMETER / 2, mPaint);
}
canvas.drawBitmap(mBitmap, 0, 0, mPaint);
}

public void putChess(int x, int y, int blackwhite) {//标志棋子赋值,给棋子做标记
mGridArray[x][y] = blackwhite;
}

public boolean checkWin(int wbflag) {//输赢判断机制
for (int i = 0; i < GRID_SIZE - 1; i++) //i表示列(根据宽度算出来的)
for (int j = 0; j < GRID_SIZE - 1; j++) {//i表示行(根据高度算出来的)
//检测横轴五个相连
if (((i + 4) < (GRID_SIZE - 1)) &&
(mGridArray[i][j] == wbflag) && (mGridArray[i + 1][j] == wbflag) && (mGridArray[i + 2][j] == wbflag) && (mGridArray[i + 3][j] == wbflag) && (mGridArray[i + 4][j] == wbflag)) {
Log.e("check win or loss:", wbflag + "win");

mWinFlag = wbflag;
}

//纵轴5个相连
if (((j + 4) < (GRID_SIZE - 1)) &&
(mGridArray[i][j] == wbflag) && (mGridArray[i][j + 1] == wbflag) && (mGridArray[i][j + 2] == wbflag) && (mGridArray[i][j + 3] == wbflag) && (mGridArray[i][j + 4] == wbflag)) {
Log.e("check win or loss:", wbflag + "win");

mWinFlag = wbflag;
}

//左上到右下5个相连
if (((j + 4) < (GRID_SIZE - 1)) && ((i + 4) < (GRID_SIZE - 1)) &&
(mGridArray[i][j] == wbflag) && (mGridArray[i + 1][j + 1] == wbflag) && (mGridArray[i + 2][j + 2] == wbflag) && (mGridArray[i + 3][j + 3] == wbflag) && (mGridArray[i + 4][j + 4] == wbflag)) {
Log.e("check win or loss:", wbflag + "win");

mWinFlag = wbflag;
}

//右上到左下5个相连
if (((i - 4) >= 0) && ((j + 4) < (GRID_SIZE - 1)) &&
(mGridArray[i][j] == wbflag) && (mGridArray[i - 1][j + 1] == wbflag) && (mGridArray[i - 2][j + 2] == wbflag) && (mGridArray[i - 3][j + 3] == wbflag) && (mGridArray[i - 4][j + 4] == wbflag)) {
Log.e("check win or loss:", wbflag + "win");

mWinFlag = wbflag;
}
}

if (mWinFlag == wbflag) {
return true;
} else {
return false;
}

}

public boolean checkFull() {//判断是否棋子已经满棋盘了
int mNotEmpty = 0;
for (int i = 0; i < GRID_SIZE - 1; i++)
for (int j = 0; j < GRID_SIZE - 1; j++) {
if (mGridArray[i][j] != 0) mNotEmpty += 1;
}

if (mNotEmpty == (GRID_SIZE - 1) * (GRID_SIZE - 1))
return true;
else
return false;
}

public void showTextView(CharSequence mT) {//显示提示文本
if(mStatusTextView==null) return;
this.mStatusTextView.setText(mT);
mStatusTextView.setVisibility(View.VISIBLE);
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: