Merge pull request #767 from Gryzor/add_32_diamonds_kotlin

Add Kotlin port of 32_Diamonds
This commit is contained in:
Jeff Atwood
2022-06-27 16:40:27 -05:00
committed by GitHub
2 changed files with 164 additions and 1 deletions

View File

@@ -1,3 +1,12 @@
Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html)
Conversion to [Kotlin](https://kotlinlang.org/)
Conversion to [Kotlin](https://kotlinlang.org/), structure inspired from [the Java port](https://github.com/coding-horror/basic-computer-games/blob/main/32_Diamond/java/Diamond.java).
### How to Run
1. Install [kotlin command line](https://kotlinlang.org/docs/command-line.html) compiler from JetBrains.
2. Compile with `kotlinc diamond.kt -include-runtime -d diamond.jar`
3. Run with `java -jar diamond.jar`
### Changes from Original
This version validates that user input is correct.

View File

@@ -0,0 +1,154 @@
/**
* Game of Diamond
* <p>
* Based on the BASIC game of Diamond
* https://github.com/coding-horror/basic-computer-games/blob/main/32%20Diamond/diamond.bas
* <p>
*
* Changes From Original: Input is validated.
*
* Converted from BASIC to Kotlin by Martin Marconcini (@Gryzor)
* Inspired in the Java code written by Darren Cardenas.
*/
fun main() {
Diamond().startGame()
}
class Diamond {
init {
printIntro()
}
fun startGame() {
var body: Int
var end: Int
var start: Int = 1
var row: Int = 1
var numPerRow: Int
var increment: Int = 2
var lineContent: String
var prefixIndex: Int
printPrompt()
// Read the user input
val input = readLine()
// Validate input
val userInput: Int = try {
input?.toInt() ?: -1
} catch (e: NumberFormatException) {
-1
}
if (!isValid(userInput)) {
printInvalidInput()
return
}
// Calculate how many diamonds can horizontally fit in the given space
numPerRow = calculateDiamondsPerRow(userInput)
end = userInput
// Loop throw rows of Diamonds
while (row <= numPerRow) {
body = start
while (canLoop(increment, body, end)) {
lineContent = ""
// Add white spaces to the "left" of the leftmost diamond.
while (lineContent.length < ((userInput - body) / 2)) {
lineContent += " "
}
// Begin loop through each column of diamonds
for (col in 1..numPerRow) {
prefixIndex = 1
// Begin loop that fills each diamond with characters (not whitespace)
for (fill in 1..body) {
// Right side of diamond, if the index is greater than the prefix, put a Symbol.
if (prefixIndex > PREFIX.length) {
lineContent += SYMBOL
}
// Left side of diamond, pick a Prefix character (-1 since it starts at 0)
else {
lineContent += PREFIX[prefixIndex - 1]
prefixIndex++
}
}// End loop that fills each diamond with characters
// Is Column finished?
if (col == numPerRow) {
break
}
// Column is not finished...
else {
// Add whitespace on the "right" side of the current diamond, and fill the "left" side of the
// next; doesn't fill the space to the right of the rightmost diamond.
while (lineContent.length < (userInput * col + (userInput - body) / 2)) {
lineContent += " "
}
}
}// End loop through each column of diamonds
// Print the current Line
println(lineContent)
// Increment the body that moves
body += increment
} //end While Loop throw rows of Diamonds
// Increment the current Row of diamonds.
row++
if (start != 1) {
start = 1
end = userInput
increment = 2
} else {
// We're rendering the "bottom half" of the total rendering.
// Alter the parameters, and decrease the row number so the logic can loop again.
start = userInput - 2
end = 1
increment = -2
row--
}
} // End loop through each row of diamonds
}
private fun canLoop(increment: Int, body: Int, end: Int): Boolean = if (increment < 0) body >= end else body <= end
private fun calculateDiamondsPerRow(totalDiamonds: Int): Int = LINE_WIDTH / totalDiamonds
private fun isValid(input: Int): Boolean = (input in 5..21) && (input % 2 != 0)
private fun printInvalidInput() = println("Invalid input")
private fun printPrompt() {
println(
"""
FOR A PRETTY DIAMOND PATTERN
TYPE IN AN ODD NUMBER BETWEEN 5 AND 21?
""".trimIndent()
)
println()
}
private fun printIntro() {
println(" ".repeat(32) + "DIAMOND")
println(" ".repeat(14) + "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY")
println()
println()
}
companion object {
const val LINE_WIDTH = 60
const val PREFIX = "CC"
const val SYMBOL = "!"
}
}