多线程乒乓球双打服务计算概论作业Word文档下载推荐.docx
《多线程乒乓球双打服务计算概论作业Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《多线程乒乓球双打服务计算概论作业Word文档下载推荐.docx(8页珍藏版)》请在冰豆网上搜索。
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唤醒,开始下一次发球。
三、实现代码
packagemain
import(
"
fmt"
sync"
math/rand"
container/ring"
strings"
time"
)
var(
wgsync.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)//发球顺序
serveMetuxsync.Mutex//发球锁
catch_chanel_B=make(chanTableTennis,0)//B队伍接球的通道
catch_chanel_A=make(chanTableTennis,0)//A队伍接球的通道
balls_ids=make(chanint,serveTotals)//球的id
//乒乓球
typeTableTennisstruct{
idint
trailstring//球的轨迹
}
funcserve(){
deferwg.Done()
//初始化发球顺序
turn.Value="
A1"
turn=turn.Next()
B1"
A2"
B2"
//开始发球
fori:
=0;
i<
times;
i++{
forj:
j<
nums;
j++{
serveMetux.Lock()//解锁时发下一个球
name:
=turn.Value.(string)
t:
=TableTennis{<
-balls_ids,name+"
-in"
ifname[0]=='
A'
{
catch_chanel_B<
-t
}else{
catch_chanel_A<
}
time.Sleep(time.Second)//等待playergoroutine对catch_chanel的使用
close(catch_chanel_A)
close(catch_chanel_B)
//A队选手
funcplayerA(namestring,rateint){
deferwg.Done()//延迟递减计数
fort:
=rangecatch_chanel_A{
//2.将球击打出去
rest:
=shot(rate)
//3.记录球的轨迹
t.trail+="
-"
+name+"
+rest
//球出界
ifstrings.Compare("
out"
rest)==0{
//对方得分
score_balls_B=append(score_balls_B,t)
fmt.Println(t)
serveMetux.Unlock()
continue
//4.对面队伍准备接球
//B队选手
funcplayerB(namestring,rateint){
=rangecatch_chanel_B{
score_balls_A=append(score_balls_A,t)
//击球
funcshot(rateint)string{
ifrand.Intn(100)<
rate{
return"
in"
funcmain(){
fmt.Println("
比赛开始..."
//初始化球的id
serveTotals;
balls_ids<
-i+1
wg.Add(nums+1)//累加计数
goserve()
//time.Sleep(time.Second)
goplayerA("
45)
60)
goplayerB("
50)
90)
wg.Wait()
比赛结束."
fmt.Printf("
A:
B=(%d,%d)\n"
len(score_balls_A),len(score_balls_B))
for_,t:
=rangescore_balls_A{
fmt.Println()
=rangescore_balls_B{
四、运行结果
(从自己博客复制的图片,所以有水印)