android学习之五子棋游戏demo的实现

package com.zhdf.wuziqi;


import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;


public class wuziqiPanle extends View {


private int mPanleWidth;// 棋盘的宽度的宽度
private float mLineHeight;// 棋盘线与线之间的间隔
private int MAN_LINE = 12; // 棋盘的最大线数
private int MAX_IN_LINE = 5;


private Paint paint = new Paint();
private Bitmap mWhitePiece;
private Bitmap mBlackPiece;
// 设置白棋为先手
private Boolean mIsWhite = true;
// 定义白子坐标的集合
private ArrayList<Point> mWhiteArray = new ArrayList<Point>();
// 定义黑子坐标的集合
private ArrayList<Point> mBlackeArray = new ArrayList<Point>();
// 棋子的大小设置为横高的3/4,这样棋子之间就会有横高的1/4的间隙
private float radioPieceOfLineHeight = 3 * 1.0f / 4;
private Boolean mIsGameOver = false;
private Boolean mIsWhiteWinner;


public wuziqiPanle(Context context, AttributeSet attrs) {
super(context, attrs);
// setBackgroundColor(0x44ff0000);
init();


}


// paint初始化操作
private void init() {
paint.setColor(0x88000000);
paint.setAntiAlias(true);// (抗锯齿功能)使得图像边缘相对清晰一点,锯齿痕迹不那么明显
paint.setDither(true);// (防抖动功能)绘制的时候使得图像颜色相对柔和
paint.setStyle(Paint.Style.STROKE);


mWhitePiece = BitmapFactory.decodeResource(getResources(),
R.drawable.stone_w2);
mBlackPiece = BitmapFactory.decodeResource(getResources(),
R.drawable.stone_b1);
}


/**
* onMeasure测量view 的大小详细测量值 ( measureSpec) 需要两样东西来确定它,那就是大小(size)和模式(mode)
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);


int heightize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);


int width = Math.min(widthSize, heightize);
/**
* UNSPECIFIED *父不没有对子施加任何约束,子可以是任意大小(也就是未指定)
* (UNSPECIFIED在源码中的处理和EXACTLY一样。
* 当View的宽高值设置为0的时候或者没有设置宽高时,模式为UNSPECIFIED
*/
if (widthMode == MeasureSpec.UNSPECIFIED) {
width = heightize;
} else if (heightMode == MeasureSpec.UNSPECIFIED) {
width = widthMode;
}
setMeasuredDimension(width, width);
}


/**
* 当view布局发生变化的时候调用此方法,重新绘制布局
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mPanleWidth = w;
mLineHeight = mPanleWidth * 1.0f / MAN_LINE;


// 更改棋子图片的尺寸大小
int pieceWidth = (int) (mLineHeight * radioPieceOfLineHeight);
mWhitePiece = Bitmap.createScaledBitmap(mWhitePiece, pieceWidth,
pieceWidth, false);
mBlackPiece = Bitmap.createScaledBitmap(mBlackPiece, pieceWidth,
pieceWidth, false);
}


@Override
public boolean onTouchEvent(MotionEvent event) {
if (mIsGameOver)
return false;
int action = event.getAction();
if (action == MotionEvent.ACTION_UP) {
int x = (int) event.getX();
int y = (int) event.getY();
Point p = getValiPoint(x, y);
if (mWhiteArray.contains(p) || mBlackeArray.contains(p)) {
return false;
}
if (mIsWhite) {
mWhiteArray.add(p);
} else {
mBlackeArray.add(p);
}
invalidate();
mIsWhite = !mIsWhite;
return true;// 意思是在该项目中该事件交给View处理
}
return true;
}


// 得到的是点击棋盘上线与线之间的交叉点的坐标,这样能够保证同样一个坐标不会重复放棋子
private Point getValiPoint(int x, int y) {


return new Point((int) (x / mLineHeight), (int) (y / mLineHeight));
}


@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawBoard(canvas);// 绘制棋盘
drawPiece(canvas);// 绘制棋子
checkGameOver();// 检查游戏是否结束
}


private void checkGameOver() {
boolean whiteWin = cheackFiveInLine(mWhiteArray);
boolean blackWin = cheackFiveInLine(mBlackeArray);
if (whiteWin || blackWin) {
mIsGameOver = true;
mIsWhiteWinner = whiteWin;
// 判断是白棋胜还是黑棋胜利 mIsWhiteWinner?"白棋胜利":"黑棋胜利"
String text = mIsWhiteWinner ? "白棋胜利" : "黑棋胜利";
Toast.makeText(getContext(), text, Toast.LENGTH_SHORT).show();
}
}


private boolean cheackFiveInLine(List<Point> points) {
for (Point p : points) {
int x = p.x;
int y = p.y;
boolean win = checkHorizontal(x, y, points);
if (win)
return true;
win = checkVertical(x, y, points);
if (win)
return true;
win = checkLeftDiagonal(x, y, points);
if (win)
return true;
win = checkRightDiagonal(x, y, points);
if (win)
return true;
}
return false;
}


/**
* 判断x,y位置的棋子,是否横向有相邻的五个一致。

* @param x
* @param y
* @param points
* @return
*/
private boolean checkHorizontal(int x, int y, List<Point> points) {
int count = 1;
// 左边相同颜色棋子数的统计
for (int i = 1; i < MAX_IN_LINE; i++) {
if (points.contains(new Point(x - i, y))) {
count++;
} else {
break;
}
}
if (count == MAX_IN_LINE)
return true;


// 右边相同颜色棋子数的统计
for (int i = 1; i < MAX_IN_LINE; i++) {
if (points.contains(new Point(x + i, y))) {
count++;
} else {
break;
}
}
if (count == MAX_IN_LINE)
return true;
return false;
}


