import javafx.animation.AnimationTimer import javafx.collections.FXCollections import javafx.scene.paint.Color import javafx.scene.shape.Rectangle import tornadofx.* import java.lang.Thread.sleep class 選擇排序 : App(選擇排序V::class) class 選擇排序V : View("learn 選擇排序") { // 每一個矩形寬度 val w = 10.0 // 100個矩形容器 val rec = FXCollections.observableArrayList<Rectangle>() // 動畫計時器 val aniTimer =AniTimer() val result = stringProperty() val swapNum = stringProperty() val N = 100 val randomBound = 400 val data0 = SelectionSortData(N, randomBound) val delay0 = 1L override val root = borderpane { top = vbox(5) { result.value = "result:${data0.numbers.toString()}" label(result) { isWrapText = true } label(swapNum) hbox(5) { button("run").action { // aniTimer.start() run { aniTimer.start() } } button("stop").action { aniTimer.stop() } } } center = group { (1..N).forEach { val r = rectangle(w * it, 200.0, w - 2, data0.numbers[N - it]) { fill = Color.GRAY } rec.add(r) } rotate = 180.0 } prefHeight = 800.0 prefWidth = 1000.0 } fun paint() { setData(0, -1, -1) for (i in data0.numbers.indices) { var minIndex = i rec[minIndex].fill = Color.INDIGO setData(i, -1, minIndex) var j = i + 1 if (j < data0.N()) { (j..data0.N()).map { setData(i, j, minIndex) if (data0.get(j) > data0.get(minIndex)) { rec[j].fill = Color.LIGHTBLUE rec[minIndex].fill = Color.LIGHTBLUE swapNum.value = "當前比較的數:j:${j}:${data0.get(j)} -- ${data0.orderedIndex} -- ${j}:${data0.get(j)}--${minIndex}:${data0.get( minIndex )}" minIndex = j rec[minIndex].fill = Color.INDIGO setData(i, j, minIndex) } } } data0.swap(i, minIndex) setData(i+1, -1, -1) rec[i].height=data0.numbers[i].toDouble() rec[minIndex].height=data0.numbers[minIndex].toDouble() sleep(delay0) result.value = "result:${data0.numbers.reversed()}" } setData(data0.N(), -1, -1) } fun setData(orderedIndex: Int, currentCompareIndex: Int, currentMinIndex: Int) { data0.orderedIndex = orderedIndex data0.currentCompareIndex = currentCompareIndex data0.currentMinIndex = currentMinIndex // if(orderedIndex in (0..N-1)) { // (orderedIndex..N-1).map{ // rec[it].fill = Color.RED // } // } // if(currentCompareIndex in (0..N-1)) { // rec[currentCompareIndex].fill = Color.LIGHTBLUE // } // if(currentMinIndex in (0..N-1)) { // rec[currentMinIndex].fill = Color.INDIGO // } // if (i == data0.currentCompareIndex) rec[i].fill = Color.LIGHTBLUE // if (i == data0.currentMinIndex) rec[i].fill = Color.INDIGO } // 此方法能夠中止動畫 inner class AniTimer: AnimationTimer() { var lastTime = 0L override fun handle(now: Long) { if ((now - lastTime) > 10000000) { lastTime = now } else { return } paint() } } } class SelectionSortData { val numbers = ArrayList<Int>() // [0..orderedIndex)是有序的 var orderedIndex = -1 // 當前找到的最小元素的索引 var currentMinIndex = -1 // 當前正在比較的元素的索引 var currentCompareIndex = -1 constructor(N: Int, randomBound: Int) { (1..N).map { numbers.add((1..randomBound).random()) } } fun N() = numbers.size fun get(i: Int) = numbers[i] fun swap(i: Int, j: Int) { val t = numbers[i] numbers[i] = numbers[j] numbers[j] = t } }