From 15b4a3158bbb501aef542cba3bf1e429d2d594b1 Mon Sep 17 00:00:00 2001 From: "Jakob L. Kreuze" Date: Sat, 15 Dec 2018 09:21:53 -0500 Subject: Turn into proper Android project. --- app/src/main/AndroidManifest.xml | 21 ++++ .../main/java/space/jakob/mines/GameActivity.kt | 11 ++ app/src/main/java/space/jakob/mines/GameView.kt | 21 ++++ app/src/main/java/space/jakob/mines/Grid.kt | 113 +++++++++++++++++++++ .../main/java/space/jakob/mines/SetupActivity.kt | 18 ++++ app/src/main/res/drawable/atlas.png | Bin 0 -> 13629 bytes app/src/main/res/layout/activity_game.xml | 6 ++ app/src/main/res/layout/activity_setup.xml | 82 +++++++++++++++ app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 1631 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1110 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 2036 bytes app/src/main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 3106 bytes app/src/main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 4137 bytes app/src/main/res/values/colors.xml | 6 ++ app/src/main/res/values/dimens.xml | 5 + app/src/main/res/values/strings.xml | 4 + app/src/main/res/values/styles.xml | 11 ++ 17 files changed, 298 insertions(+) create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/java/space/jakob/mines/GameActivity.kt create mode 100644 app/src/main/java/space/jakob/mines/GameView.kt create mode 100644 app/src/main/java/space/jakob/mines/Grid.kt create mode 100644 app/src/main/java/space/jakob/mines/SetupActivity.kt create mode 100644 app/src/main/res/drawable/atlas.png create mode 100644 app/src/main/res/layout/activity_game.xml create mode 100644 app/src/main/res/layout/activity_setup.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/dimens.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/styles.xml (limited to 'app/src/main') diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..7a4a4d0 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + diff --git a/app/src/main/java/space/jakob/mines/GameActivity.kt b/app/src/main/java/space/jakob/mines/GameActivity.kt new file mode 100644 index 0000000..ad09481 --- /dev/null +++ b/app/src/main/java/space/jakob/mines/GameActivity.kt @@ -0,0 +1,11 @@ +package space.jakob.mines + +import android.support.v7.app.AppCompatActivity +import android.os.Bundle + +class GameActivity : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_game) + } +} diff --git a/app/src/main/java/space/jakob/mines/GameView.kt b/app/src/main/java/space/jakob/mines/GameView.kt new file mode 100644 index 0000000..eed0d9c --- /dev/null +++ b/app/src/main/java/space/jakob/mines/GameView.kt @@ -0,0 +1,21 @@ +package space.jakob.mines + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Paint +import android.util.AttributeSet +import android.view.View + +class GameView(context: Context, attrs: AttributeSet) : View(context, attrs) { + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + + val textPaint = Paint().apply { + textSize = 64f + } + + canvas.apply { + drawText("Hello, world!", 24f, 24f, textPaint) + } + } +} diff --git a/app/src/main/java/space/jakob/mines/Grid.kt b/app/src/main/java/space/jakob/mines/Grid.kt new file mode 100644 index 0000000..a532632 --- /dev/null +++ b/app/src/main/java/space/jakob/mines/Grid.kt @@ -0,0 +1,113 @@ +data class Tile(val adjacentMines: Int = 0, val mine: Boolean = false, val masked: Boolean = true) + +/** + * The Minesweeper "grid", containing instances of [Tile]. + */ +class Grid(val width: Int, val height: Int, val tiles: Array) { + constructor(width: Int = 8, height: Int = 8, mines: Int = 10) + : this(width, height, Array(width * height) { Tile() }) { + for (i in 0 until mines) { + val x = (0 until width).random() + val y = (0 until height).random() + placeMine(x, y) + } + } + + private fun index(x: Int, y: Int) = y * width + x + private fun valid(x: Int, y: Int) = y in 0 until height && x in 0 until width + private fun place(x: Int, y: Int, tile: Tile) { + tiles[index(x, y)] = tile + } + + /** + * Returns the tile at the given coordinates. + * + * @throws IllegalArgumentException if the X coordinate is outside + * the range of [0, width), or if the Y coordinate is outside the + * range of [0, height). + */ + operator fun get(x: Int, y: Int) = if (valid(x, y)) { + tiles[index(x, y)] + } else { + throw IllegalArgumentException("Invalid coordinates (${x}, ${y})") + } + + /** + * Places a mine at the given coordinates. + * + * @throws IllegalArgumentException if the X coordinate is outside + * the range of [0, width), or if the Y coordinate is outside the + * range of [0, height). + */ + fun placeMine(x: Int, y: Int) { + if (!valid(x, y)) { + throw IllegalArgumentException("Invalid coordinates (${x}, ${y})") + } + + if (this[x, y].mine) { + return; + } + + place(x, y, Tile(mine = true)) + + val xMin = (x - 1).coerceAtLeast(0) + val xMax = (x + 1).coerceAtMost(width - 1) + val yMin = (y - 1).coerceAtLeast(0) + val yMax = (y + 1).coerceAtMost(height - 1) + + for (y in yMin..yMax) { + for (x in xMin..xMax) { + with (tiles[index(x, y)]) { + if (!mine) { + place(x, y, copy(adjacentMines + 1)) + } + } + } + } + } + + /** + * Reveals a tile at the given coordinates according to the game rules. + * + * @throws IllegalArgumentException if the X coordinate is outside + * the range of [0, width), or if the Y coordinate is outside the + * range of [0, height). + */ + fun reveal(x: Int, y: Int) { + if (!valid(x, y) || !this[x, y].masked) { + return; + } + + with (this[x, y]) { + place(x, y, copy(masked = false)) + + if (!mine && adjacentMines == 0) { + val xMin = (x - 1).coerceAtLeast(0) + val xMax = (x + 1).coerceAtMost(width - 1) + val yMin = (y - 1).coerceAtLeast(0) + val yMax = (y + 1).coerceAtMost(height - 1) + + for (y in yMin..yMax) { + for (x in xMin..xMax) { + reveal(x, y) + } + } + } + } + } + + override fun toString(): String = buildString { + for (y in 0 until height) { + for (x in 0 until width) { + val tile = this@Grid[x, y] + append(when { + tile.masked -> "." + tile.mine -> "M" + tile.adjacentMines == 0 -> " " + else -> tile.adjacentMines.toString() + } + " ") + } + append("\n") + } + } +} diff --git a/app/src/main/java/space/jakob/mines/SetupActivity.kt b/app/src/main/java/space/jakob/mines/SetupActivity.kt new file mode 100644 index 0000000..e78322e --- /dev/null +++ b/app/src/main/java/space/jakob/mines/SetupActivity.kt @@ -0,0 +1,18 @@ +package space.jakob.mines + +import android.support.v7.app.AppCompatActivity +import android.os.Bundle +import android.widget.Button +import android.content.Intent + +class SetupActivity : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_setup) + + val goButton = findViewById(R.id.goButton) as Button + goButton.setOnClickListener { + startActivity(Intent(this, GameActivity::class.java)) + } + } +} diff --git a/app/src/main/res/drawable/atlas.png b/app/src/main/res/drawable/atlas.png new file mode 100644 index 0000000..b218df9 Binary files /dev/null and b/app/src/main/res/drawable/atlas.png differ diff --git a/app/src/main/res/layout/activity_game.xml b/app/src/main/res/layout/activity_game.xml new file mode 100644 index 0000000..794c96e --- /dev/null +++ b/app/src/main/res/layout/activity_game.xml @@ -0,0 +1,6 @@ + + diff --git a/app/src/main/res/layout/activity_setup.xml b/app/src/main/res/layout/activity_setup.xml new file mode 100644 index 0000000..5e3a4cc --- /dev/null +++ b/app/src/main/res/layout/activity_setup.xml @@ -0,0 +1,82 @@ + + + + +