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 } }