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/.gitignore | 1 + app/build.gradle | 34 +++++++ app/proguard-rules.pro | 21 ++++ 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 ++ app/src/test/java/space/jakob/mines/GridTest.kt | 17 ++++ 21 files changed, 371 insertions(+) create mode 100644 app/.gitignore create mode 100644 app/build.gradle create mode 100644 app/proguard-rules.pro 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 create mode 100644 app/src/test/java/space/jakob/mines/GridTest.kt (limited to 'app') diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..6cf711a --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,34 @@ +apply plugin: 'com.android.application' + +apply plugin: 'kotlin-android' + +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 28 + defaultConfig { + applicationId "space.jakob.mines" + minSdkVersion 15 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + implementation 'com.android.support:design:28.0.0' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile 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 @@ + + + + +