diff --git a/kadai3-1/README.md b/kadai3-1/README.md new file mode 100644 index 0000000..51dcfe5 --- /dev/null +++ b/kadai3-1/README.md @@ -0,0 +1,15 @@ + +## 課題 + +``` +タイピングゲームを作ろう +標準出力に英単語を出す(出すものは自由) +標準入力から1行受け取る +制限時間内に何問解けたか表示する +``` + +## 実装 + +* [x] `bufio.Scanner`を使って標準入力から1行ずつ読み取りチャンネルに送る。 +* [x] `time.After` を使って時間が来たら知らせるチャンネルを作成。 +* [x] for select を使って、タイマーのチャンネルと標準入力を受け取るチャンネルを待つ。 \ No newline at end of file diff --git a/kadai3-1/pchatsu/cmd/main.go b/kadai3-1/pchatsu/cmd/main.go new file mode 100644 index 0000000..309a42a --- /dev/null +++ b/kadai3-1/pchatsu/cmd/main.go @@ -0,0 +1,12 @@ +package main + +import ( + "os" + + "github.com/gopherdojo/dojo3/kadai3-1/pchatsu" +) + +func main() { + tg := typinggame.NewTypingGame(60, os.Stdin, os.Stdout) + tg.Play() +} diff --git a/kadai3-1/pchatsu/questions.go b/kadai3-1/pchatsu/questions.go new file mode 100644 index 0000000..8367232 --- /dev/null +++ b/kadai3-1/pchatsu/questions.go @@ -0,0 +1,81 @@ +package typinggame + +var ( + questions = []string{ + "time", + "person", + "year", + "way", + "day", + "thing", + "man", + "world", + "life", + "hand", + "part", + "child", + "eye", + "woman", + "place", + "work", + "week", + "case", + "point", + "government", + "company", + "number", + "group", + "problem", + "fact", + "good", + "new", + "first", + "last", + "long", + "great", + "little", + "own", + "other", + "old", + "right", + "big", + "high", + "different", + "small", + "large", + "next", + "early", + "young", + "important", + "few", + "public", + "bad", + "same", + "able", + "be", + "have", + "do", + "say", + "get", + "make", + "go", + "know", + "take", + "see", + "come", + "think", + "look", + "want", + "give", + "use", + "find", + "tell", + "ask", + "work", + "seem", + "feel", + "try", + "leave", + "call", + } +) diff --git a/kadai3-1/pchatsu/typing_game.go b/kadai3-1/pchatsu/typing_game.go new file mode 100644 index 0000000..c5061c9 --- /dev/null +++ b/kadai3-1/pchatsu/typing_game.go @@ -0,0 +1,55 @@ +package typinggame + +import ( + "bufio" + "io" + "strconv" + "time" +) + +type TypingGame struct { + limitSec int + correct int + r io.Reader + w io.Writer +} + +func NewTypingGame(limitSec int, r io.Reader, w io.Writer) *TypingGame { + tg := TypingGame{ + limitSec: limitSec, + r: r, + w: w, + } + return &tg +} + +func readAnswer(r io.Reader, ch chan<- string) { + sc := bufio.NewScanner(r) + for sc.Scan() { + ch <- sc.Text() + } +} + +func (t *TypingGame) Play() { + ch := make(chan string) + go readAnswer(t.r, ch) + + timer := time.After(time.Duration(t.limitSec) * time.Second) + question := questions[t.correct] + + t.w.Write([]byte(question + "\n")) +LOOP: + for { + select { + case s := <-ch: + if question == s { + t.correct++ + question = questions[t.correct%len(questions)] + t.w.Write([]byte(question + "\n")) + } + case <-timer: + t.w.Write([]byte("time over! correct:" + strconv.Itoa(t.correct))) + break LOOP + } + } +} diff --git a/kadai3-1/pchatsu/typing_game_test.go b/kadai3-1/pchatsu/typing_game_test.go new file mode 100644 index 0000000..c66936c --- /dev/null +++ b/kadai3-1/pchatsu/typing_game_test.go @@ -0,0 +1,85 @@ +package typinggame + +import ( + "bytes" + "io" + "reflect" + "testing" +) + +func TestNewTypingGame(t *testing.T) { + type args struct { + limitSec int + r io.Reader + w io.Writer + } + tests := []struct { + name string + args args + want *TypingGame + }{ + {"#1 normal case", args{5, bytes.NewBufferString("a"), &bytes.Buffer{}}, &TypingGame{limitSec: 5, r: bytes.NewBufferString("a"), w: &bytes.Buffer{}}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + w := &bytes.Buffer{} + if got := NewTypingGame(tt.args.limitSec, tt.args.r, w); !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewTypingGame() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_readAnswer(t *testing.T) { + type args struct { + r io.Reader + } + tests := []struct { + name string + args args + want []string + }{ + {"#1 normal case", args{bytes.NewBufferString("foo\nbar\nbaz\n")}, []string{"foo", "bar", "baz"}}, + {"#2 normal case", args{bytes.NewBufferString("foo\nbar\nbaz")}, []string{"foo", "bar"}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ch := make(chan string) + go readAnswer(tt.args.r, ch) + for _, w := range tt.want { + if got := <-ch; got != w { + t.Errorf("channel got = %v, want %v", got, w) + } + } + }) + } +} + +func TestTypingGame_Play(t *testing.T) { + // for tests + questions = []string{"foo", "bar", "baz"} + + tests := []struct { + name string + r io.Reader + wantCorrect int + wantW string + }{ + {"#1 normal case", bytes.NewBufferString("foo\nbar\n"), 2, "foo\nbar\nbaz\ntime over! correct:2"}, + {"#2 1 mistake case", bytes.NewBufferString("foo\nbaz\nbar"), 2, "foo\nbar\nbaz\ntime over! correct:2"}, + {"#3 loop case", bytes.NewBufferString("foo\nbar\nbaz\nfoo\n"), 4, "foo\nbar\nbaz\nfoo\nbar\ntime over! correct:4"}, + } + for _, tt := range tests { + w := &bytes.Buffer{} + tg := NewTypingGame(1, tt.r, w) + t.Run(tt.name, func(t *testing.T) { + tg.Play() + if gotCorrect := tg.correct; gotCorrect != tt.wantCorrect { + t.Errorf("correct got = %v, want %v", gotCorrect, tt.wantW) + } + if gotW := w.String(); gotW != tt.wantW { + t.Errorf("io.Writer got = %v, want %v", gotW, tt.wantW) + } + }) + } +}