Kotlin版拼图游戏,做出来不会玩就很尴尬,Android开发中常见的一些问题面试专题

if (type) {
pictureBlock2dMap[dstPoint.x][dstPoint.y]!!.left = value.toInt();
} else {
pictureBlock2dMap[dstPoint.x][dstPoint.y]!!.top = value.toInt();
}
invalidate()
}
});
animatorSet.start()
}

判断完成

比如最后移动成了这个样子,此时在向左滑动即可拼图完成,那么该如何判断呢?

image.png

这时候二维数组保存的postion就体现出作用了,我们只需要判断顺序是不是123456789就可以了。

如果二维数组中不会判断,那么这样来,现在有一个集合,集合中是1-9的数组,那么如何判断顺序是不是123456789呢?

办法有很多,比如转成字符串,和"123456789"比较,还有一种办法是比较差,就像下面这样,因为如果是顺序的话,每相邻的两个差必定是1。

private fun List.isOrder(): Boolean {
for (i in 1 until this.size) {
if (this[i] - this[i - 1] != 1) {
return false
}
}
return true;
}

完整代码

当然还有些细节没提到,可在以下代码啊中查看,比如在长按后,显示原图,

录屏_选择区域_20210515105356.gif

package com.example.kotlindemo

import android.animation.Animator
import android.animation.Animator.AnimatorListener
import android.animation.AnimatorSet
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.*
import android.os.Handler
import android.util.AttributeSet
import android.util.Log
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View
import android.view.animation.*
import android.view.animation.Interpolator
import android.widget.Toast
import kotlin.math.min
import kotlin.random.Random

class JigsawView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr), GestureDetector.OnGestureListener {

private var TAG = “TAG”;

//表格大小
private var tableSize = 3;

//二维数组,存放图标块
private val pictureBlock2dMap = Array(tableSize) { Array<PictureBlock?>(tableSize) { null } }

//手势监听
private var gestureDetector: GestureDetector = GestureDetector(context, this);

//是否开始
private var isStart: Boolean = false;

//空白点坐标
private var moveBlockPoint: Point = Point(-1, -1);

//top偏移
private var offsetTop: Int = 0;

//图片大小
private var gridItemSize = 0;
private var slideAnimatorDuration: Long = 150;
private var showSourceBitmap = false;
//移动步数
private var step: Int = 0;

private var itemMovInterpolator:Interpolator=OvershootInterpolator()
//目标Bitmap
private lateinit var targetPicture: Bitmap;

fun setPicture(bitmap: Bitmap) {
post {
targetPicture = bitmap.getCenterBitmap();
parsePicture();
step = 0;
}
}

//分割图片
private fun parsePicture() {
var top = 0;
var left = 0;
var postion = 0;
for (i in pictureBlock2dMap.indices) {
for (j in pictureBlock2dMap[i].indices) {
postion++;
left = j * gridItemSize;
top = i * gridItemSize;
pictureBlock2dMap[i][j] =
PictureBlock(
createBitmap(left, top, gridItemSize),
postion,
left,
top
)
}
}
pictureBlock2dMap[tableSize - 1][tableSize - 1]!!.bitmap = createSolidColorBitmap(width)
isStart = true;
randomPostion();
invalidate()

}

private fun randomPostion() {
for (i in 1…pictureBlock2dMap.size * pictureBlock2dMap.size) {
var srcIndex = Random.nextInt(0, pictureBlock2dMap.size);
var dstIndex = Random.nextInt(0, pictureBlock2dMap.size);
var srcIndex1 = Random.nextInt(0, pictureBlock2dMap.size);
var dstIndex2 = Random.nextInt(0, pictureBlock2dMap.size);
pictureBlock2dMap[srcIndex][dstIndex]!!.swap(pictureBlock2dMap[srcIndex1][dstIndex2]!!);
}

for (i in pictureBlock2dMap.indices) {
for (j in pictureBlock2dMap[i].indices) {
var item = pictureBlock2dMap[i][j]!!;
if (item.postion == tableSize * tableSize) {
moveBlockPoint.set(i, j)
return
}
}
}
}

override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
offsetTop = (h - w) / 2;
gridItemSize = w / tableSize;
}

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
var min = min(widthMeasureSpec, heightMeasureSpec)
setMeasuredDimension(min, min)
}

override fun onDraw(canvas: Canvas) {
if (!isStart) {
return
}
if (showSourceBitmap) {
var pictureRect = Rect(0, 0, targetPicture.width, targetPicture.height);
var rect = Rect(0, 0, measuredWidth, measuredHeight);
canvas.drawBitmap(targetPicture, pictureRect, rect, Paint())
return
}
var left: Int = 0;
var top: Int = 0;
for (i in pictureBlock2dMap.indices) {
for (j in pictureBlock2dMap[i].indices) {
var item = pictureBlock2dMap[i][j]!!;
left = item.left;
top = item.top;
var bitmap = pictureBlock2dMap[i][j]!!.bitmap;
var pictureRect = Rect(0, 0, bitmap.width, bitmap.height);
var rect = Rect(left, top + offsetTop, gridItemSize + left, gridItemSize + top + offsetTop);
canvas.drawBitmap(bitmap, pictureRect, rect, Paint())
}
}

}

//交换内容
private fun PictureBlock.swap(target: PictureBlock) {
target.postion = this.postion.also {
this.postion = target.postion;
}
target.bitmap = this.bitmap.also {
this.bitmap = target.bitmap;
}
}

