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();
}
}