学生時代では、Java + eclipse環境で、RPGのAndroidアプリを作成した経験がありますが、
最近のAndroidプログラミング言語はKorlin、開発環境はAndroid Studioが主流になっているみたいです。
スマホアプリ作りたくなったので、言語と環境を覚えるために、Kotlinでサンプルの三目並べゲームを作ってみました。
activity_main.xml
赤いエリア → palette。部品を選択するところです。
水色のエリア → Component Tree。画面に設置した部品の関係ツリーを表示します。
緑のエリア → スマホの画面。ここに部品を配置します。
オレンジのエリア → 緑色のエリアで選択している部品のプロパティが表示されます。
今回はTable LayoutにTable Rowを配置してその中にbuttonを配置して、三目並べの形を作りました!
それで、それぞれのbuttonに、onClickイベントがあるので、ここで呼び出すfunction名を書き込むと、
MainActivity.kt側のfunctionを呼び出すことができるようになります。
コードはこちら
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/whiteColorBackground"
android:gravity="center"
tools:context=".MainActivity">
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:layout_marginTop="3px">
<Button
android:id="@+id/bu1"
android:layout_width="40pt"
android:layout_height="40pt"
android:layout_marginLeft="3pt"
android:background="@color/whiteBu"
android:onClick="buClick" />
<Button
android:id="@+id/bu2"
android:layout_width="40pt"
android:layout_height="40pt"
android:layout_marginLeft="3pt"
android:background="@color/whiteBu"
android:onClick="buClick" />
<Button
android:id="@+id/bu3"
android:layout_width="40pt"
android:layout_height="40pt"
android:layout_marginLeft="3pt"
android:background="@color/whiteBu"
android:onClick="buClick" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:layout_marginTop="3px">
<Button
android:id="@+id/bu4"
android:layout_width="40pt"
android:layout_height="40pt"
android:layout_marginLeft="3pt"
android:background="@color/whiteBu"
android:onClick="buClick" />
<Button
android:id="@+id/bu5"
android:layout_width="40pt"
android:layout_height="40pt"
android:layout_marginLeft="3pt"
android:background="@color/whiteBu"
android:onClick="buClick" />
<Button
android:id="@+id/bu6"
android:layout_width="40pt"
android:layout_height="40pt"
android:layout_marginLeft="3pt"
android:background="@color/whiteBu"
android:onClick="buClick" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:layout_marginTop="3px">
<Button
android:id="@+id/bu7"
android:layout_width="40pt"
android:layout_height="40pt"
android:layout_marginLeft="3pt"
android:background="@color/whiteBu"
android:onClick="buClick" />
<Button
android:id="@+id/bu8"
android:layout_width="40pt"
android:layout_height="40pt"
android:layout_marginLeft="3pt"
android:background="@color/whiteBu"
android:onClick="buClick" />
<Button
android:id="@+id/bu9"
android:layout_width="40pt"
android:layout_height="40pt"
android:layout_marginLeft="3pt"
android:background="@color/whiteBu"
android:onClick="buClick" />
</TableRow>
</TableLayout>
colors.xml
先程の、activity_main.xmlでbackgroundに色を指定しているのですが、その色は直接色コードを指定する他に、
名前をつけて定義することもできます。
こちらのほうが変更するときに後々楽なので定義します。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#008577</color>
<color name="colorPrimaryDark">#00574B</color>
<color name="colorAccent">#D81B60</color>
<color name="whiteColorBackground">#D3D3D3</color>
<color name="whiteBu">#F9F9F9</color>
<color name="blue">#FF33B5E5</color>
<color name="darkGreen">#FF669900</color>
</resources>
MainActivity.kt
実行コードです。
ボタンを押されたとき、buClickイベントが実行されてゲームが進みます。
package com.example.tictactoeapp
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Button
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_main.*
import java.util.Random
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
fun buClick(view: View) {
val buSelected = view as Button
var cellId = 0
when(buSelected.id){
R.id.bu1 -> cellId = 1
R.id.bu2 -> cellId = 2
R.id.bu3 -> cellId = 3
R.id.bu4 -> cellId = 4
R.id.bu5 -> cellId = 5
R.id.bu6 -> cellId = 6
R.id.bu7 -> cellId = 7
R.id.bu8 -> cellId = 8
R.id.bu9 -> cellId = 9
}
//Log.d("buClick", buSelected.id.toString())
//Log.d("buClick: cellId", cellId.toString())
playGame(cellId, buSelected)
}
var activityPlayer = 1
var player1 = ArrayList<Int>()
var player2 = ArrayList<Int>()
fun playGame(cellId:Int, buSelected:Button){
if(activityPlayer == 1){
buSelected.text = "X"
buSelected.setBackgroundResource(R.color.blue)
player1.add(cellId)
activityPlayer = 2
autoPlay()
}else{
buSelected.text = "O"
buSelected.setBackgroundResource(R.color.darkGreen)
player2.add(cellId)
activityPlayer = 1
}
buSelected.isEnabled = false
checkWinner()
}
fun checkWinner(){
var winner = -1
//row1
if(player1.contains(1) && player1.contains(2) && player1.contains(3)) {
winner = 1
}
if(player2.contains(1) && player2.contains(2) && player2.contains(3)){
winner = 2
}
//row2
if(player1.contains(4) && player1.contains(5) && player1.contains(6)) {
winner = 1
}
if(player2.contains(4) && player2.contains(5) && player2.contains(6)){
winner = 2
}
//row3
if(player1.contains(7) && player1.contains(8) && player1.contains(9)) {
winner = 1
}
if(player2.contains(7) && player2.contains(8) && player2.contains(9)){
winner = 2
}
//col1
if(player1.contains(1) && player1.contains(4) && player1.contains(7)) {
winner = 1
}
if(player2.contains(1) && player2.contains(4) && player2.contains(7)){
winner = 2
}
//col2
if(player1.contains(2) && player1.contains(5) && player1.contains(8)) {
winner = 1
}
if(player2.contains(2) && player2.contains(5) && player2.contains(8)){
winner = 2
}
//col3
if(player1.contains(3) && player1.contains(6) && player1.contains(9)) {
winner = 1
}
if(player2.contains(3) && player2.contains(6) && player2.contains(9)){
winner = 2
}
//cross1
if(player1.contains(1) && player1.contains(5) && player1.contains(9)) {
winner = 1
}
if(player2.contains(1) && player2.contains(5) && player2.contains(9)){
winner = 2
}
//cross2
if(player1.contains(3) && player1.contains(5) && player1.contains(7)) {
winner = 1
}
if(player2.contains(3) && player2.contains(5) && player2.contains(7)){
winner = 2
}
if(winner == 1){
player1WinnerCount += 1
Toast.makeText(this, "Player 1 win the game", Toast.LENGTH_LONG).show()
restartGame()
}else if(winner == 2){
player2WinnerCount += 1
Toast.makeText(this, "Player 2 win the game", Toast.LENGTH_LONG).show()
restartGame()
}
}
fun autoPlay(){
var emptyCells = ArrayList<Int>()
for(cellId in 1..9){
if(!(player1.contains(cellId) || player2.contains(cellId))){
emptyCells.add(cellId)
}
}
if(emptyCells.size == 0){
restartGame()
}
val r = Random()
val randIndex = r.nextInt(emptyCells.size)
val cellId = emptyCells[randIndex]
var buSelected:Button?
buSelected = when(cellId){
1 -> bu1
2 -> bu2
3 -> bu3
4 -> bu4
5 -> bu5
6 -> bu6
7 -> bu7
8 -> bu8
9 -> bu9
else -> {bu1}
}
playGame(cellId, buSelected)
}
var player1WinnerCount = 0
var player2WinnerCount = 0
fun restartGame(){
activityPlayer = 1
player1.clear()
player2.clear()
for(index in 1..9){
val buSelected:Button
buSelected = when(index){
1 -> bu1
2 -> bu2
3 -> bu3
4 -> bu4
5 -> bu5
6 -> bu6
7 -> bu7
8 -> bu8
9 -> bu9
else -> {bu1}
}
buSelected!!.text = ""
buSelected!!.setBackgroundResource(R.color.whiteBu)
buSelected!!.isEnabled = true
}
Toast.makeText(this, "Player1: $player1WinnerCount ,Player2: $player2WinnerCount", Toast.LENGTH_LONG).show()
}
}
実行結果
エミュレーターで実行するとこんな感じです。
感想
AndroidStudioが登場したことで、Java+eclipseの時代よりも、簡単に開発環境の構築と
コーディングできるようになっていると思います。
kotlinについてはJavaのライブラリも最新のkotlinのライブラリも使えつつ、現代的なコードなので生産性の向上が期待できると思います。
もっと多くのアプリを作ってみたいところです。