KotlinでCLIのWordleクローンを作ってみた


# Wordleとは

いま流行りの単語当てゲームです。まだの方はこちらから遊んでみてください。

https://www.nytimes.com/games/wordle/index.html

Wordleのルールは非常にシンプルです。

* プレイヤーは5文字の英単語を入力する
* 入力された英単語に含まれる各文字を正解の英単語と比較して、
  - 正解に含まれる文字が正解と同じ位置なら🟩で表示
  - 正解に含まれる文字が正解と異なる位置なら🟨で表示
* 6回以内に正解の単語を当てられたらクリア

このゲームをCLIで再現すること自体はそれほどむずかしくなさそうです。

というわけでKotlinの勉強がてら作りました。

# 枕詞を当てるゲームにしてみた

[Wordles of the World](https://rwmpelstilzchen.gitlab.io/wordles/)を見ればわかる通り、Wordleクローンは今や雨後の筍がごとく作られています。日本語版も複数あり、ふつうにやっていてはネタ被りは避けられません（wordleクローンがすでにネタ被り？　それはそう）

というわけで、（「Wordle 枕詞」でググった感じなさそうだったので）枕詞を当てるゲームにしてみました。

だいたいこんな感じになっています：

![makurakotoba_test2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521499/6a500696-a29d-7f82-378b-9c8c5eaa005c.gif)

![makurakotoba_test3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521499/b67e4df7-208e-f186-2036-268a6963f308.gif)

ソースコードはGithubに上げました。

https://github.com/msattova/makurakotobadle

## コード（枕詞リストを除く）

```kotlin:Main.kt
import java.security.SecureRandom

enum class Valid {
    GRAY, YELLOW, GREEN
}

enum class ANSIColor(val escapeSequence: String) {
    GREEN("\u001b[32;1m"),
    YELLOW("\u001b[33;1m"),
    RESET("\u001b[0m")
}

fun wordCheck(word: String, answer: String): Array<Valid>{
    val checkArray: Array<Valid> = Array(word.length){Valid.GRAY}
    for (i in word.indices){
        for (j in word.indices){
            if (word[i] == answer[j]){
                if (i == j){
                    checkArray[i] = Valid.GREEN
                }else{
                    checkArray[i] = Valid.YELLOW
                }
            }
        }
    }
    return checkArray
}

fun putColor(word: String, checkList: List<Valid>): String{
    var coloredString = ""
    for ((index, ele) in checkList.withIndex()){
        coloredString += when(ele){
            Valid.GREEN -> ANSIColor.GREEN.escapeSequence+word[index]+ANSIColor.RESET.escapeSequence
            Valid.YELLOW -> ANSIColor.YELLOW.escapeSequence+word[index]+ANSIColor.RESET.escapeSequence
            Valid.GRAY -> word[index]
        }
    }
    return coloredString
}

fun main() {
    val canTry = 7
    var cleared = false
    val answer = makurakotoba[SecureRandom().nextInt(makurakotoba.size)]
    var checkArray: Array<Valid>
    val message = "${answer.length}文字の枕詞を「ひらがな」で入力してください。"
    println(message)
    println("${canTry}回までトライできます。")
    for ( i in 0 until canTry ){
        print("> ")
        var word = readLine()
        while (word.isNullOrEmpty() || word.length != answer.length || (!makurakotoba.contains(word))){
            when{
                word.isNullOrEmpty() -> {
                    println(message)
                }
                word.length != answer.length -> {
                    println("${answer.length}文字の枕詞を入力してください。")
                }
                !makurakotoba.contains(word) -> {
                    println("入力されたことばが本プログラムの辞書にありません。")
                }
            }
            print("> ")
            word = readLine()
        }
        checkArray = wordCheck(word, answer)
        val colored = putColor(word, checkArray.toList())
        println(colored)
        if (word.equals(answer, ignoreCase = true)){
            cleared = true
            break
        }
    }
    if (cleared){
        println("おめでとうございます！")
    }else{
        println("こたえはこれでした：　$answer")
    }
}
```

# 参考

https://qiita.com/takmatsukawa/items/c54fc1c7796e4428f46c

https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/enum-classes.html

https://itsakura.com/java-random