Kotlinまとめ
変数と定数
// 変数 var a : Int = 10000 // 定数 val c : Double = 12345.6
文字列
// 文字列比較は「==」で行う if (str == "Kotlin") // 文字列テンプレート val i = 10 print("i = $i") // i = 10と出力される // 文字列テンプレート2 val s = "Kotlin" printl("$s length is ${s.length}) // Kotlin length is 6 と出力される。{}をつけないと、Kotlin length is Kotlin.lengthと表示される
型変換
// 文字列からInt型へ val str = "64" val intVal: Int = str.toInt() // 文字列からInt型へ val str = "Kotlin" val intVal: Int? = str.toIntOrNull() // 変換できない場合は変数にNULLを設定 // 数値から文字列へ val num = 128 val intStr: String = num.toString() // 数値同士の変換 val i: Int = 100 val l: Long = i.toLong() // 明示的に変換が必要
null許容型とnull非許容型
// 以下の場合はエラーになる var text: String = null // 正しくは以下のような記述が必要 var text: String? = null // null許容型の変数の場合、String型のメソッドやプロパティをそのままでは使用できないなどの制限が発生する
配列
// Arrayクラスを使い、arrayOf関数で配列の生成と初期化を実行 val arrayofInt: Array<Int> = arrayOf(1,2,3,5,8) for (i in arrayofInt) print("$i,")
if式
val c = 10 val d = 20 if (c > d) { print("c") } else { print("d") }
when式
val a = 4 when(a) { 1 -> println("a == 1") 2,3 -> println("a == 2 or 3") in 10..20 -> println("a is in the range") !in 20..30 -> println("a is outside the range") else -> println("otherwise") }
for文
for(i in 1..4) // 配列を使う場合 val a = arrayOf(1,2,3,10,100) for(i in a.indices) { print("a[$i]=${a[i]}") }
while文
var x = 0 while(x < 10) // do-while文 var i = 7 do { }while(i > 4)
リスト
// 読み込み専用リスト val items: List<Int> = listOf(1, 2, 3) println(items.get(0)) println(items[1]) println(items.size) // 変更可能なリスト val numbers:MutableList<Int> = mutableListOf(1,2,3) numbers.add(4) // リストの末尾に4を追加 numbers.remove(4) // 一致する要素を削除
セット
// 特徴:要素の順番をもたず、要素の重複も不可 // 読み取り専用セット var strings:Set<String> = setOf("A", "B", "C") println(strings) // 変更可能セット var strings: MutableSet<String> = mutableSetOf("x", "y", "z") strings.add("A") strings.remove("x")
マップ
// 読み取り専用のマップ val fruits:Map<String, Int> = mapOf("apple" to 1, "orange" to 2, "banana" to 3) // 変更可能なマップ val fruits: MutableMap<String, Int> = mutableMapOf("apple" to 1, "orange" to 2, "banana" to 3) println(fruits.get("apple")) println(fruits["orange"]) fruits.put("melon",4) // 要素の追加 fruits.remove("banana") // 要素の削除
関数
// fun 関数名(引数:型,・・・):戻り値 fun times(a: Int, b: Int): Int { return a * b } // 関数の呼び出し // Kotlinではクラスに属さない関数を作成できる times(2, 5) // 戻り値がなく、2番目の引数をデフォルト設定する場合 fun printTimes(a: Int, b:Int = 2):Unit{} printTimes(10)
ラムダ式と関数型
ラムダ式:{引数 -> 処理}
// ラムダ式は変数に格納可能。この時の変数を関数型と呼ぶ var minus = {x: Int, y: Int -> x - y} minus(3, 1) // 結果は2 // 変数plusは「(Int, Int) -> Int」型 var plus:(Int, Int) -> Int = {x:Int, y:Int -> x + y} plus(5, 2) // 暗黙の引数it // 引数一つの場合は、引数を省略し引数itを使用できる // itを使用しない場合はvar double:(Int)->Int = {x:Int -> x * 2}とかく var double: (Int)->Int = {it * 2} double(5) // 関数型を引数に持つ関数 fun doLambda(x: Int, y:(Int) -> Int) = y(x) doLambda(5, {it * 2})
クラスとインターフェイス
クラスの定義:class クラス名{}
※publicがデフォルト
// インスタンス生成 class dog{} val dog = Dog()
インターフェイスの定義:interface インターフェイス名{定義}
Kotlinのインターフェイスは、抽象メソッドだけでなく具体的な処理も記述できる
プロパティ
Javaのフィールドとセッター/ゲッターを合わせたような機能
var dog = Dog() dog.name = "Pochi" // プロパティに値を設定 println(dog.name) // プロパティから値を取得
コンストラクタ
プライマリコンストラクタ:クラス宣言でクラス名の後ろにコンストラクタの引数のみを記載する。処理ブロックをもたないため、処理を行う場合はinitブロックに記載。
セカンダリコンストラクタ:処理ブロックを持つため、その他の処理も記載可能。
class Dog(val name: String) {}
イニシャライザ
class Dog(val name: String) { init{ print("The dog's name is $name") } val dog = Dog("Pochi") // ここでイニシャライザが呼ばれる
クラスの継承
class クラス名(プライマリコンストラクタ):親クラス名(コンストラクタ引数)
open class Person(val name: String) {} // 親クラス class Student(name: String, var degree: String): Person(name) {} // 子クラス val student = Student("Sato", "Bechelor") // インスタンスの取得
インターフェイスの実装
class クラス名(プライマリコンストラクタ):インターフェイス名
※Kotlinのインターフェイスでは抽象メソッドだけでなく、具体的な処理を含むメソッドも定義可能。
interface Pet { fun eat() fun showName() = println("I'm Pet") } class Cat : Pet { override fun eat() = println("I'm eating") }
型チェックとスマートキャスト
fun getLen(obj: Any) : Int? { // isでStringかどうかチェック if ( obj is String) { // チェック後はStringとしてふるまう return obj.length } return null }
継承関係のあるオブジェクトのキャスト
// 親クラス open class Person(val name: String) { } // 子クラス class Student(name: String, var degree: String): Person(name) {} // 親クラスの変数に子クラスのインスタンスを生成 var person: Person = Student("Sato", "Bechelor") // 子クラスへキャスト var student: Student = person as Student // as?の使い方 var person: Person = Student("Sato", "Bechelor") // 例外が発生せずに、nullがセットされる var student = person as? Int
objectキーワード
objectキーワードを使うと、クラスの宣言とそのインスタンス生成を一気に行う。
■シングルトンの実現
object MyProfile { 処理内容 } // objectを使用するにはオブジェクト名を使う MyProfile.メソッド名
■コンパニオンオブジェクト
class Person(val name: String) { companion object { fun printMe() = println("Hello") } } // スタティックメソッドのように扱える Person.printMe()
■オブジェクト式
無名インナークラスを簡単に記述するための機能
SAM変換
Javaのインターフェイスで、メソッドを1つしか持たないものをSAM(Simgle Abstract Method)インターフェイスと呼ぶ。
KotlinではSAMインターフェイスを引数としたメソッドを、ラムダ式で置き換えることをSAM変換と呼ぶ。
NULL安全
var s: String? = null // The length of null is nullと出力される print("The length of $s is ${s?.length}")
// 変数sがNULLでなければsを返し、sがNULLならdefaultという文字列を返す val t : String = s ?: "default"
スコープ関数
■with関数
with(対象オブジェクト){処理}
with(Dog("Pochi")) { age = 10 // プロパティに値を設定 message() // メソッドの利用 }
■apply関数
対象オブジェクト.apply{処理}
Dog("Pochi").apply{ age = 10 }.message()
■let関数
対象オブジェクト.leg{処理}
var output = name?.let{ var upperCase = it.toUpperCase() var len = it.length "$upperCase $len" } print(output)
■run関数
対象オブジェクト.run{処理}
var output = name?.run{ "${toUpperCase()} $length" } print(output)
Pair
val p = Pair("apple", 1) println("the number of ${p.first} is ${p.second} // the number of apple is 1と出力される
拡張関数
fun 型名.関数名(引数):戻り値{処理}
隻狼 SEKIRO_どんなことでも、楽しむためには成長が必要
朝食:サーモンアボカド丼、味噌汁
昼食:つけ麺
夕食:ホタルイカと春キャベツのサラダ、焼き鳥
待ち焦がれていた「SEKIRO」、発売日に買いました。
それから、4~5時間ほどやってるけど、ホントに死んで死んで死にまくる。自分はこれまでDarkSoulsシリーズや、Bloodborneをやったことがなくて、FROMSOFTWAREの死にゲー具合が全く分からなかった。けど、これほど死にまくるとは。まさに、心折れる。。
けど、不思議なことに、こんな敵絶対倒せないと思っていながら、何回もやってるといつの間にか倒せるようになってくる。これこそ、ゲームをやって「成長」が実感できる瞬間だ。
自分はゲームに求めるものは、「成長」だ。分かりやすくいうと、RPGの「レベル」だ。何十時間とやることで、レベルがあがり、強くなるし、使える技や魔法が増える。できることが増えると、さらにゲームが楽しくなり、プレイするという具合だ。
コマンド式のRPGは、アクションゲームなどのように反射神経を駆使したテクニックなどは必要なく、誰もが平等に時間をかければ必ず強くなれるゲームだ。だから、RPGでストレスなどは感じないと思う。ここでいうストレスとは、コントローラーをぶん投げてしまうようなことだ。
だが、このSEKIROはアクションゲームである。そのため、誰もが平等に成長できるわけではない。センスのいい人、悪い人ではっきりと成長速度に差が生じてしまう。
また、コマンド式のRPGなどのように、ただ時間をかければいいというものではない。アクションをマスターするために、操作の練習が必要だ。このSEKIROでも、「弾き」「回避」「見切り」などの、敵を倒すうえで必須なアクションが様々ある。これらは、相手の攻撃に合わせ、タイミングよく操作しないと発動しないアクションなのだが、これがとても難しい。
敵によって、攻撃パターンが違えば、こちらのコマンドを押すタイミングも違ってくる。敵の攻撃パターンを把握し、それらを見て、反射的に適切なアクションのコマンド操作が必要になってくる。なお、これらのアクションが何度でも練習できるシステムがゲームに組み込まれているのだが、これはプレイヤーの努力なしでは先に進めないことを物語っているともいえる。
FROMSOFTWAREが以前インタビューで答えていたのだが、「プレイヤーにはゲームで達成感を感じてもらいたい」。この考えは、SEKIROにも十分反映されていると思う。
SEKIROはたしかに高難易度だが、絶対にクリアできないなんてことはない。プレイヤーが努力し、プレイヤー自身が「成長」すれば、必ず先に進める。そうすると、新たな技を覚えたり、武器を入手できたりして、さらに強くなる。そして、またゲームに深くのめり込んでいく。
これ、ゲームだけにとどまらず、現実世界でも同じことだと思う。何事も楽しむためには、「成長」が必要。
さて、しばらくはSEKIROで死んで死んで死にまくる生活を送ります。
MLBが開幕したから、ワールドスポーツMLBの魅力について語らせてほしい
MLB開幕
朝食:おにぎり
昼食:麦飯、レンコンのきんぴら、たまごやき、ミートボール
夕食:ほうれん草とキノコの卵とじ、春巻き
ついにMLB開幕。1年早いもんですな。
因みに自分はMLB、NFL、NBAと見てるもんだから、1年中スポーツまみれの幸せな1年を過ごせている。あとこれに、UFCを見てるし、最近はF1にも手を出そうとしているから、むしろ色々追い付かなくなる悲劇に見舞われている。。
と、ここで昔を振り返ると、自分が「野球」に興味を持って、まさか試合を見るようになるとは思わなかった。
野球少年以外の少年にとって、「野球」とは憎むべき対象だった場合もあると思う。そう、昔は地上波で放送していたプロ野球中継だ。
プロ野球中継で、いつもやっている番組が中止になる。また、テレビの主導権は親にあるため、チャンネルを変えられる。予約録画をしていたら、野球が延長で放送時間が伸びて、録画が失敗するなどなど。野球に興味がなかった自分にとっては、本当に迷惑でしかなかった。
では、なぜ大人になって野球に興味を持ったかというと、「ワールドスポーツMLB」の番組のおかげだ。
最初、この番組を見始めたきっかけは、NBAの情報を見るためだ。しかし、番組タイトルから分かる通り、メインで扱うスポーツはMLB。そのため、MLBの情報が嫌でも入ってくるのだが、そこで放送されるシーンの数々は、野球に興味を抱かせるには充分だった。
あと、ちょうど自分が仕事から帰宅した時間帯にやっていたのも大きい。そして決定的に野球(というか、MLB)にハマるきっかけとなったのは、シカゴ・カブス vs クリーブランド・インディアンスのワールドシリーズだ。
このシリーズは、第7戦までもつれ、その第7戦の異様な盛り上がりは今思い出しても鳥肌が立つ。
また、ワールドスポーツMLBでの解説も素晴らしい。初心者にとって、そのスポーツの詳しいルールだったり、場面場面の駆け引きなどは試合を見ているだけでは分かりにくい。
「知る」ことにより「さらに好きになる」というのは、スポーツだけに留まらずどんなジャンルにも当てはまることだと言えるが、当時のワールドスポーツMLBの解説者である小宮山悟氏のコメントは、的確で分かりやすく大好きだった。そして何より、野球が大好きなのが伝わってくるのが素晴らしい。
そしてワールドスポーツMLBのもう一つの魅力として、ちゃんと野球が好きなキャスターを起用していること。中でも代表的なのが(というか、自分が好きなのが)、平原沖恵氏だ。プライベートでもプロ野球、MBL問わずの野球好きで、だからこそ番組内でのコメントにも好感しか持てない。特にこういうスポーツを扱う番組では、しっかりとそのスポーツを好きな人に担当してもらいたいのが、自分の自論だ。
だがしかし、Wikipediaを見ると今年のワールドスポーツMLBには、平原沖恵氏が出なさそうな。。というか、ワールドスポーツMLB、いつから始まるのか。
僕が筋トレする理由
2019年3月17日の所感
朝食:麦飯、味噌汁、鮭
昼食:炙り焼豚の極太つけ麺
夕食:サバ缶、豆腐、レタスのサラダ、もずく、ニンジンと柿ピーのマヨネーズ和え
体重:72.0kg
今日は日曜日なので、ジムでトレーニング。かれこれ1年以上ジムに通っているけど、体的には全く変化なし。
まぁ、ジムに行くのは休日だけで、しかも土日のどちらか1日だけだったりする。また、毎週行っているわけでもないので、月に1回しか行かないなんてこともざらにある。こんなペースで体を変えようという方が都合が良すぎる。
けど、全く変化がないかというと実はそうでもない。
最初レッグプレスは、70kgしかあがらなかった。けど今では120kgまであがるようになった。ベンチプレスは、20kgが限界だったが、今では倍の40kgまであがるようになった。バーベルスクワットは、40kgしかあがらなかったが、60kgまであがるようになった。
というように、体の変化はなくとも、確実に成長している。成長があるからこそ、今でもジムに通い続けている。
が、ジムに行く理由はこれだけではない。自分が今行っているジムにはサウナがついているのだが、このサウナが一番のお目当てといってもいい。実際、ジムに行くというより、サウナに行っている感覚が強い。
ただ、サウナだけに入って帰ってくると、料金的に損した気分になるため、筋トレもしているといった感じだ。
けど、サウナはもともと好きではなかった。というより、温泉や銭湯といった大勢が入るお風呂が苦手なのだ。結構、潔癖なとこがあるので。。
けど、今ではサウナがない生活は考えられない。サウナのどこがそんなにいいかと言うと、やはり体の底から、リフレッシュできるとこだろう。自分はサウナ-水風呂を1セットとして、これを3セット繰り返す。
3セット目にもなると、汗の質が変わってくる。いわゆる、サラサラ汗だ。ここまで来れば、体の不純物が取り除かれた(と思っている)。そうすると、体の爽快感が凄まじい。もう、これを体験すると、サウナから離れられなくなる。
あと、もう30歳を超えてきて、加齢臭のような体臭を放つ年齢になってきたので、体の不純物を定期的に出すことは、本当に重要だと感じている。ということで、あまり人に何かを薦めるということはないのだが、体臭に悩んでいる人には、サウナを激しくオススメします。
【ゲーム開発】ドット絵練習記録4
ゲーム開発をしていて、一番自分に足りないと思うのは、「イラスト」や「デザイン」の部分。
正直、ゲームシステムは大したことなくても、いわゆる「絵」の部分がしっかりしていれば、かなりまともなゲームに見えると思う。
ということで、しばらくお休みしていたドット絵練習をこっそり再開してます。
最近、この本買って、これを模写してるとこ。
この本は詳しく書いてあるけど、1から10まで書いてあるわけではなくて、一部は自分で考えて書かないといけないから、いい練習になっている。
ちなみに、これまで模写したドット絵たちがこちら。
ドット絵模写完了数:19枚
そこそこのラーメンが一番好きです。
2019年3月16日の所感
朝食:トースト
昼食:麦飯、つけ麺
夕食:スープ、納豆、豆腐、魚のソテー
体重:71.3kg
昼食に食べたつけ麺というのが、これ。
おそらく知っている人は知っていると思うが、この「炙り焼豚の極太つけ麺」、異常なくらい旨いです。しかも、これだけうまくて、お値段なんと税込み248円。
つけ麺をお店で食べると1000円近くするのが普通やと思うけど、そこに1000円も出すのがバカらしくなるくらいの衝撃。いや、もちろん1000円出しても食べたくなるつけ麺はあるけど、すべてのつけ麺ではないと思う。
つけ麺だけではなく、ラーメン全般で1000円が適正価格として浸透しつつあるけど、自分は1000円が適正価格だとは決して思わない。
ちなみに自分がこの世で一番うまいと思うラーメンがこれ。
東海地方の人なら誰でも知ってるスガキヤのラーメン。お値段320円。(昔は270円だった気が。。)
このスガキヤのラーメン、小さいときから食べてるから、もちろん思い出補正が入ってることは認める。けど、このラーメンを食べて、まずいと思う人はいないと思う。
一「うまいラーメン屋を知ってことが、一種のステータス」となることから、自分も積極的にラーメン屋に通った時期もあった。
けど、どれだけ食べても、「めっちゃうまい」と思える店にはほぼ出会えない。どこも、「うん、美味しいね」ぐらいの感想だ。じゃあ、それらのラーメンと、スガキヤとどっちが好き?と聞かれると、自分は秒で「スガキヤ」と答える。そうすると、ラーメン1杯に1000円を払うことに躊躇してしまう。このことに気付いてからというもの、意識的にラーメン屋に行かなくなった。
何にどれだけお金を払うのか、これは人によって大きく違ってくると思う。だからこそ、お金を払うとき、「自分にとって、これは適正か?」と自問自答することが大切だと感じる。
ということで、休日の昼食は、しばらく炙り焼豚の極太つけ麺、これで決まりです。
パスポート更新には要注意
2019年3月15日の所感
朝食:なし
昼食:ウィンナーパン、カレーパン、明太子パン
夕食:外食(フレンチのフルコース)
会社の休みを取って、パスポートを更新しにいった。
もう十年以上前にパスポートは一度取ったことがあり、とっくに期限は切れていた。今度、海外旅行に行く予定ができたので、そのためのパスポート更新だ。
平日の早朝だったため、かなり人は少ない。ちなみにパスポートの更新に必要なのは、「以前のパスポート」と「戸籍謄本」だ。戸籍謄本はその場で取得したので、家からの持ち物としては「以前のパスポート」のみ。
そこで書類もすべて作成し、審査を待っていると事件が!!!
「このパスポートは、すでにvoid”無効”のスタンプが押されています。このvoidスタンプは、パスポートの更新を行うときにしか押しません。パスポートセンターに問い合わせると、以前お客様はパスポート更新を行っており、そのパスポートの有効期限は切れていません。」
え!!!すでにパスポート更新してる!?全く記憶にございませんけど。。ということで急いで家に帰り、探してみると、ありましたパスポート。けど、もちろん一度も使っていなくて、更新した理由も忘れてしまったな。
記憶力はいい方やと思ってたけど、こういうこともあるんすね、自分。なにはともあれ、解決しました!