大家好,今天我来说说五子棋游戏的实现.
五子棋,包涵了棋盘和棋子,在这里我使用BitMap实现了棋盘和棋子,通过SurfaceView(对SurfaceView不熟悉的同学,可以看看其他博客了解一下)来展示BitMap,通过在工作线程中在BitMap上绘制棋盘和棋子,也就是使用二级缓存。这样减轻了View的绘制负担,提高了游戏的流畅度.废话不多说,上图.
棋盘是正方形,棋子是绘制的BitMap:代码如下
public void drawQiPan() {
Canvas ca = new Canvas(mMyQiPan);
int w = (getWidth() - 100) / 100 * 100;
int h = (getHeight() - 100) / 100 * 100;
value = Math.min(w, h);
mPaint.setColor(Color.BLACK);
mPaint.setStrokeWidth(5);
mPaint.setAntiAlias(true);
//起点
int x = (getWidth() - value) / 2;
int y = (getHeight() - value) / 2;
for (int i = 0; i <= value; i = i + 100) {
ca.drawLine(i + x, 0 + y, i + x, value + y, mPaint);
ca.drawLine(0 + x, i + y, value + x, i + y, mPaint);
}
}
//这里是绘制棋子BitMap和一些初始化工作
private void init() {
holder = getHolder();
mThread = new Thread(this);
mMyQiPan = BitmapFactory.decodeResource(getResources(), R.mipmap.bg).copy(Config.ARGB_8888, true);
mWhite = Bitmap.createBitmap(100, 100, Config.ARGB_8888).copy(Config.ARGB_8888, true);
mBlack = Bitmap.createBitmap(100, 100, Config.ARGB_8888).copy(Config.ARGB_8888, true);
mPaint = new Paint();
mPaint.setColor(Color.WHITE);
Canvas ca = new Canvas(mWhite);
mPaint.setColor(Color.RED);
mPaint.setAntiAlias(true);
ca.drawCircle(45, 45, 46, mPaint);
mPaint.setColor(Color.WHITE);
ca.drawCircle(45, 45, 44, mPaint);
mPaint.setColor(Color.BLACK);
Canvas caa = new Canvas(mBlack);
mPaint.setColor(Color.WHITE);
mPaint.setAntiAlias(true);
caa.drawCircle(45, 45, 46, mPaint);
mPaint.setColor(Color.BLACK);
caa.drawCircle(45, 45, 44, mPaint);
mQiZiBlack = new ArrayList<>();
mQiZiWihte = new ArrayList<>();
mRect = new Rect(0, 0, getWidth(), getHeight());
holder.addCallback(this);
}
//
绘制好棋盘和准备好棋子后,需要对触摸操作进行绘制棋子
public boolean onTouchEvent(MotionEvent event) {
//起点
int x = (getWidth() - value) / 2;
int y = (getHeight() - value) / 2;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
return true;
case MotionEvent.ACTION_MOVE:
isMoving = true;
return false;
case MotionEvent.ACTION_UP:
if (isWin||isMoving) {
break;
}
int xx = (int) event.getX();
int yy = (int) event.getY();
currentPoint = new Point((xx - x) / 100, (yy - y) / 100);
if (!check(currentPoint)) {
break;
}
isWhite = !isWhite;
if (isWhite) {
mQiZiWihte.add(currentPoint);
} else {
mQiZiBlack.add(currentPoint);
}
//判断在那个位置上
new Thread(this).start();
//判断
if (isWhite) {
if (mQiZiWihte.size() < 5) {
break;
}
} else {
if (mQiZiBlack.size() < 5) {
break;
}
}
if (currentPoint != null ) {
checkH(currentPoint,true);
if (!isWin){
checkH(currentPoint,false);
}
if (!isWin){
checkDuijiao();
}
if (!isWin){
chekZhengXianxian();
}
if (isWin) {
Toast.makeText(getContext().getApplicationContext(), "赢了", Toast.LENGTH_LONG).show();
}
}
break;
}
return super.onTouchEvent(event);
}
这里是当收到UP事件的时候进行处理,当移动事件发生时,我们就不作处理.保存完黑白棋子集合后,就要绘制它们了,代码如下:
//线程方法
@Override
public void run() {
int x = (getWidth() - value) / 2;
int y = (getHeight() - value) / 2;
drawQiPan();
Canvas ca = new Canvas(mMyQiPan);
for (int i = 0; i < mQiZiWihte.size(); i++) {
ca.drawBitmap(mWhite, mQiZiWihte.get(i).x * 100 + x - 46, mQiZiWihte.get(i).y * 100 + y - 46, mPaint);
}
for (int i = 0; i < mQiZiBlack.size(); i++) {
ca.drawBitmap(mBlack, mQiZiBlack.get(i).x * 100 + x - 46, mQiZiBlack.get(i).y * 100 + y - 46, mPaint);
}
Canvas canvas = holder.lockCanvas(mRect);
canvas.drawBitmap(mMyQiPan, mRect, new Rect(0, 0, getWidth(), getHeight()), mPaint);
holder.unlockCanvasAndPost(canvas);
}
通过线程绘制图片,再讲图片贴在View上面,减轻View的负担。接下来就要处理棋子落下的正确性检查
1.检查该位置是否已经下过;
public boolean check(Point point) {
int num = value / 100;
if (mQiZiWihte.contains(point) || mQiZiBlack.contains(point)) {
return false;
}
if (point.x >= 0 && point.y < num + 1 && point.x < num + 1 && point.y >= 0) {
return true;
}
return false;
}
2.检查是否是5子连珠(横,竖,正对角,斜对角);
public void checkH(Point point,boolean isX) {
int x = point.x;
int y = point.y;
int count = 1;
int xunhuan;
if (isX){
xunhuan = x;
}else {
xunhuan = y;
}
//想左
for (int i = xunhuan - 1; i >= 0; i--) {
int xx;
int yy;
if (isX){
xx = i;
yy = point.y;
}else {
xx = point.x;
yy = i;
}
if (equal(xx, yy)) {
count++;
Log.e("==z====","====="+count);
if (countCheck(count)) {
isWin = true;
Log.e("==z====","==1==="+count);
return;
}
} else {
break;
}
}
//向右
for (int i = xunhuan + 1; i < value / 100 + 1; i++) {
int xx;
int yy;
if (isX){
xx = i;
yy = point.y;
}else {
xx = point.x;
yy = i;
}
if (equal(xx, yy)) {
count++;
if (countCheck(count)) {
isWin = true;
Log.e("==z====","==2==="+count);
return;
}
} else {
break;
}
}
}
//检查斜线
public void checkDuijiao(){
int count = 1;
for (int i =1; i <= value/100; i++) {
if (currentPoint.x+i>value/100||currentPoint.y+i>value/100){
break;
}
if (equal(currentPoint.x+i,currentPoint.y+i)){
count++;
countCheck(count);
if (countCheck(count)){
isWin = true;
Log.e("==z====","===3=="+count);
return;
}
}else {
break;
}
}
for (int i = 1; i<=value/100 ;i++) {
if (currentPoint.x-i>value/100||currentPoint.y-i>value/100){
break;
}
if (equal(currentPoint.x-i,currentPoint.y-i)){
count++;
if (countCheck(count)){
isWin = true;
Log.e("==z====","==4==="+count);
return;
}
}else {
break;
}
}
}
public void chekZhengXianxian(){
int count = 1;
int mine = Math.min(currentPoint.x,currentPoint.y);
for (int i = 1; i < value/100; i++) {
if (currentPoint.x+i>value/100||currentPoint.y-i<0){
break;
}
if (equal(currentPoint.x+i,currentPoint.y-i)){
count++;
countCheck(count);
if (countCheck(count)){
isWin = true;
Log.e("==z====","===5=="+count);
return;
}
}else {
break;
}
}
for (int i = 1; i >=0; i++) {
if (currentPoint.x+i>value/100||currentPoint.y-i<0){
break;
}
if (equal(currentPoint.x-i,currentPoint.y+i)){
count++;
if (countCheck(count)){
isWin = true;
Log.e("==z====","===6=="+count);
return;
}
}else {
break;
}
}
}
其中的equal()方法和countChek()方法是判断点是否存在和点的数量是否已经达到5个。由于字数限制,我就不贴出来了。项地址https://github.com/yzzAndroid/5ZiQiPlay。好啦,这样下来我们就完成了五子棋的简单实现,谢谢。