LoginSignup
8
6

More than 5 years have passed since last update.

はじめてのGo言語でランダム会話機を作る

Posted at

はじめに

Go言語を使って、自分の発言に対してランダムな接続詞を返してくれる会話機を作ってみます。

実行イメージ
2017-9-3_19-13-55_00-2.png

開発経緯

自分以外の人と会話している時、不思議と頭の中が整理される感覚があります。
しかし、いざ頭の中を整理したい時に常に誰かと会話できるとは限りません。

そもそも「他人と会話する」とは言うものの、相手が人間である必要はあるのでしょうか。
もしかして、自分の発言に対してランダムな言葉を返してくれるだけの簡易な機械があれば、頭の中を整理するのに役立つのではないでしょうか。

つまりこういうことです。
2017-9-4_4-39-22_00.png

これを検証するため、最近(?)流行りのGo言語を使ってランダム会話機を作ってみることにしました。

開発

ソースコード
https://github.com/MasaoBlue/go-random-joiner

1.インストールとHello World

はじめての Go 言語 (on Windows)

上記を参考にインストール & 動作確認します。
何歳になっても、新しい言語を触るのはわくわくしますね!

2.入力受け付け

まずはコンソール入力を受け取る部分を作ります。

sample.go
package main

import "fmt"

func main(){
  fmt.Printf("こんにちは。\n>") // 入力前のプロンプトを表示

  var stdin string // 入力文字列を保存する変数定義
  fmt.Scan(&stdin) // 「&」を付けてstdin変数のポインタを渡し、入力待ち

  // stdin変数に入力文字列が格納されます。
  // fmt.Println(stdin)
}

3.無限ループで繰り返し入力

入力を繰り返し行うため、無限ループを作ります。

sample.go
// func main
  for { // ループ条件を書かない場合は無限ループになる
    var stdin string
    fmt.Scan(&stdin)
  }

4.接続詞をファイルから読み込む

入力に対して応答させるための接続詞リストを、テキストファイルから読み込みます。
ファイル入出力の簡単な使い方はこちらを参照してください。

sample.go
import "os"
import "bufio"

// func main
  // テキスト配列を定義
  // 「:=」で変数宣言と代入を同時に行う
  words := []string{}

  // ファイルを開く
  fp, err := os.Open("words.txt")
  if err != nil {
    panic(err)
  }
  scanner := bufio.NewScanner(fp) // 1行ずつ読み取るためbufio(バッファ付きIO)を使用
  for scanner.Scan() {
    // 1行ずつ読み取ってwords配列に格納
    words = append(words, scanner.Text())
  }
  fp.Close()

5.接続詞をランダム抽出

読み込んだ接続詞リストから、ランダムに1つを抽出する関数を作ります。
こちらの実装を元に、intの部分をstringに変更します。

sample.go
import "time"
import "math/rand"

// 配列からランダム抽出
func choice(s []string) string {
    rand.Seed(time.Now().UnixNano()) // 乱数のシードとして現在時刻のナノ秒を渡す
    i := rand.Intn(len(s)) // 0 ~ 配列の要素数までのランダム値取得
    return s[i]
}

6.結果をファイルに書き込む

せっかく文字列を打ち込むのですから、入力値を保存できるようにしておきましょう。
複数回実行するため、ファイル名には現在時刻を使用します。

日付の文字列変換に関してはこちらにまとまっています。

sample.go
// func main
  // 複数回実行を考慮し、ファイル名に現在時刻を入れる
  const format = "20060102_1504"
  now := time.Now()
  outputFile := "result_" + now.Format(format) + ".txt"

  // 書き込み用ファイルを開く
  fpw, err := os.Create(outputFile)
  if err != nil {
    panic(err)
  }

  w := bufio.NewWriter(fpw)
  for {
    // 入力受け付け
    var stdin string
    fmt.Scan(&stdin)

    // ファイルへ書き込み
    fmt.Fprint(w, stdin + "\n")
    w.Flush()

    // 次の接続詞をランダムで表示
    fmt.Printf(choice(words) + "\n>")
  }

  fpw.Close()
  // ※無限ループをCtrl+cで止めるためこの位置のCloseは実行されない。
  //  必要な場合は以下の通りrescueを使って対応する。
  //
  // begin
  //   ループ処理
  // rescue Interrupt
  //   fpw.Close()
  // end

6.実行してみる

以下で実行します。

go run sample.go

2017-8-31_23-37-28_00.png

ちゃんと動いていそうです。
終了する場合はCtrl + cで停止します。

補足:接続詞一覧

必要に応じて以下のページなどからコピーし、words.txtに張り付けてください。
Yahoo!知恵袋:接続詞の役割&一覧

結論

会話相手がランダムだと、自分の行きたい方向に話が進められずもどかしい。
しかし一方で、人間と会話するのとは違った会話の広がりを感じる。

どうしても会話が発散してしまうため、情報を整理する用途には不向きそうです。
逆に、1人でアイデア発想などを行う場合には使えそうな気がします。

さいごに

This is 初投稿記事です。
「Qiitaに何書けば良いか分からない・・・」という言い訳から脱却するため、思い付きで作ったものを投稿してみました。

きっといつか誰かの役に立つように頑張ろうと思います。

おしまい。

8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6