五子棋

MyView

package com.example.demo;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;

import java.util.ArrayList;

public class MyView extends View {
    // 整个棋盘的宽度=高度
    int panel_width;
    // 每个格子的宽度=高度
    int cell_width;
    // 每个棋子的宽度=高度
    float piece_percent = 0.75F;
    int piece_width;

    Paint paint = new Paint();
    private Bitmap rawWhitePiece;
    private Bitmap rawBlackPiece;
    private Bitmap whitePiece;
    private Bitmap blackPiece;

    ArrayList<PieceLocation> whiteArray = new ArrayList<>();
    ArrayList<PieceLocation> blackArray = new ArrayList<>();

    boolean isWhite = false;

    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        paint.setStrokeWidth(4);

        rawWhitePiece = BitmapFactory.decodeResource(getResources(), R.drawable.stone_w2);
        rawBlackPiece = BitmapFactory.decodeResource(getResources(), R.drawable.stone_b1);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(Color.argb(20, 200, 0, 0));
        // 画棋盘的十条横线
        drawTenHengXian(canvas);
        // 画棋盘的十条竖线
        drawTenShuXian(canvas);

//        if(pieceLocation != null){
//        // 根据棋子坐标绘制
//        float x = (float) ((pieceLocation.x + (0.5-piece_percent/2))*cell_width);
//        float y = (float) ((pieceLocation.y + (0.5-piece_percent/2))*cell_width);
//        canvas.drawBitmap(whitePiece, x, y, paint);
//        }

        for (PieceLocation pieceLocation : whiteArray) {
            float x = (float) ((pieceLocation.x + (0.5 - piece_percent / 2)) * cell_width);
            float y = (float) ((pieceLocation.y + (0.5 - piece_percent / 2)) * cell_width);
            canvas.drawBitmap(whitePiece, x, y, paint);
        }

        for (PieceLocation pieceLocation : blackArray) {
            float x = (float) ((pieceLocation.x + (0.5 - piece_percent / 2)) * cell_width);
            float y = (float) ((pieceLocation.y + (0.5 - piece_percent / 2)) * cell_width);
            canvas.drawBitmap(blackPiece, x, y, paint);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_UP:
                PieceLocation pieceLocation = getPieceLocation(x, y);
                if (isWhite) {
                    whiteArray.add(pieceLocation);
                } else {
                    blackArray.add(pieceLocation);
                }

                isWhite = !isWhite;
                invalidate();
                break;
        }
        return true;
    }

    /**
     * 根据触摸点的x y坐标得到棋子实际应放置的坐标
     *
     * @param x
     * @param y
     * @return
     */
    private PieceLocation getPieceLocation(float x, float y) {
        PieceLocation pieceLocation = new PieceLocation();
        pieceLocation.x = (int) (x / cell_width);
        pieceLocation.y = (int) (y / cell_width);
        return pieceLocation;
    }

    private void drawTenShuXian(Canvas canvas) {
        int startX = cell_width / 2;
        int startY = cell_width / 2;
        int stopX = cell_width / 2;
        int stopY = panel_width - (cell_width / 2);
        for (int i = 0; i < 10; i++) {
            canvas.drawLine(startX + (i * cell_width), startY,
                    stopX + (i * cell_width), stopY, paint);
        }

    }

    private void drawTenHengXian(Canvas canvas) {
        int startX = cell_width / 2;
        int startY = cell_width / 2;
        int stopX = panel_width - (cell_width / 2);
        int stopY = cell_width / 2;
        for (int i = 0; i < 10; i++) {
            canvas.drawLine(startX, startY + i * cell_width,
                    stopX, stopY + i * cell_width, paint);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        Log.e("onMeasure", "width = " + width + " height = " + height);
        int min = width;
        if (width > height) {
            min = height;
        }
        // 设置棋盘的绘制区域为一个正方形 同时选宽高的小值
        setMeasuredDimension(min, min);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        Log.e("onSizeChanged", "w = " + w + " h = " + h);
        super.onSizeChanged(w, h, oldw, oldh);
        panel_width = w;
        cell_width = w / 10;
        piece_width = (int) (cell_width * piece_percent);

        // 根据棋子指定的大小 生成bitmap
        whitePiece = Bitmap.createScaledBitmap(rawWhitePiece, piece_width, piece_width, false);
        blackPiece = Bitmap.createScaledBitmap(rawBlackPiece, piece_width, piece_width, false);

    }
}

PieceLocation

package com.example.demo;
// 自定义棋子的坐标
public class PieceLocation {
    int x;
    int y;
}

