最近看见了围住神经猫这个游戏,刚好极客学院又有这个游戏的教学视频,就准备跟着视频撸一遍,但是干撸不过瘾,所以打算用kotlin撸了一遍,游戏的原理我就不做过多赘述了,网上已经一搜一大把了。直接贴出代码了
package com.yking.catchcrazycat
import android.content.Context
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.util.Log
import android.view.MotionEvent
import android.view.SurfaceHolder
import android.view.SurfaceView
import android.view.View
import android.widget.Toast
import java.util.*
import kotlin.collections.HashMap
/**
* Created by on 2018/8/28.YaoKai
*/
class PlayGround constructor(
context: Context
) : SurfaceView(context), SurfaceHolder.Callback, View.OnTouchListener {
companion object {
private const val COL: Int = 10
private const val ROW: Int = 10
private const val BLOCKS: Int = 15//初始障碍物个数
private var WIDTH: Int = 40//每个圆圈的默认宽度
}
private var martix = Array(COL) { arrayOfNulls<Dot>(ROW) }
private var cat: Dot? = null
init {
holder.addCallback(this)
//加载数据源
for ((i, arrayRow) in martix.withIndex()) {
for (j in 0..(COL - 1)) {
arrayRow[j] = Dot(j, i)
}
}
setOnTouchListener(this)
initGame()
}
/**
* 初始化游戏
*/
private fun initGame() {
for (arrayRow in martix) for (dot in arrayRow) dot?.let {
it.status = Dot.STATUS_OFF
}
cat = Dot(4, 5)
getDot(4, 5)?.status = Dot.STATUS_IN
for (i in 1..BLOCKS) {
val x: Int = ((Math.random() * 1000) % COL).toInt()
val y: Int = ((Math.random() * 1000) % ROW).toInt()
if (getDot(x, y)?.status == Dot.STATUS_OFF) {
getDot(x, y)?.status = Dot.STATUS_ON
Log.e("BLOCKS", "x:$x y:$y")
}
}
}
private fun getDot(i: Int, i1: Int): Dot? {
return martix[i1][i]
}
/**
* 判断是否为边界
*/
private fun isAtEdge(dot: Dot): Boolean {
if (dot.x * dot.y == 0 || dot.x + 1 == COL || dot.y + 1 == ROW) {
return true
}
return false
}
/**
* 获取相邻点位
*/
private fun getNeighbor(dot: Dot, dir: Int): Dot? {
when (dir) {
1 -> {
return getDot(dot.x - 1, dot.y)
}
2 -> {
return if (dot.y % 2 == 0) {
getDot(dot.x - 1, dot.y - 1)
} else {
getDot(dot.x, dot.y - 1)
}
}
3 -> {
return if (dot.y % 2 == 0) {
getDot(dot.x, dot.y - 1)
} else {
getDot(dot.x + 1, dot.y - 1)
}
}
4 -> {
return getDot(dot.x + 1, dot.y)
}
5 -> {
return if (dot.y % 2 == 0) {
getDot(dot.x, dot.y + 1)
} else {
getDot(dot.x + 1, dot.y + 1)
}
}
6 -> {
return if (dot.y % 2 == 0) {
getDot(dot.x - 1, dot.y + 1)
} else {
getDot(dot.x, dot.y + 1)
}
}
}
return null
}
/**
* 获取距离
*/
private fun getDistance(dot: Dot, dir: Int): Int {
var distance = 0
var ori: Dot = dot
var next: Dot?
if (isAtEdge(dot)) {
return 1
}
while (true) {
next = getNeighbor(ori, dir)
if (next!!.status == Dot.STATUS_ON) {
return -distance
}
if (isAtEdge(next)) {
distance++
return distance
}
distance++
ori = next
}
}
/**
* 移动点位到新点
*/
private fun moveTo(dot: Dot) {
getDot(cat!!.x, cat!!.y)!!.status = Dot.STATUS_OFF
dot.status = Dot.STATUS_IN
cat!!.x = dot.x
cat!!.y = dot.y
}
/**
* 移动方法
*/
private fun move() {
if (isAtEdge(cat!!)) {
lose()
return
}
val avaliable = Vector<Dot>()
val positive = Vector<Dot>()
val al = HashMap<Dot, Int>()
for (i in 1..6) {
val neighbor = getNeighbor(cat!!, i)
if (neighbor!!.status == Dot.STATUS_OFF) {
avaliable.add(neighbor)
al.put(neighbor, i)
if (getDistance(neighbor, i) > 0) {
positive.add(neighbor)
}
}
}
when {
avaliable.size == 0 -> win()
avaliable.size == 1 -> moveTo(avaliable[0])
else -> {
var best: Dot? = null
if (positive.size == 0) {
var max = 0
(0 until avaliable.size).forEach { i ->
val distance = getDistance(cat!!, al[avaliable[i]]!!)
if (distance < max) {
max = distance
best = avaliable[i]
}
}
} else {
var min = 999
for (i in 0 until positive.size) {
val distance = getDistance(positive[i], al[positive[i]]!!)
if (distance < min) {
min = distance
best = positive[i]
}
}
}
moveTo(best!!)
}
}
}
private fun lose() {
Toast.makeText(context, "Lose", Toast.LENGTH_SHORT).show()
}
private fun win() {
Toast.makeText(context, "You Win!", Toast.LENGTH_SHORT).show()
}
override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) {
WIDTH = width / (COL + 1)
reDraw()
}
override fun surfaceDestroyed(holder: SurfaceHolder?) {
}
override fun surfaceCreated(holder: SurfaceHolder?) {
reDraw()
}
private fun reDraw() {
val canvas = holder.lockCanvas()
canvas.drawColor(Color.LTGRAY)
val paint = Paint(Paint.ANTI_ALIAS_FLAG)
for (i in 0 until ROW) {
var offset = 0
if (i % 2 != 0) {
offset = WIDTH / 2
}
for (j in 0 until COL) {
val dot = getDot(j, i)
when (dot!!.status) {
Dot.STATUS_ON -> {
paint.color = 0xFFFFAA00.toInt()
}
Dot.STATUS_OFF -> {
paint.color = 0xFFEEEEEE.toInt()
}
Dot.STATUS_IN -> {
paint.color = 0xFFFF0000.toInt()
}
}
canvas.drawOval(RectF(
(dot.x * WIDTH + offset).toFloat(),
(dot.y * WIDTH).toFloat(),
((dot.x + 1) * WIDTH + offset).toFloat(),
((dot.y + 1) * WIDTH).toFloat()
), paint)
}
}
holder.unlockCanvasAndPost(canvas)
}
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
if (event!!.action == MotionEvent.ACTION_UP) {
val x: Int
val y: Int = (event.y / WIDTH).toInt()
x = if (y % 2 == 0) {
(event.x / WIDTH).toInt()
} else {
((event.x - WIDTH / 2) / WIDTH).toInt()
}
when {
x > COL + 1 || y > ROW + 1 -> initGame()
getDot(x, y)!!.status == Dot.STATUS_OFF -> {
getDot(x, y)!!.status = Dot.STATUS_ON
move()
}
}
reDraw()
}
return true
}
}
这是游戏的核心代码,不得不说kotlin真的是十分简洁啊
原谅我如此懒惰