Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InoAyaka / 課題3 #24

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
55 changes: 55 additions & 0 deletions kadai3-1/InoAyaka/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# <課題3-1>【TRY】タイピングゲームを作ろう
## 概要

- 標準出力に英単語を出す(出すものは自由)
- 標準入力から1行受け取る
- 制限時間内に何問解けたか表示する


## 使い方
```
$ go build -o typing
$
$ ./typing -h
Usage of ./typing:
-t int
time limit(unit:seconds) (default 30)
$
$
```

実行例
```
$ ./typing -t 15
society
society
ability
ablity
bless
bless
anybody
anybody
title
title
understand
understand
commercial
commercial
表示 入力 (一致)
---------------------------------------------------------------------------
society society (◯)
ability ablity (×)
bless bless (◯)
anybody anybody (◯)
title title (◯)
understand understand (◯)
commercial commercial (◯)
---------------------------------------------------------------------------
7問中 6問 (85.71 %)
---------------------------------------------------------------------------
```

### 感想

- 前回の課題にあったテストのしやすさを考慮したコードをいかに書くかに悩みました
- 課題3-2に比べると、難しい課題ではないように感じたが、いざ書いてみると読みやすく書くにはどうしたら良いか悩んだ部分も多かった
3 changes: 3 additions & 0 deletions kadai3-1/InoAyaka/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/gopherdojo/dojo8/kadai3-1/InoAyaka

go 1.14
174 changes: 174 additions & 0 deletions kadai3-1/InoAyaka/typing.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
package main

import (
"bufio"
"flag"
"fmt"
"io"
"math/rand"
"os"
"strings"
"time"
)

type word string
type words []word

var errOut io.Writer = os.Stderr
var out io.Writer = os.Stdout

//オプション指定
var t = flag.Int("t", 30, "time limit(unit:seconds)")

type result struct {
word word
input string
match bool
}

func main() {
flag.Parse()

//出力する英単語リストの取得
words, err := getWords()
if err != nil {
fmt.Fprintf(errOut, err.Error())
os.Exit(1)
}

//結果を記録するための構造体
rs := make([]result, 0, 100)
//結果をやり取りするためのチャネル
ch := make(chan result)
//時間の設定
tm := time.After(time.Duration(*t) * time.Second)

//MEMO:引数のresultは、スライスのためアドレスを渡すことはしない
go do(&words, ch)

LOOP:
for {
select {
case r := <-ch:
rs = append(rs, r)
case <-tm:
//結果を表示
printResult(rs)
//close(abort)
break LOOP
}
}

}

//getWords 英単語のリストを取得します
func getWords() (words, error) {
wordsFile := "./words.txt"

words := make(words, 0, 2000)

f, err := os.Open(wordsFile)
if err != nil {
return nil, err
}

defer f.Close()

scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Text()
words = append(words, word(line))
}

if scanner.Err() != nil {
return nil, err
}

return words, nil
}

//do 英単語の表示、入力結果の送信を行います
func do(words *words, ch chan<- result) {
for {
//標準出力にランダムで1単語出力する
word := printWord(words)

input, err := getInput()
if err != nil {
fmt.Fprintf(errOut, err.Error())
os.Exit(1)
}

ch <- result{
word: word,
input: input,
match: string(word) == input,
}
}

}

//printWord ランダムで英単語を出力します
func printWord(words *words) word {
//ランダムで出力するために、乱数を作成
t := time.Now().UnixNano()
rand.Seed(t)

//indexを指定して取得するため、len(words)までを上限とする
s := rand.Intn(len(*words))

fmt.Fprintln(out, (*words)[s])
return (*words)[s]
}

//getInput 標準入力から1行読み込みます
func getInput() (string, error) {
scanner := bufio.NewScanner(os.Stdin)

//読み込み失敗を5回繰り返したら、エラーを返す
var input string

for errCnt := 0; errCnt < 5; {
scanner.Scan()
input = scanner.Text()

if err := scanner.Err(); err != nil {
errCnt++
fmt.Fprintf(errOut, "読み込みに失敗しました(%d回目): %v", errCnt+1, err)
} else {
//問題なく読み込めた場合、読み込み結果を返す
return input, nil
}
}
return input, fmt.Errorf("読み込みに5回連続で失敗しました")
}

//printResult 結果の表示を行います
func printResult(rs []result) {
var matchCnt int

//入力途中でタイムアウトした場合を考慮し、改行を追加しておく
fmt.Fprintln(out)
fmt.Fprintf(out, "%-20s %-20s (%s)\n", "表示", "入力", "一致")
fmt.Fprintln(out, strings.Repeat("-", 75))

for _, r := range rs {
var m string

switch {
case r.match:
m = "◯"
matchCnt++
case !r.match:
m = "×"
}

fmt.Fprintf(out, "%-20s %-20s (%s)\n", r.word, r.input, m)
}

matchRate := float64(matchCnt) / float64(len(rs)) * 100

fmt.Fprintln(out, strings.Repeat("-", 75))
fmt.Fprintf(out, "%d問中 %d問 (%.2f %%)\n", len(rs), matchCnt, matchRate)
fmt.Fprintln(out, strings.Repeat("-", 75))
}
Loading