问题1.已经落子的地方 不能再下

在这里插入图片描述

// 先要判断该位置是否已有棋子
                if(whitePieceArray.contains(location) || blackPieceArray.contains(location)){
                    Toast.makeText(getContext(), "已有棋子不能再下这里"
                    ,Toast.LENGTH_SHORT).show();

                    return true;
                }

去PieceLocation类中实现equals方法
在这里插入图片描述

 @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        PieceLocation that = (PieceLocation) o;
        return x == that.x &&
                y == that.y;
    }
问题2 判断赢

分四种情况,8个方向情况去判断

1、水平方向
/**
     * 判断水平方向是否赢了
     * @param pieceArray
     * @return
     */
    private boolean judgeHorizontalArray(List<PieceLocation> pieceArray) {
        for(PieceLocation location:pieceArray){
            int count = 1;
            // 向左走4个
            for (int i=1; i<5; i++){
                PieceLocation temp = new PieceLocation(location.x - i, location.y);
                if(pieceArray.contains(temp)){
                    count++;
                }
            }

            if (count ==5){
                return true;
            }

		    // 重置count
			count = 1;
            // 向右走4个
            for (int i=1; i<5; i++){
                PieceLocation temp = new PieceLocation(location.x + i, location.y);
                if(pieceArray.contains(temp)){
                    count++;
                }
            }

            if (count ==5){
                return true;
            }
        }

        return  false;
    }
2、垂直方向
/**
     * 判断垂直方向有没有赢
     * @param pieceArray
     * @return
     */
    private boolean judgeVerticalArray(List<PieceLocation> pieceArray) {
        for(PieceLocation location:pieceArray){
            int count = 1;
            // 向上走4个
            for (int i=1; i<5; i++){
                PieceLocation temp = new PieceLocation(location.x, location.y-i);
                if(pieceArray.contains(temp)){
                    count++;
                }
            }

            if (count ==5){
                return true;
            }
            // 重置count
			count = 1;
            // 向下走4个
            for (int i=1; i<5; i++){
                PieceLocation temp = new PieceLocation(location.x, location.y+i);
                if(pieceArray.contains(temp)){
                    count++;
                }
            }

            if (count ==5){
                return true;
            }
        }

        return  false;
    }
3 右上方向
/**
     * 判断右上方向有没有赢
     * @param pieceArray
     * @return
     */
    private boolean judgeRightUpArray(List<PieceLocation> pieceArray) {
        for(PieceLocation location:pieceArray){
            int count = 1;
            // 向右上走4个
            for (int i=1; i<5; i++){
                PieceLocation temp = new PieceLocation(location.x+i, location.y-i);
                if(pieceArray.contains(temp)){
                    count++;
                }
            }

            if (count ==5){
                return true;
            }
            
            // 重置count
			count = 1;

            // 向左下走4个
            for (int i=1; i<5; i++){
                PieceLocation temp = new PieceLocation(location.x-i, location.y+i);
                if(pieceArray.contains(temp)){
                    count++;
                }
            }

            if (count ==5){
                return true;
            }
        }

        return  false;
    }
4 右下方向
 /**
     * 判断右下方向有没有赢
     * @param pieceArray
     * @return
     */
    private boolean judgeRightDownArray(List<PieceLocation> pieceArray) {
        for(PieceLocation location:pieceArray){
            int count = 1;
            // 向右下走4个
            for (int i=1; i<5; i++){
                PieceLocation temp = new PieceLocation(location.x+i, location.y+i);
                if(pieceArray.contains(temp)){
                    count++;
                }
            }

            if (count ==5){
                return true;
            }
            
			// 重置count
			count = 1;
            // 向左上走4个
            for (int i=1; i<5; i++){
                PieceLocation temp = new PieceLocation(location.x-i, location.y-i);
                if(pieceArray.contains(temp)){
                    count++;
                }
            }

            if (count ==5){
                return true;
            }
        }

        return  false;
    }
完整的MyView代码
package com.example.myapplication;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

import androidx.annotation.Nullable;

import java.util.ArrayList;
import java.util.List;

public class MyView extends View {
    // 面板的宽度=高度
    int panel_width;
    // 每个格子的宽度=高度
    int cell_width;
    // 棋子宽度占格子宽度的比例
    float piece_percent = 0.75F;
    // 每个棋子的宽度=高度
    int piece_width;
    // 画笔
    Paint paint = new Paint();

    // 原始大小的棋子
    Bitmap rawWhitePiece;
    Bitmap rawBlackPiece;