/**
* 判断x,y位置的棋子,是否纵向有相邻的五个一致。

* @param x
* @param y
* @param points
* @return
*/
private boolean checkVertical(int x, int y, List<Point> points) {
int count = 1;
// 左边相同颜色棋子数的统计
for (int i = 1; i < MAX_IN_LINE; i++) {
if (points.contains(new Point(x, y - i))) {
count++;
} else {
break;
}
}
if (count == MAX_IN_LINE)
return true;


// 右边相同颜色棋子数的统计
for (int i = 1; i < MAX_IN_LINE; i++) {
if (points.contains(new Point(x, y + i))) {
count++;
} else {
break;
}
}
if (count == MAX_IN_LINE)
return true;
return false;
}


/**
* 判断x,y位置的棋子,是否左斜有相邻的五个一致。

* @param x
* @param y
* @param points
* @return
*/
private boolean checkLeftDiagonal(int x, int y, List<Point> points) {
int count = 1;
// 左边相同颜色棋子数的统计
for (int i = 1; i < MAX_IN_LINE; i++) {
if (points.contains(new Point(x - i, y + i))) {
count++;
} else {
break;
}
}
if (count == MAX_IN_LINE)
return true;


// 右边相同颜色棋子数的统计
for (int i = 1; i < MAX_IN_LINE; i++) {
if (points.contains(new Point(x + i, y - i))) {
count++;
} else {
break;
}
}
if (count == MAX_IN_LINE)
return true;
return false;
}


/**
* 判断x,y位置的棋子,是否右斜有相邻的五个一致。

* @param x
* @param y
* @param points
* @return
*/
private boolean checkRightDiagonal(int x, int y, List<Point> points) {
int count = 1;
// 左边相同颜色棋子数的统计
for (int i = 1; i < MAX_IN_LINE; i++) {
if (points.contains(new Point(x - i, y - i))) {
count++;
} else {
break;
}
}
if (count == MAX_IN_LINE)
return true;


// 右边相同颜色棋子数的统计
for (int i = 1; i < MAX_IN_LINE; i++) {
if (points.contains(new Point(x + i, y + i))) {
count++;
} else {
break;
}
}
if (count == MAX_IN_LINE)
return true;
return false;
}


private void drawPiece(Canvas canvas) {
for (int i = 0, n = mWhiteArray.size(); i < n; i++) {
Point whitePoint = mWhiteArray.get(i);
canvas.drawBitmap(mWhitePiece,
(whitePoint.x + (1 - radioPieceOfLineHeight) / 2)
* mLineHeight,
(whitePoint.y + (1 - radioPieceOfLineHeight) / 2)
* mLineHeight, null);
}
for (int i = 0, n = mBlackeArray.size(); i < n; i++) {
Point blackPoint = mBlackeArray.get(i);
canvas.drawBitmap(mBlackPiece,
(blackPoint.x + (1 - radioPieceOfLineHeight) / 2)
* mLineHeight,
(blackPoint.y + (1 - radioPieceOfLineHeight) / 2)
* mLineHeight, null);
}
}


// 绘制棋盘
private void drawBoard(Canvas canvas) {
int w = mPanleWidth;
float lineWidth = mLineHeight;
for (int i = 0; i < MAN_LINE; i++) {
int startX = (int) (lineWidth / 2);
int endX = (int) (w - lineWidth / 2);
int y = (int) ((0.5 + i) * lineWidth);
// 棋盘横线的绘制
canvas.drawLine(startX, y, endX, y, paint);
/**
* 棋盘纵线的绘制 y为起点的横坐标,startX为起点的纵坐标 endX为纵坐标
*/
canvas.drawLine(y, startX, y, endX, paint);
}
}

public void start()
{
mWhiteArray.clear();
mBlackeArray.clear();
mIsGameOver = false;
mIsWhiteWinner = false;
invalidate();
}


private static final String INSTANCE = "instance";
private static final String INSTANCE_GAME_OVER = "instance_game_over";
private static final String INSTANCE_WHITE_ARRAY = "instance_white_array";
private static final String INSTANCE_BLACK_ARRAY = "instance_black_array";


@Override
protected Parcelable onSaveInstanceState() {
Bundle bundle = new Bundle();
bundle.putParcelable(INSTANCE, super.onSaveInstanceState());
bundle.putBoolean(INSTANCE_GAME_OVER, mIsGameOver);
bundle.putParcelableArrayList(INSTANCE_WHITE_ARRAY, mWhiteArray);
bundle.putParcelableArrayList(INSTANCE_BLACK_ARRAY, mBlackeArray);
return bundle;
}


@Override
protected void onRestoreInstanceState(Parcelable state) {
if (state instanceof Bundle) {
Bundle bundle = (Bundle) state;
mIsGameOver = bundle.getParcelable(INSTANCE_GAME_OVER);
mWhiteArray = bundle.getParcelableArrayList(INSTANCE_WHITE_ARRAY);
mBlackeArray = bundle.getParcelableArrayList(INSTANCE_BLACK_ARRAY);
super.onRestoreInstanceState(bundle.getParcelable(INSTANCE));
}
super.onRestoreInstanceState(state);
}


}


/**

主函数部分


**/

package com.zhdf.wuziqi;


import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.app.Activity;


public class Wuziqi extends Activity {



private wuziqiPanle wuziqipanle;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_wuziqi);
        wuziqipanle = (wuziqiPanle) findViewById(R.id.wuziqi);
        
        
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
   
    getMenuInflater().inflate(R.menu.wuziqi, menu);
    return true;
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
   
    int id = item.getItemId();
    if (id == R.id.action_settings) {
    wuziqipanle.start();
return true;
}
    if (id == R.id.action_exit) {
finish();
}
   
    return super.onOptionsItemSelected(item);
    }
}






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值