Golangマルチスレッドのシンプルな戦い

マルチスレッド、チャネル、読み取り/書き込みロック(単一書き込みと複数読み取り)、ランダム(シャッフル)は、この記事に関係する主な知識ポイントです。

結果を見てみましょう。これは実験的な手順であるため、実際の家主とのギャップはまだあります。

[ディーラー]:カードをシャッフルします。
スワイプ...
[ ディーラー]:カードがシャッフルされます。
[ディーラー]:取引を開始します。
[ディーラー]:1人あたり17枚のカード。
[ディーラー]:家主をつかみます。
[牙]:ハハ、私は家主です!
牙の手は[♣9♦9♥A♠9♣6♣5♦3♣10♥5♣8♠Q♠A♠8♦4♥4♦K♥7♣A♠K♥3]で​​、合計20 。
ドンのカードは[大王♦8♠5暁王♠6♣Q♠10♣7♠3♦A♦Q♥J♣K♥6♥9♥Q♣2]で、合計17枚のカードです。
erのカードは[♣A♠K♥3♥2♠4♦2♦5♥K♦10♠2♥8♦6♣4♦J♣3♣J♠7]で、合計17枚のカードです。
[牙]:トランプを始めました。
[er]:トランプを始めました。
[ドン]:トランプを始めました。
勝者はerです。
基本的なプロセスはシャッフル->ディール->家主をつかむ->トランプ-> ggです。

ハハ、このプログラムの本質は、時間(lan)(de)に(xie)制限(le)があるため、カードゲームのどのスレッドがそれをつかむか、カードをプレイし、カードが出るまで、それが勝つということです。(マルチスレッドライティングDoudizhuは私の大学のオペレーティングシステムコースの実験プロジェクトです。当時、DoudizhuアルゴリズムはC ++とMFCを使用して完全に実装されており、インターフェイスでインタラクティブにカードをプレイできます)

コードの変更を見てください。

主な機能

func main(){ // カードをシャッフルする:= shuffle()// カードを配るDealCards:= deal(cards)//家主fmt.Println( "[Dealer]:Landlord。")go player(order [0]、dealCards [0])go player(order [1]、dealCards [1])go player(order [2]、dealCards [2])//勝者勝者:= <-winner fmt.Printf( "Winner %sです。\ n”、勝者)} 分析:













1.メインは、トランプ、シャッフル、取引、家主の獲得、トランプ、ggのステップです。
2. go player()を使用すると、3つのスレッド、つまり3つのプレーヤーが開かれます。
3.カードが配られると、残りの3枚のホールカードがチャネルの「底」に保存されます。家主をつかむと、3つのスレッドがそれを受け取ります。最初に手にしたのは家主です。
4.カードゲームの最後に、値は他のチャネル「勝者」に書き込まれます。最初にゲームを終了した人は誰でも彼の名前を保存します。
5.3プレイヤーがカードをプレイしているとき、メインはブロックされ、チャネル「勝者」からの値の読み取りを待機します。プレイヤーがプレイを終了すると、チャネル「勝者」は値を持ち、アクティブになります。
シャッフル機能

func shuffle()[] string { fmt.Println( "[Dealer]:カードをシャッフルします。")fmt.Println( "Swipe ...")カード:=カード()rand.Seed(time.Now( ).UnixNano())rand.Shuffle(len(cards)、func(i、j int){ カード[i]、カード[j] =カード[j]、カード[i] })fmt.Println( "[ディーラー]:カードはシャッフルされます。」)







return cards

}
分析:

1. Randは、何回実行しても同じであるため、デフォルトではfalseランダムです。ランダムな結果がそれぞれ異なるように、シードtime.Now()。UnixNano()を設定する必要があります。
2.rand.Shuffle()はカードをシャッフルし、2枚のカードの位置をランダムに交換します。
取引機能

func deal(cards [] string)[] [] string { fmt.Println( "[Dealer]:Start Dealing Cards 。")var dealCards [] [] string dealCards = append(dealCards、cards [0:17] )dealCards = append(dealCards、cards [17:34])dealCards = append(dealCards、cards [34:51])fmt.Println( "[Dealer]:17 card per person。")





go leaveBottom(cards[51:54])

return dealCards

}
分析:

1.カードがシャッフルされているため、まず17枚ずつ、3枚のカードを直接切り取ります。
2. 3穴のカードを残して、チャネルの「下」に置きます。
3.スレッドがここで開かれなくなった場合、デッドロックが発生します。main自体もスレッドであるため、チャネルを直接格納すると、スレッドがチャネルの値を読み取るまでmainがブロックされます。mainがブロックされると、後続のコードを実行できなくなり、さらに3つのプレーヤースレッドを開始できなくなります。値が読み取られると、デッドロックが発生します。
4.したがって、leaveBottom()は別のスレッドを開始します。
デスクテーブル

タイプDesk struct { mutex sync.RWMutex playCards [] string }


func(d * Desk)write(card string){ d.mutex.Lock()defer d.mutex.Unlock()d.playCards = append(d.playCards、card)}



func(d * Desk)read()[] string { d.mutex.RLock()defer d.mutex.RUnlock()return d.playCards } 解析:




1.読み取り/書き込みロックとテーブルでプレイされるカードを含むデスク構造が定義されます。
2. write()とread()の2つの関数が定義されています。3つのスレッドは同時に読み取ることができますが、書き込むことができるのは1回のみ、つまり複数の読み取りロックと複数の読み取りロックです。
プレイヤー機能

func player(name string、hands [] string){ landlord:= <-bottom if len(landlord )> 0 { fmt.Printf( "[%s]:Haha、I am the landlord!\ n"、name)hands = append(hands、landlord …)desk.write(name)} fmt.Printf( "%sのカードは%s、合計%dのカードです。\ n"、名前、手、len(hands))






time.Sleep(time.Second)

i := 0
for true {
	playCards := desk.read()
	if playCards[len(playCards)-1] == name {
		if i == 1 {
			fmt.Printf("[%s]:我开始出牌了。\n", name)
		}
		desk.write(hands[i])
		desk.write(order[(getOrderID(name)+1)%3])
		i += 1
		if i == len(hands) {
			winner <- name
			break
		}
	}
}

}
アマゾン評価www.yisuping.com

おすすめ

転載: blog.csdn.net/weixin_45032957/article/details/108599378