    // 需要绘制的棋子
    Bitmap whitePiece;
    Bitmap blackPiece;

    // 是否已经赢了 停止
    boolean isStop = false;

    // 当前下棋的位置
//    PieceLocation location;

    // 用两个List分别保存白子 和黑子 的位置
    List<PieceLocation> whitePieceArray = new ArrayList<>();
    List<PieceLocation> blackPieceArray = new ArrayList<>();

    // 当前下的是白子吗
    boolean isWhite = false;

    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        paint.setStrokeWidth(4);

        rawWhitePiece = BitmapFactory.decodeResource(getResources(), R.drawable.stone_w2);
        rawBlackPiece = BitmapFactory.decodeResource(getResources(), R.drawable.stone_b1);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(Color.argb(25, 200, 0, 0));

        // 画十条横线
        drawTenHengXian(canvas);
        // 画十条竖线
        drawTenShuXian(canvas);

//        canvas.drawBitmap(whitePiece, 0, 0, paint);

        // 绘制棋子
//        if(location != null) {
//            float x = (location.x + (0.5F - piece_percent / 2)) * cell_width;
//            float y = (location.y + (0.5F - piece_percent / 2)) * cell_width;
//            canvas.drawBitmap(whitePiece, x, y, paint);
//        }

        // 绘制白子和黑子的列表
        for (PieceLocation location : whitePieceArray) {
            float x = (location.x + (0.5F - piece_percent / 2)) * cell_width;
            float y = (location.y + (0.5F - piece_percent / 2)) * cell_width;
            canvas.drawBitmap(whitePiece, x, y, paint);
        }

        for (PieceLocation location : blackPieceArray) {
            float x = (location.x + (0.5F - piece_percent / 2)) * cell_width;
            float y = (location.y + (0.5F - piece_percent / 2)) * cell_width;
            canvas.drawBitmap(blackPiece, x, y, paint);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // 如果一方已经赢了 那就不能再下了
        if (isStop) {
            return true;
        }

        float x = event.getX();
        float y = event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_UP:
                PieceLocation location = getPieceLocation(x, y);

                // 先要判断该位置是否已有棋子
                if (whitePieceArray.contains(location) || blackPieceArray.contains(location)) {
                    Toast.makeText(getContext(), "已有棋子不能再下这里"
                            , Toast.LENGTH_SHORT).show();

                    return true;
                }


                // 加入到白子或黑子的位置列表
                if (isWhite) {
                    whitePieceArray.add(location);
                } else {
                    blackPieceArray.add(location);
                }

                // 判断某一方有没有赢
                judge();

                isWhite = !isWhite;
                invalidate();
                break;
        }

