※これは解答です。どうしても課題が解けない場合、ご利用ください。
課題1 - 基本問題
package main
import (
"fmt"
"math/rand"
"time"
)
const (
PAA = 1
GUU = 2
CHOKI = 3
)
func main() {
COUNT := 1000000
rand.Seed(time.Now().UnixNano())
result := [3]int{}
for i := 0; i < COUNT; i++ {
a := yukpiz()
b := kent()
switch {
case a == b:
result[0]++
case a == PAA && b == GUU, a == GUU && b == CHOKI, a == CHOKI && b == PAA:
result[1]++
case a == PAA && b == CHOKI, a == GUU && b == PAA, a == CHOKI && b == GUU:
result[2]++
default:
panic("(´・ω・`)")
}
}
fmt.Printf("引分: %d\n", result[0])
fmt.Printf("勝利: %d\n", result[1])
fmt.Printf("敗北: %d\n", result[2])
}
func yukpiz() int {
s := []int{PAA, GUU, CHOKI}
return s[rand.Intn(len(s))]
}
func kent() int {
s := []int{PAA, GUU, CHOKI}
return s[rand.Intn(len(s))]
}
課題1 - 発展問題
※変更箇所のみ記載しています。
func kent() int {
s := []int{PAA, PAA, PAA, GUU, CHOKI}
return s[rand.Intn(len(s))]
}
課題2 - 基本問題
package main
import (
"fmt"
)
type MessageTo int
const (
MESSAGE_TO_KENT MessageTo = 0
MESSAGE_TO_YUKPIZ MessageTo = 1
MESSAGE_END_ME MessageTo = 3
MESSAGE_END_ME_TOO MessageTo = 4
)
func main() {
ch := make(chan MessageTo) // 相手にボールを渡す為のチャネル
done := make(chan bool) // 全ての会話完了を検知するチャネル
go kent(ch, done)
go yukpiz(ch, done)
// 会話が終わるまでブロック
<-done
// 閉じているかを確認
<-ch
fmt.Println("会話完了")
}
func kent(ch chan MessageTo, done chan bool) {
texts := []string{"あなたの名前を教えてください", "私はけんとです", "生ハム食べに行きましょう"}
for v := range ch {
switch v {
case MESSAGE_END_ME_TOO:
// 終了通知が来たらチャネルを閉じる
close(ch)
close(done)
case MESSAGE_END_ME:
if len(texts) == 0 {
// セリフがなくなったら完了
ch <- MESSAGE_END_ME_TOO
break
}
fallthrough
case MESSAGE_TO_KENT:
if len(texts) > 0 {
fmt.Println("kent:" + texts[0]) // 次のセリフを発言する
texts = texts[1:] // 発言済みのセリフを消す
ch <- MESSAGE_TO_YUKPIZ // 相手にボールを渡す
} else {
ch <- MESSAGE_END_ME
}
case MESSAGE_TO_YUKPIZ:
ch <- MESSAGE_TO_YUKPIZ
}
}
}
func yukpiz(ch chan MessageTo, done chan bool) {
texts := []string{"私はゆくぴずです", "よろしくおねがいします", "行きましょう"}
ch <- MESSAGE_TO_KENT
for v := range ch {
switch v {
case MESSAGE_END_ME_TOO:
close(ch)
close(done)
case MESSAGE_END_ME:
if len(texts) == 0 {
ch <- MESSAGE_END_ME_TOO
break
}
fallthrough
case MESSAGE_TO_KENT:
ch <- MESSAGE_TO_KENT
case MESSAGE_TO_YUKPIZ:
if len(texts) > 0 {
fmt.Println("yukpiz:" + texts[0])
texts = texts[1:]
ch <- MESSAGE_TO_KENT
} else {
ch <- MESSAGE_END_ME
}
}
}
}
課題2 - 発展問題
チャネルは1対1での送信と受信をサポートしていますが、
ブロードキャストのような1対多のような通信をサポートするには工夫が必要です。
package main
import (
"fmt"
)
type Worker struct {
Name string
BroadcastChan chan int
DoneChan chan int
ReceiveChan chan int
Receive func(*Worker)
}
func main() {
bch := make(chan int) //ブロードキャスト用のチャネル
done := make(chan int) //終了判定用のチャネル
var workers []*Worker
workers = append(workers, &Worker{
Name: "yukpiz",
BroadcastChan: bch,
ReceiveChan: make(chan int),
Receive: yukpiz,
})
workers = append(workers, &Worker{
Name: "kent",
BroadcastChan: bch,
ReceiveChan: make(chan int),
Receive: kent,
})
workers = append(workers, &Worker{
Name: "ariaki",
BroadcastChan: bch,
ReceiveChan: make(chan int),
Receive: ariaki,
})
go BroadcastObserve(workers, bch, done)
for _, w := range workers {
go w.Receive(w)
}
// 全てのチャネルが閉じられている事を確認
<-done
<-bch
for _, w := range workers {
<-w.ReceiveChan
}
fmt.Println("exit!")
}
func BroadcastObserve(workers []*Worker, bch chan int, done chan int) {
defer close(done)
for v := range bch {
for _, w := range workers {
w.ReceiveChan <- v
}
}
fmt.Println("closed broad cast")
for _, w := range workers {
close(w.ReceiveChan)
}
}
func yukpiz(me *Worker) {
fmt.Printf("%s: 皆さんの名前を教えてください\n", me.Name)
me.BroadcastChan <- 1
for v := range me.ReceiveChan {
switch v {
case 3:
fmt.Printf("%s: ありがとうございます\n", me.Name)
fmt.Printf("%s: 好きなモノを教えてください\n", me.Name)
v++
me.BroadcastChan <- v
case 5:
fmt.Printf("%s: 日本酒が好きなんですね\n", me.Name)
v++
me.BroadcastChan <- v
case 7:
fmt.Printf("%s: 生ハムを食べにいきましょう\n", me.Name)
v++
me.BroadcastChan <- v
}
}
}
func kent(me *Worker) {
for v := range me.ReceiveChan {
switch v {
case 1:
fmt.Printf("%s: 私はけんとです\n", me.Name)
v++
me.BroadcastChan <- v
case 6:
fmt.Printf("%s: 私は生ハムが好きです\n", me.Name)
v++
me.BroadcastChan <- v
case 8:
fmt.Printf("%s: 行きましょう\n", me.Name)
close(me.BroadcastChan)
}
}
}
func ariaki(me *Worker) {
for v := range me.ReceiveChan {
switch v {
case 2:
fmt.Printf("%s: 私はありあきです\n", me.Name)
v++
me.BroadcastChan <- v
case 4:
fmt.Printf("%s: 私は日本酒です\n", me.Name)
v++
me.BroadcastChan <- v
}
}
}