Skip to content

Instantly share code, notes, and snippets.

@Opposite34
Last active January 16, 2022 15:58
Show Gist options
  • Select an option

  • Save Opposite34/647d8cf1be8349e355132b3226a7793a to your computer and use it in GitHub Desktop.

Select an option

Save Opposite34/647d8cf1be8349e355132b3226a7793a to your computer and use it in GitHub Desktop.
a (messy) implementation of cli-based minesweeper in kotlin
import kotlin.random.Random
fun main() {
var value = 0
print("width: ")
val w = readNum()
print("height: ")
val h = readNum()
val playDim = listOf(w, h)
if(invalidSize(playDim)) {
print("Please enter valid width and height")
System.exit(-1)
}
//init minefield of w,h size with 20% chance for each tile to have a mine/bomb
val m = Mine(w, h, 20)
val size = w*h;
val notBomb = size - m.bombNum
println("-----------")
//START OF GAME LOOP
while (true) {
m.print()
println()
print("row: ")
val row = readNum()
print("column: ")
val col = readNum()
if(invalidSize(listOf(row, col), max = playDim)) {
println("Please enter valid row and column")
}
else {
value = m.open(col-1, row-1)
}
if(value == -1) {
println("You Lose!")
break;
}
else if(m.getOpenNum() >= notBomb) {
println("You Win!")
break;
}
}
//END OF GAME LOOP
println("-----------")
m.printMine()
}
//handles input into number
fun readNum(): Int {
try {
return (readLine() ?: "-1").toInt()
}
catch(e: NumberFormatException) {
return -1
}
}
//check if the dimension (the coord value) is valid
fun invalidSize(dim: List<Int>, min: Int = 0, max: List<Int> = listOf()): Boolean {
val lessThanMin: Boolean = (dim[0] <= min || dim[1] <= min)
if(max.size > 0) {
return (dim[0] > max[0] || dim[1] > max[1] || lessThanMin)
}
return lessThanMin
}
fun percentToBool(n: Int, percent: Int): Boolean {
return if(n<percent) true else false
}
class Mine(val width: Int, val height: Int, val bombPercent: Int) {
val mineList = List<List<Boolean>>(height) {this.makeLine(bombPercent)}
val opened = mutableListOf<List<Int>>()
val bombNum = countBomb()
fun makeLine(percent: Int): List<Boolean> {
val mineLine = List<Boolean>(this.width) {percentToBool(Random.nextInt(0,101), percent)}
return mineLine
}
// basically pushing and return the value
fun open(x: Int, y: Int): Int {
val coord = listOf(x, y)
if(!(coord in this.opened)) this.opened.add(coord)
return getCount(x,y)
}
// get the mine/bomb count around that tile (warning: nested loop)
fun getCount(x: Int, y: Int): Int {
var count = 0
if(getVal(x,y)) return -1
for(i in -1..1) {
for(j in -1..1) {
if(x+i in 0..this.width-1 && y+j in 0..this.height-1) {
if(getVal(x+i, y+j)) count++
}
}
}
return count
}
fun getVal(x: Int, y: Int): Boolean {return this.mineList[y][x]}
//for checking in game loop if all non mines/bombs has been opened
fun getOpenNum(): Int {
return this.opened.size
}
fun countBomb(): Int {
var count = 0
for(line in mineList) {
line.forEach {
if(it) count++
}
}
return count
}
//print functions, quite messy
fun print() {
for(y in 0..this.height-1) {
for(x in 0..this.width-1) {
if(listOf(x,y) in this.opened) {
val count = this.getCount(x,y)
if(count == -1) print("x") else print(count)
}
else print("=")
print(" ")
}
println()
}
}
fun printMine() {
for(line in this.mineList) {
line.forEach {
if(it) print("x") else print("o")
print(" ")
}
println()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment