多线程乒乓球双打-服务计算概论作业

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

J I A N G S U U N I V E R S ITY 多线程模拟乒乓球双打

学院名称:计算机

专业班级:软件1401

学生姓名:***

学生学号:**********

指导教师姓名:陈锦富

2017年6月7日

一、题目

1.有四个选手, A1和A2为一个队, B1和B2为另一个队. A1首

先发球(启动球), 然后B1, A2, B2将最后发球. 每一轮每个选

手发2个球.

2.选手不改变他们的位置.

3.比赛期间, 双方选手必须轮流发球,并且在同一个队伍的两个选

手可以竞争发球.

4.当轮到某个选手时, 他/她可以调用一个叫做shot(rate) 的随

机函数来模拟比赛,在给定概率rate以内,该函数返回“in”, 否则返回”out”. 例如rate=85%, 则球在界内的概率为

85%, 出界的概率为15%.

5.如果shot函数返回”in”, 对方选手必须调用shot函数把球

打回.

6.如果shot函数返回”out”, 对方选手赢得1分,随后重新发

球.

7.当每个选手发完2个球后比赛终止.分数多的一方赢得比赛.分

数一样多,比赛为平局.

8.每个选手作为一个线程实现.

二、实现思路

serve: 是指发球的goroutine.

serveMetux: 发球锁。

playerA: 是指A队伍抢到球的goroutine.

playerB: 是指B队伍抢到球的goroutine.

catch_chanel_A : 给A队伍的球的通道。

catch_chanel_B : 给B队伍的球的通道。

大致步骤:

1. serve 先加锁,后发球(将TableTennis放入通道中,如

catch_chanel_A ),然后重复上锁(serveMetux)阻塞自身。

2. playerA 如果catch_chanel_A 没有球,阻塞自身。如果有球,则从通道中拿到球,shot(rate) 后返回in, 记录信息后,则将球放

入给B的通道catch_chanel_B中。

3. playerB 如果catch_chanel_B 没有球,阻塞自身。如果有球,则从通道中拿到球,shot(rate) 后返回in, 记录信息后,则将球放入给B的通道catch_chanel_A中。如果shot(rate)返回out, 则解除锁(serveMetux),此时serve唤醒,开始下一次发球。

三、实现代码

package main

import (

"fmt"

"sync"

"math/rand"

"container/ring"

"strings"

"time"

)

var (

wg sync.WaitGroup // 用于goroutine计数

times = 2// 每个选手发球次数

nums = 4// 多少个选手

serveTotals = nums * times // 总发球次数

score_balls_A = make([]TableTennis, 0, serveTotals) // A的得分球

score_balls_B = make([]TableTennis, 0, serveTotals) // B的得分球

turn = ring.New(4) // 发球顺序

serveMetux sync.Mutex // 发球锁

catch_chanel_B = make(chan TableTennis, 0) // B队伍接球的通道

catch_chanel_A = make(chan TableTennis, 0) // A队伍接球的通道

balls_ids = make(chan int, serveTotals) // 球的id )

// 乒乓球

type TableTennis struct {

id int

trail string// 球的轨迹

}

func serve() {

defer wg.Done()

// 初始化发球顺序

turn.Value = "A1"

turn = turn.Next()

turn.Value = "B1"

turn = turn.Next()

turn.Value = "A2"

turn = turn.Next()

turn.Value = "B2"

// 开始发球

for i := 0; i < times; i++ {

for j := 0; j < nums; j++ {

serveMetux.Lock() // 解锁时发下一个球

turn = turn.Next()

name := turn.Value.(string)

t := TableTennis{<-balls_ids, name + "-in"}

if name[0] == 'A' {

catch_chanel_B <- t

} else {

catch_chanel_A <- t

}

}

}

time.Sleep(time.Second) // 等待player goroutine对catch_chanel的使用close(catch_chanel_A)

close(catch_chanel_B)

}

// A队选手

func playerA(name string, rate int) {

defer wg.Done() // 延迟递减计数

for t := range catch_chanel_A {

// 2. 将球击打出去

rest := shot(rate)

相关文档
最新文档