もがき系プログラマの日常

もがき系エンジニアの勉強したこと、日常のこと、気になっている技術、備忘録などを紹介するブログです。

株式会社メディアドゥに潜入して、Go言語 初心者向けハンズオンを「少しだけ」受けてきた

はじめに

こんばんは。

Goの勉強しはじめてます。

基本的なところとかを少しづつやってるんですが、今回 Go言語 初心者向けハンズオン #2 に参加させていただきました。

このハンズオン自体 #2で、自分は今回初参加かつ、仕事が忙しくて #1の資料を見れていなかった(言い訳)ので、ちょっと転校生気分で参加しました。

しかもそんな状態なのに、あろうことか仕事の影響で遅れて参加するという更に転校生気分に拍車をかけつつの参加でした。

タイトルに「少しだけ」とつけたのは↑が理由です。

すでに結構進んでいて、ゴルーチンとかテストの説明を少し聞けたくらいでした。

ただ、最後の課題には間に合ったので、試行錯誤の結果を載せておきます。

課題の内容は以下。

  1. じゃんけんゲームを作ろう
  2. 会話ゲームを作ろう

ハンズオンで使用されたスライドに仕様も記載されています。

やってみた

自分の実力では制限時間が短かったので、時間内に出来たのは1だけでした。。

そのかわりテストとかも書いたりして、1は完全に終わらそうと頑張りました。

package main

import (
    "fmt"
    "math/rand"
    "strconv"
    "time"
)

const (
    // GU じゃんけんグー
    GU = iota
    // CHOKI じゃんけんチョキ
    CHOKI
    // PA じゃんけんパー
    PA
)

const (
    // DRAW 引き分け
    DRAW = iota
    // LOSE 負け
    LOSE
    // WIN 勝ち
    WIN
)

// Player ユーザーの勝敗などを持つ構造体
type Player struct {
    winCount  int
    loseCount int
    drawCount int
}

// executeCount 実行回数
const executeCount = 100

func main() {
    player := Player{
        winCount:  0,
        loseCount: 0,
        drawCount: 0,
    }

    for i := 1; i <= executeCount; i++ {
        battle(&player)
    }

    drawResult(player)
}

// battle じゃんけん開始
func battle(player *Player) {
    playerHand := selectHand()
    enemyHand := selectHand()
    switch judge(playerHand, enemyHand) {
    case DRAW:
        player.drawCount++
    case LOSE:
        player.loseCount++
    case WIN:
        player.winCount++
    }
}

// selectHand じゃんけんの手を決定する
func selectHand() int {
    rand.Seed(time.Now().UnixNano())
    return rand.Intn(2)
}

// judge 判定
// @see https://qiita.com/mpyw/items/3ffaac0f1b4a7713c869
func judge(playerHand int, enemyHand int) int {
    return (playerHand - enemyHand + 3) % 3
}

// drawResult 勝敗結果表示
func drawResult(player Player) {
    fmt.Println("勝利=" + strconv.Itoa(player.winCount) + "回")
    fmt.Println("引分=" + strconv.Itoa(player.drawCount) + "回")
    fmt.Println("敗北=" + strconv.Itoa(player.loseCount) + "回")
    fmt.Println("-------------------------------")
    fmt.Println("合計=" + strconv.Itoa(executeCount) + "回")
}

=> $ go run main.go
勝利=28回
引分=44回
敗北=28回
-------------------------------
合計=100

時間制限があったので焦ってしまい、当初 judge() のロジックは完全にif文で泥臭くやってました(笑)

その後テストを書き始める前に、参考サイトを確認し編集しました。

(あー頭が良くなりたい)

以下はテストです。

package main

import (
    "strconv"
    "testing"
)

func TestSelectHand_ありえない値(t *testing.T) {
    hand := selectHand()
    if hand != PA && hand != GU && hand != CHOKI {
        t.Error("selectHand()でとれるはずのない値が取れている => " + strconv.Itoa(hand))
    }
}

func TestJudge_引き分けなのに引き分けではない(t *testing.T) {
    result := judge(0, 0)
    if result != DRAW {
        t.Error("引き分けのはずなのに引き分けではない => " + strconv.Itoa(result))
    }
}

func TestJudge_負けなのに負けではない(t *testing.T) {
    result := judge(1, 0)
    if result != LOSE {
        t.Error("負けのはずなのに負けではない => " + strconv.Itoa(result))
    }
}

func TestJudge_勝ちなのに勝ちではない(t *testing.T) {
    result := judge(2, 0)
    if result != WIN {
        t.Error("勝ちのはずなのに勝ちではない => " + strconv.Itoa(result))
    }
}

func TestBattle(t *testing.T) {
    player := Player{
        winCount:  0,
        loseCount: 0,
        drawCount: 0,
    }
    battle(&player)
    if player.drawCount == 0 && player.winCount == 0 && player.loseCount == 0 {
        t.Error("勝敗結果が登録されていない")
    }
}

=> $ go test -v
=== RUN   TestSelectHand_ありえない値
--- PASS: TestSelectHand_ありえない値 (0.00s)
=== RUN   TestJudge_引き分けなのに引き分けではない
--- PASS: TestJudge_引き分けなのに引き分けではない (0.00s)
=== RUN   TestJudge_負けなのに負けではない
--- PASS: TestJudge_負けなのに負けではない (0.00s)
=== RUN   TestJudge_勝ちなのに勝ちではない
--- PASS: TestJudge_勝ちなのに勝ちではない (0.00s)
=== RUN   TestBattle
--- PASS: TestBattle (0.00s)
PASS
ok      _/path/to/study_01     0.057s

終わりに

スタッフで参加されていた@yukpizさんがQiitaに解答を載せてくれています。

【解答】Go言語初心者向けハンズオン #2

正直2番の方は解答見てもちょっとわからなかったので、もうちょいゴルーチン・チャネルについて勉強しないとなと思いました。

また、懇親会で @yukpizさんとお話させてもらい、エンジニアの登壇を応援する会を教えてもらいました。

slackチームにも参加させていただきました。

自分が運営している 週1でブログ書くslackチームに入ってくれている人たちも何人かいらして、面白かったですw

せっかくslackチームにも入ったので、来年こそは登壇を経験したいと思います。

f:id:kojirooooocks:20181128134525p:plain

ではでは。