Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions kadai3-1/yoheimiyamoto/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
タイピングゲームを作ろう
標準出力に英単語を出す(出すものは自由)
標準入力から1行受け取る
制限時間内に何問解けたか表示する
13 changes: 13 additions & 0 deletions kadai3-1/yoheimiyamoto/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package main

import (
"os"

"github.com/YoheiMiyamoto/dojo4/kadai3-1/yoheimiyamoto/pingpong"
)

func main() {
words := []string{"one", "two", "three", "four", "five"}
pingpong.Play(os.Stdin, os.Stdout, words)

}
5 changes: 5 additions & 0 deletions kadai3-1/yoheimiyamoto/pingpong/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/*
Package pingpong ...

*/
package pingpong
71 changes: 71 additions & 0 deletions kadai3-1/yoheimiyamoto/pingpong/pingpong.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package pingpong

import (
"bufio"
"fmt"
"io"
"time"
)

// Play ...
// words -> 出題するワード一覧
func Play(r io.Reader, w io.Writer, words []string) {
inputCh := make(chan string)
inputDone := make(chan struct{}, 1)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

特に値を入れていることはなさそうなので、サイズの指定は必要なさそうです

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

了解です。修正しましたっ

input(r, inputCh, inputDone)

var s score

fmt.Fprintln(w, "ゲームスタート!制限時間は5秒!")
GAME:
for {
// wordsをすべて回答したらゲームを終了させる
if s.count() == (len(words) - 1) {
break GAME
}

word := words[s.count()]
fmt.Fprintln(w, word)

select {
case i := <-inputCh:
if i == word {
fmt.Fprintln(w, "正解!")
s.addCorrect()
} else {
fmt.Fprintln(w, "不正解!")
s.addIncorrect()
}
case <-time.After(5 * time.Second):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

一つのワード入力の 制限時間5秒 であるならばよいのですが、ゲーム自体の制限時間であれば、このforの外で time.After を実行しておかないとforに入るたびに5秒からカウントしてしまいます

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

こちらも修正しましたっ

break GAME
}
}
close(inputDone) // inputのチャネルを閉じる
fmt.Fprintln(w, "タイムアウト。ゲーム終了")
fmt.Println(s.Result())
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここまで w io.Writer にのみ利用してきているので、ここも os.Stdout ではなく w に書き込んだほうがテストしやすさ的にも良いと思います

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

そうですねっ。こちらも修正しました。

}

// 標準入力から受け取ったテキストをchチャネルに送信。
func input(r io.Reader, ch chan<- string, done <-chan struct{}) {
scanner := bufio.NewScanner(r)
go func() {
for scanner.Scan() {
t := scanner.Text()
ch <- t
}
}()

// ゲームが終了した場合、inputも終了させる。
go func() {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

goroutineとして実行しているので、この処理自体ほとんど意味がなさそうです

select {
case <-done:
return
}
}()

// 上記を以下のようにgoroutine使わずに記述するとゲームがフリーズしてしまう理由が理解できていないです。
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doneがcloseされるまでブロックすることになるので、inputの実行箇所でとまることになります

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。理解できましたっ

// select {
// case <-done:
// return
// }
}
1 change: 1 addition & 0 deletions kadai3-1/yoheimiyamoto/pingpong/pingpong_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package pingpong
38 changes: 38 additions & 0 deletions kadai3-1/yoheimiyamoto/pingpong/score.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package pingpong

import "fmt"

// 正解、不正解のスコアをカウント
type score struct {
correct int
incorrect int
}

// 正解をカウントアップ
func (s *score) addCorrect() {
s.correct++
}

// 不正解をカウントアップ
func (s *score) addIncorrect() {
s.incorrect++
}

func (s *score) count() int {
return s.correct + s.incorrect
}

// 正解率の算出
func (s score) rate() float32 {
if s.correct == 0 {
return 0
}
sum := float32(s.correct) + float32(s.incorrect)
return float32(s.correct) / sum * 100
}

// 結果を出力
func (s score) Result() string {
sum := s.correct + s.incorrect
return fmt.Sprintf(`正解率: %.2f %%(%d/%d)`, s.rate(), s.correct, sum)
}