package com.cyy.game.pingtu
import javafx.application.Application
import javafx.beans.property.SimpleObjectProperty
import javafx.event.EventHandler
import javafx.geometry.Pos
import javafx.geometry.Rectangle2D
import javafx.scene.control.Alert
import javafx.scene.control.RadioButton
import javafx.scene.image.Image
import javafx.scene.image.ImageView
import javafx.scene.input.MouseEvent
import javafx.scene.layout.GridPane
import javafx.scene.layout.VBox
import javafx.stage.FileChooser
import tornadofx.*
import java.io.File
import java.util.*
import kotlin.math.sqrt
fun main(args: Array<String>) = Application.launch(PingTuApp::class.java, *args)
class PingTuApp : App(PingTuView::class)
class PingTuView : View("拼图") {
var N = intProperty(4)
var n = random(N.value - 1) //自定义的函数,产生逆序数为偶数的不重复数组
var m = findnum(n) //找出那个不在随机数组里面的数字
var imageViews = (1..N.value).map { ImageView() }.toTypedArray()
// 大图片路径
val imgPath = stringProperty("pingtu/1.png")
// 空图片路径
val imgBlankPath = "pingtu/2.png"
lateinit var rbox: VBox
lateinit var gridPane: GridPane
lateinit var bigImageView: ImageView
lateinit var smallImageView: ImageView
val bigImage = SimpleObjectProperty<Image>()
val smallImage = SimpleObjectProperty<Image>()
// 大图片宽度
val imageSize = 300.0
// 每个小方格宽度
var smallSize = imageSize / sqrt(N.value.toDouble())
override val root = borderpane {
paddingAll = 10
prefHeight = 700.0
prefWidth = 1000.0
primaryStage.isResizable = false
top = hbox(10) {
alignment=Pos.CENTER
button("选择图片") {
action {
val imgType = listOf("*.jpg", "*.png", "*.bmp", "*.gif")
val efset = arrayOf(FileChooser.ExtensionFilter("$imgType", imgType))
val imgFile = chooseFile("选择图片", efset, FileChooserMode.Single) {
// p初始目录为当前项目目录
initialDirectory = File(File("").canonicalPath)
}
if (imgFile.isNotEmpty()) {
val imgPath = imgFile.first().toString().replace("\\", "/")
bigImage.value = Image(File(imgPath).inputStream())
imageViews=initImageViews1(N.value, imgPath)
initView(N.value, imgPath, smallSize,imageViews)
}
}
}
togglegroup {
listOf(4,9, 16, 25).map { v ->
radiobutton(v.toString(), this, v) { if (v === 4) isSelected = true }
}
selectedToggleProperty().addListener { _, _, _ ->
N.value = (selectedToggle as RadioButton).text.toInt()
smallSize = imageSize / sqrt(N.value.toDouble())
}
}
button("重置") {
action {
bigImage.value = Image(imgPath.value)
imageViews =initImageViews(N.value,imgPath.value)
initView(N.value, imgPath.value, smallSize,imageViews)
}
}
paddingAll = 10
}
center = gridpane {
alignment=Pos.CENTER
gridPane = this
isGridLinesVisible = true
}
right = vbox(20) {
alignment=Pos.CENTER
rbox = this
//显示空格子的图片
imageview(smallImage) {
smallImageView = this
}
//完整的大图
imageview(bigImage) {
bigImageView = this
fitHeight = imageSize
fitWidth = imageSize
}
}
}
inner class Myevent : EventHandler<MouseEvent> { //点击事件的实现
override fun handle(arg0: MouseEvent) {
val img = arg0.source as ImageView
val sx = img.layoutX
val sy = img.layoutY
val dispx = sx - imageViews[m].layoutX
val dispy = sy - imageViews[m].layoutY
if (dispx == -smallSize && dispy == 0.0) { //点击的空格左边的格子
swapimg(img, imageViews[m]) //交换imageView
if (issucc(imageViews)) { //判断是否拼成功
val alert = Alert(Alert.AlertType.WARNING, "成功!")
alert.show()
}
} else if (dispx == 0.0 && dispy == -smallSize) { //上面的格子
swapimg(img, imageViews[m])
if (issucc(imageViews)) {
val alert = Alert(Alert.AlertType.WARNING, "成功!")
alert.show()
}
} else if (dispx == smallSize && dispy == 0.0) { //右边的格子
swapimg(img, imageViews[m])
if (issucc(imageViews)) {
val alert = Alert(Alert.AlertType.WARNING, "成功!")
alert.show()
}
} else if (dispx == 0.0 && dispy == smallSize) { //下面的格子
swapimg(img, imageViews[m])
if (issucc(imageViews)) {
val alert = Alert(Alert.AlertType.WARNING, "成功!")
alert.show()
}
}
}
fun swapimg(i1: ImageView, i2: ImageView) { //交换两个imageView的实现
val row1 = GridPane.getRowIndex(i1)
val colu1 = GridPane.getColumnIndex(i1)
val row2 = GridPane.getRowIndex(i2)
val colu2 = GridPane.getColumnIndex(i2)
GridPane.setRowIndex(i1, row2)
GridPane.setColumnIndex(i1, colu2)
GridPane.setRowIndex(i2, row1)
GridPane.setColumnIndex(i2, colu1)
}
}
init {
imageViews =initImageViews(N.value,imgPath.value)
initView(N.value, imgPath.value, smallSize,imageViews)
}
// nn : 9,16,25
fun initView(nn: Int, imgPath: String, smallSize: Double,imageViews:Array<ImageView>) {
n = random(nn) //自定义的函数,产生逆序数为偶数的不重复数组
m = findnum(n) //找出那个不在随机数组里面的数字
gridPane.clear()
// nn1 =3,4,5
val nn1 = sqrt(nn.toDouble()).toInt()
var i = 0
var k = 0
while (i <= nn1 - 1) {
var j = 0
while (j <= nn1 - 1) {
//切割图片
imageViews[k].viewport = Rectangle2D(smallSize * j, smallSize * i, smallSize, smallSize)
++j
++k
}
++i
}
// nn1-1=2,3,4
var t = 0
(0 until nn1).forEach { r ->
(0 until nn1).forEach { c ->
if (t < nn - 1) {
gridPane.add(imageViews[n[t]], c, r)
}
++t
}
}
smallImage.value = imageViews[m].image
smallImageView.viewport = imageViews[m].viewport
imageViews[m].image = Image(imgBlankPath) //2.png为一个透明图,放在空格子中
gridPane.add(imageViews[m], nn1 - 1, nn1 - 1)
}
//读取类路径下的图片
fun initImageViews(nn: Int, imgPath: String):Array<ImageView>{
return (1..nn).map {
imageview(imgPath) {
onMouseClicked = Myevent()
}
}.toTypedArray()
}
//读取电脑文件系统中图片文件的路径
fun initImageViews1(nn: Int, imgPath: String):Array<ImageView>{
return (1..nn).map {
imageview(Image(File(imgPath).inputStream())) {
onMouseClicked = Myevent()
}
}.toTypedArray()
}
//判断是否拼成功
fun issucc(imageViews: Array<ImageView>): Boolean {
val t = imageViews.size
imageViews.indices.forEach { i ->
if (i != sqrt(t.toDouble()).toInt() * GridPane.getRowIndex(imageViews[i]) + GridPane.getColumnIndex(imageViews[i])) {
return false
}
}
return true
}
fun findnum(n: IntArray): Int {
(n.indices).forEach { j ->
if (j in n) {
} else {
return j
}
}
return -1
}
//生成nn个不重复的逆序数为偶数的数字
fun random(nn: Int): IntArray {
var ran = IntArray(nn)
while (!iso(ran)) {
ran = random_num(nn)
}
return ran
}
//生成nn个不重复数
fun random_num(nn: Int): IntArray {
val r = IntArray(nn)
val random = Random()
var i = 0
while (i < nn - 1) {
r[i] = random.nextInt(nn)
for (j in 0 until i) {
while (r[i] == r[j]) {
i--
break
}
}
++i
}
return r
}
//判断逆序数是否为偶数
fun iso(num: IntArray): Boolean {
var sum = 0
val t = num.size
for (i in 0..t - 2) {
for (j in i..t - 1) {
if (num[i] > num[j]) {
sum++
}
}
}
return sum % 2 == 0 && sum != 0
}
}