        return true;
    }

    /**
     * 判断某一方有没有赢
     */
    private void judge() {
        if (isWhite) {
            // 判断白子有没有赢
            if (judgeArray(whitePieceArray)) {
                Toast.makeText(getContext(), "白子赢啦", Toast.LENGTH_SHORT).show();
                isStop = true;
            }
        } else {
            // 判断黑子有没有赢
            if (judgeArray(blackPieceArray)) {
                Toast.makeText(getContext(), "黑子赢啦", Toast.LENGTH_SHORT).show();
                isStop = true;
            }
        }
    }

    private boolean judgeArray(List<PieceLocation> pieceArray) {
        if (pieceArray.size() < 5) {
            return false;
        }
        // 判断水平方向赢了没
        if (judgeHorizontalArray(pieceArray)) {
            return true;
        }

        if (judgeVerticalArray(pieceArray)) {
            return true;
        }

        if (judgeRightDownArray(pieceArray)) {
            return true;
        }

        return judgeRightUpArray(pieceArray);
    }

    /**
     * 判断右上方向有没有赢
     *
     * @param pieceArray
     * @return
     */
    private boolean judgeRightUpArray(List<PieceLocation> pieceArray) {
        for (PieceLocation location : pieceArray) {
            int count = 1;
            // 向右上走4个
            for (int i = 1; i < 5; i++) {
                PieceLocation temp = new PieceLocation(location.x + i, location.y - i);
                if (pieceArray.contains(temp)) {
                    count++;
                }
            }

            if (count == 5) {
                return true;
            }

            // 重置count
            count = 1;
            // 向左下走4个
            for (int i = 1; i < 5; i++) {
                PieceLocation temp = new PieceLocation(location.x - i, location.y + i);
                if (pieceArray.contains(temp)) {
                    count++;
                }
            }

            if (count == 5) {
                return true;
            }
        }

        return false;
    }

    /**
     * 判断右下方向有没有赢
     *
     * @param pieceArray
     * @return
     */
    private boolean judgeRightDownArray(List<PieceLocation> pieceArray) {
        for (PieceLocation location : pieceArray) {
            int count = 1;
            // 向右下走4个
            for (int i = 1; i < 5; i++) {
                PieceLocation temp = new PieceLocation(location.x + i, location.y + i);
                if (pieceArray.contains(temp)) {
                    count++;
                }
            }

            if (count == 5) {
                return true;
            }

            count = 1;
            // 向左上走4个
            for (int i = 1; i < 5; i++) {
                PieceLocation temp = new PieceLocation(location.x - i, location.y - i);
                if (pieceArray.contains(temp)) {
                    count++;
                }
            }

            if (count == 5) {
                return true;
            }
        }

        return false;
    }

    /**
     * 判断垂直方向有没有赢
     *
     * @param pieceArray
     * @return
     */
    private boolean judgeVerticalArray(List<PieceLocation> pieceArray) {
        for (PieceLocation location : pieceArray) {
            int count = 1;
            // 向上走4个
            for (int i = 1; i < 5; i++) {
                PieceLocation temp = new PieceLocation(location.x, location.y - i);
                if (pieceArray.contains(temp)) {
                    count++;
                }
            }

            if (count == 5) {
                return true;
            }

            count = 1;
            // 向下走4个
            for (int i = 1; i < 5; i++) {
                PieceLocation temp = new PieceLocation(location.x, location.y + i);
                if (pieceArray.contains(temp)) {
                    count++;
                }
            }

            if (count == 5) {
                return true;
            }
        }

        return false;
    }

    /**
     * 判断水平方向是否赢了
     *
     * @param pieceArray
     * @return
     */
    private boolean judgeHorizontalArray(List<PieceLocation> pieceArray) {
        for (PieceLocation location : pieceArray) {
            int count = 1;
            // 向左走4个
            for (int i = 1; i < 5; i++) {
                PieceLocation temp = new PieceLocation(location.x - i, location.y);
                if (pieceArray.contains(temp)) {
                    count++;
                }
            }

            if (count == 5) {
                return true;
            }

            count = 1;
            // 向右走4个
            for (int i = 1; i < 5; i++) {
                PieceLocation temp = new PieceLocation(location.x + i, location.y);
                if (pieceArray.contains(temp)) {
                    count++;
                }
            }

            if (count == 5) {
                return true;
            }
        }

        return false;
    }

    // 根据触摸的坐标计算棋子的位置
    private PieceLocation getPieceLocation(float x, float y) {
        PieceLocation pieceLocation = new PieceLocation();
        pieceLocation.x = (int) (x / cell_width);
        pieceLocation.y = (int) (y / cell_width);
        return pieceLocation;
    }

    /**
     * 画十条竖线
     *
     * @param canvas
     */
    private void drawTenShuXian(Canvas canvas) {
        float startX = cell_width * 0.5F;
        float startY = cell_width * 0.5F;
        float stopX = cell_width * 0.5F;
        float stopY = panel_width - cell_width * 0.5F;

        for (int i = 0; i < 10; i++) {
            canvas.drawLine(startX + i * cell_width, startY, stopX + i * cell_width, stopY, paint);
        }
    }

    /**
     * 画十条横线
     *
     * @param canvas
     */
    private void drawTenHengXian(Canvas canvas) {
        float startX = cell_width * 0.5F;
        float startY = cell_width * 0.5F;
        float stopX = panel_width - cell_width * 0.5F;
        float stopY = cell_width * 0.5F;

        for (int i = 0; i < 10; i++) {
            canvas.drawLine(startX, startY + i * cell_width, stopX, stopY + i * cell_width, paint);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        Log.e("onMeasure", "width = " + width + " height = " + height);
        int min = width;
        if (width > height) {
            min = height;
        }

        setMeasuredDimension(min, min);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        Log.e("onSizeChanged", "w = " + w + "  h = " + h);
        panel_width = w;
        cell_width = panel_width / 10;
        piece_width = (int) (cell_width * piece_percent);

        // 生成指定大小的棋子
        whitePiece = Bitmap.createScaledBitmap(rawWhitePiece, piece_width, piece_width, false);
        blackPiece = Bitmap.createScaledBitmap(rawBlackPiece, piece_width, piece_width, false);
    }

    // 重新开始  就要把所有的参数重置
    public void reStart() {
        whitePieceArray.clear();
        blackPieceArray.clear();
        isWhite = false;
        isStop = false;
        invalidate();
    }
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值