fun Bitmap.getCenterBitmap(): Bitmap {
//如果图片宽度大于View宽度
var min = min(this.height, this.width)
if (min >= measuredWidth) {
val matrix = Matrix()
val sx: Float = measuredWidth / min.toFloat()
matrix.setScale(sx, sx)
return Bitmap.createBitmap(
this, 0, (this.height * sx - measuredHeight / 2).toInt(),
this.width,
this.width,
matrix,
true
)
}
return this;
}

fun setTarget(targetPicture: Bitmap) {
this.targetPicture = targetPicture;
}

private fun createSolidColorBitmap(size: Int): Bitmap {
var bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888)
bitmap.eraseColor(Color.TRANSPARENT)
return bitmap;
}

private fun createBitmap(left: Int, top: Int, size: Int): Bitmap {
return Bitmap.createBitmap(targetPicture, left, top, size, size)
}

private fun List.isOrder(): Boolean {
for (i in 1 until this.size) {
if (this[i] - this[i - 1] != 1) {
return false
}
}
return true;
}

private fun isFinish() {
var list = mutableListOf();
for (i in pictureBlock2dMap.indices) {
for (j in pictureBlock2dMap[i].indices) {
var item = pictureBlock2dMap[i][j]!!;
list.add(item.postion)
}
}
if (list.isOrder()) {
finish()
}
}

private fun finish() {
Toast.makeText(context, “”, Toast.LENGTH_SHORT).show()
}

private fun startAnimator(
start: Int,
end: Int,
srcPoint: Point,
dstPoint: Point,
type: Boolean
) {
val handler = object : AnimatorListener {
override fun onAnimationRepeat(animation: Animator?) {
}

override fun onAnimationEnd(animation: Animator?) {
pictureBlock2dMap[dstPoint.x][dstPoint.y] =
pictureBlock2dMap[srcPoint.x][srcPoint.y].also {
pictureBlock2dMap[srcPoint.x][srcPoint.y] =
pictureBlock2dMap[dstPoint.x][dstPoint.y]!!;
}
invalidate()
isFinish()

}

override fun onAnimationCancel(animation: Animator?) {
}

override fun onAnimationStart(animation: Animator?) {
}

}
var animatorSet = AnimatorSet()
animatorSet.addListener(handler)
animatorSet.playTogether(ValueAnimator.ofFloat(start.toFloat(), end.toFloat()).apply {
duration = slideAnimatorDuration
interpolator=itemMovInterpolator
addUpdateListener { animation ->
var value = animation.animatedValue as Float
if (type) {
pictureBlock2dMap[srcPoint.x][srcPoint.y]!!.left = value.toInt();
} else {
pictureBlock2dMap[srcPoint.x][srcPoint.y]!!.top = value.toInt();

}
invalidate()
}
}, ValueAnimator.ofFloat(end.toFloat(), start.toFloat()).apply {
duration = slideAnimatorDuration
interpolator=itemMovInterpolator
addUpdateListener { animation ->
var value = animation.animatedValue as Float
if (type) {
pictureBlock2dMap[dstPoint.x][dstPoint.y]!!.left = value.toInt();
} else {
pictureBlock2dMap[dstPoint.x][dstPoint.y]!!.top = value.toInt();

}
invalidate()
}
});
animatorSet.start()

}

private fun doMoveTopBottom(direction: Boolean) {
if ((moveBlockPoint.x == 0 && direction) || (moveBlockPoint.x == tableSize - 1 && !direction)) {
return;
}
step++;
var value = if (direction) 1 else {
-1
}

var start = moveBlockPoint.x * gridItemSize;
var end = (moveBlockPoint.x - (value)) * gridItemSize

startAnimator(
start, end, Point(moveBlockPoint.x, moveBlockPoint.y),
Point(moveBlockPoint.x - (value), moveBlockPoint.y),
false
)
moveBlockPoint.x = moveBlockPoint.x - (value);

}

private fun doMoveLeftRight(direction: Boolean) {
if ((moveBlockPoint.y == 0 && direction) || (moveBlockPoint.y == tableSize - 1 && !direction)) {
return;
}
step++
var value = if (direction) 1 else {
-1
}

var start = moveBlockPoint.y * gridItemSize;
var end = (moveBlockPoint.y - (value)) * gridItemSize

startAnimator(
start, end, Point(moveBlockPoint.x, moveBlockPoint.y),
Point(moveBlockPoint.x, moveBlockPoint.y - (value)),
true
)

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的24套腾讯、字节跳动、阿里、百度2020-2021面试真题解析,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节

还有 高级架构技术进阶脑图、Android开发面试专题资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

一线互联网面试专题

379页的Android进阶知识大全

379页的Android进阶知识大全

点击:

Android架构视频+BAT面试专题PDF+学习笔记》即可免费获取~

腾讯、字节跳动、阿里、百度2020-2021面试真题解析*,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节

还有 高级架构技术进阶脑图、Android开发面试专题资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

[外链图片转存中…(img-fScAsGsf-1711189221592)]

[外链图片转存中…(img-WpaEDOAs-1711189221593)]

[外链图片转存中…(img-zrJ63icn-1711189221593)]

点击:

Android架构视频+BAT面试专题PDF+学习笔记》即可免费获取~

网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值