目录
实现思路
- 创建一个自定义View,将View平均分配为一个24x24的方块,每个需要消除的块占3个方块,即展示的布局为8x8。如果是想实现9x9,则是27x27,其他分布也同理。
- 随着关卡增多,将视图分为1层2层3层,每层数量1层18 ,2层27,三层27这样排布
- 每层随机抽取相对应的数量的块进行随机排布
代码实现
package com.yltz.ycdcw.views.game;
import android.annotation.SuppressLint;
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.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.yltz.ycdcw.R;
import com.yltz.ycdcw.game.GameYang;
import com.yltz.ycdcw.utils.Utils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @author Created by PengGuiChu on 2022/11/8 10:14.
* @explain 羊了个羊
*/
public class YangLeGeYang extends View {
private final LayerDrawable layerDrawable;
private List<List<GameYang>> gameCardList;
private List<GameYang> missYang = new ArrayList<>();
private int level = -1;
private int[] levelNum = {6, 36, 72, 72, 72};
private Paint strokePaint;
private Paint imgPaint;//背景画笔
private Paint textPaint;//文字画笔
private YangCallback yangCallback;
private int defWidth;
private List<Bitmap> bitmaps = new ArrayList<>();
public YangLeGeYang(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
imgPaint = new Paint();
imgPaint.setStyle(Paint.Style.FILL_AND_STROKE);//充满
imgPaint.setColor(Color.GREEN);
imgPaint.setAntiAlias(true);// 设置画笔的锯齿效果
textPaint = new Paint();
textPaint.setStyle(Paint.Style.FILL);
textPaint.setTextSize(context.getResources().getDimensionPixelSize(R.dimen.sp_20));
textPaint.setColor(getResources().getColor(R.color.red));
textPaint.setTextAlign(Paint.Align.CENTER);
layerDrawable = (LayerDrawable) ContextCompat.getDrawable(context, R.drawable.game_card);
}
@SuppressLint("DrawAllocation")
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (gameCardList != null) {
defWidth = getWidth() / 24;
for (int i = gameCardList.size() - 1; i >= 0; i--) {
List<GameYang> gameYangs = gameCardList.get(i);
for (GameYang gameYang : gameYangs) {
RectF rectF = new RectF(gameYang.x * defWidth, gameYang.y * defWidth, (gameYang.x + 3) * defWidth, (gameYang.y + 3) * defWidth);
canvas.drawBitmap(getBitmap(layerDrawable.getDrawable(gameYang.index)), null, rectF, textPaint);
imgPaint.setStyle(Paint.Style.STROKE);//充满
imgPaint.setColor(Color.BLACK);
canvas.drawRoundRect(rectF, 10, 10, imgPaint);
for (int z = i - 1; z >= 0; z--) {
List<GameYang> colorYangs = gameCardList.get(z);
if (!checkYangCanAdd(gameYang.x, gameYang.y, colorYangs)) {
imgPaint.setStyle(Paint.Style.FILL);//充满
imgPaint.setColor(ContextCompat.getColor(getContext(), R.color.cc000000));
canvas.drawRoundRect(rectF, 10, 10, imgPaint);
break;
}
}
}
}
for (int i = 0; i < 7; i++) {
int left = (int) ((1.5 + i * 3) * defWidth);
int top = (getHeight() - getWidth() - defWidth * 3) / 2 + getWidth();
RectF rectF = new RectF(left, top, left + 3 * defWidth, top + defWidth * 3);
if (missYang.size() > i) {
canvas.drawBitmap(getBitmap(layerDrawable.getDrawable(missYang.get(i).index)), null, rectF, textPaint);
}
imgPaint.setStyle(Paint.Style.STROKE);
imgPaint.setColor(Color.BLACK);
canvas.drawRoundRect(rectF, 10, 10, imgPaint);
}
} else if (level != -1 && gameCardList == null) {
initGameCardList();
}
}
private Bitmap getBitmap(Drawable drawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
private void initGameCardList() {
if (level == -1) return;
if (getWidth() == 0) return;
missYang.clear();
gameCardList = new ArrayList<>();
List<GameYang> gameYangs = new ArrayList<>();
int num = levelNum[level];
if (level == 0) {
for (int i = 0; i < num; i++) {
GameYang gameYang = new GameYang((i + 1) * 3, 12, i % 2);
gameYangs.add(gameYang);
}
gameCardList.add(gameYangs);
} else if (level == 1) {
List<Integer> texts = new ArrayList<>();
for (int i = 0; i < num; i++) {
texts.add(i % 6);
}
Collections.shuffle(texts);
int z = 0;
while (z < 2) {
while (gameYangs.size() < num / 2) {
int randomX = Utils.getRandomInt(22);
int randomY = Utils.getRandomInt(22);
int randomIndex = Utils.getRandomInt(texts.size());
if (checkYangCanAdd(randomX, randomY, gameYangs)) {
GameYang gameYang = new GameYang(randomX, randomY, texts.get(randomIndex));
gameYangs.add(gameYang);
texts.remove(randomIndex);
}
}
gameCardList.add(gameYangs);
gameYangs = new ArrayList<>();
z++;
}
} else {
List<Integer> texts = new ArrayList<>();
for (int i = 0; i < num; i++) {
texts.add(i % 12);
}
Collections.shuffle(texts);
int z = 0;
while (z < 3) {
while (gameYangs.size() < (z == 0 ? 18 : 27)) {
int randomX = Utils.getRandomInt(22);
int randomY = Utils.getRandomInt(22);
int randomIndex = Utils.getRandomInt(texts.size());
if (checkYangCanAdd(randomX, randomY, gameYangs)) {
GameYang gameYang = new GameYang(randomX, randomY, texts.get(randomIndex));
gameYangs.add(gameYang);
texts.remove(randomIndex);
}
}
gameCardList.add(gameYangs);
gameYangs = new ArrayList<>();
z++;
}
}
invalidate();
}
public int getMaxLevel() {
return levelNum.length;
}
private boolean checkYangCanAdd(int x, int y, List<GameYang> gameYangs) {
for (GameYang gameYang : gameYangs) {
if ((!(x + 3 <= gameYang.x || (x >= gameYang.x + 3 && x + 3 <= 24)) && !(y + 3 <= gameYang.y || (y >= gameYang.y + 3 && y + 3 <= 24)))) {
return false;
}
}
return true;
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
if (gameCardList != null && gameCardList.size() > 0 && missYang.size() < 7) {
float x = event.getX();
float y = event.getY();
if (event.getAction() == MotionEvent.ACTION_DOWN) {
for (int i = 0; i < gameCardList.size(); i++) {
List<GameYang> yangList = gameCardList.get(i);
for (GameYang gameYang1 : yangList) {
if (gameYang1.x * defWidth < x && (gameYang1.x + 3) * defWidth > x && gameYang1.y * defWidth < y && (gameYang1.y + 3) * defWidth > y) {
if (i == 1) {
if (!checkYangCanAdd(gameYang1.x, gameYang1.y, gameCardList.get(i - 1))) {
continue;
}
} else if (i == 2) {
if (!checkYangCanAdd(gameYang1.x, gameYang1.y, gameCardList.get(i - 1)) || !checkYangCanAdd(gameYang1.x, gameYang1.y, gameCardList.get(i - 2))) {
continue;
}
}
yangList.remove(gameYang1);
if (yangList.size() == 0) {
gameCardList.remove(yangList);
}
initMissYang(gameYang1);
invalidate();
return true;
}
}
}
}
}
return super.onTouchEvent(event);
}
public void setLevel(int level) {
this.level = level;
initGameCardList();
}
public void setYangCallback(YangCallback yangCallback) {
this.yangCallback = yangCallback;
}
public interface YangCallback {
void onSuccess();
void onFail();
}
private void initMissYang(GameYang gameYang) {
List<GameYang> gameYangs = new ArrayList<>();
int removeNum = 0;
for (GameYang g : missYang) {
if (g.index == gameYang.index) {
removeNum++;
}
}
if (removeNum >= 2) {
for (GameYang g : missYang) {
if (g.index != gameYang.index) {
gameYangs.add(g);
}
}
missYang = gameYangs;
} else {
missYang.add(gameYang);
}
if (yangCallback != null) {
if (missYang.size() == 7) {
yangCallback.onFail();
} else if (missYang.size() == 0 && gameCardList.size() == 0) {
yangCallback.onSuccess();
}
}
}
}
使用
<com.yltz.ycdcw.views.game.YangLeGeYang
android:id="@+id/yang_view"
android:layout_width="@dimen/dp_300"
android:layout_height="@dimen/dp_360"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_tips"
app:layout_constraintBottom_toTopOf="@id/ib_check_point"
/>
yangLeGeYang.setLevel(level);
yangLeGeYang.setYangCallback(new YangLeGeYang.YangCallback() {
@Override
public void onSuccess() {
translationGameResultDialog.show();
translationGameResultDialog.setTv_result_tips(1,"恭喜过关");
new Handler().postDelayed(() -> {
if (translationGameResultDialog != null) {
translationGameResultDialog.dismiss();
}
}, 2000);
}
@Override
public void onFail() {
translationGameResultDialog.show();
translationGameResultDialog.setTv_result_tips(2,"很遗憾,未过关");
}
});
补充
GameYang
package com.yltz.ycdcw.game;
/**
* @author Created by PengGuiChu on 2022/11/8 11:35.
* @explain
*/
public class GameYang {
public int x;
public int y;
public int index;
public GameYang(int x, int y, int index) {
this.x = x;
this.y = y;
this.index = index;
}
}
R.drawable.game_card
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/game_card_1"/>
<item
android:drawable="@drawable/game_card_2"/>
<item
android:drawable="@drawable/game_card_3"/>
<item
android:drawable="@drawable/game_card_4"/>
<item
android:drawable="@drawable/game_card_5"/>
<item
android:drawable="@drawable/game_card_6"/>
<item
android:drawable="@drawable/game_card_7"/>
<item
android:drawable="@drawable/game_card_8"/>
<item
android:drawable="@drawable/game_card_9"/>
<item
android:drawable="@drawable/game_card_10"/>
<item
android:drawable="@drawable/game_card_11"/>
<item
android:drawable="@drawable/game_card_12"/>
</layer-list>