1. 判断操作类型
首先,我们需要判断操作数组 operateArray
。如果操作是弃牌行为,我们先处理弃牌逻辑,其他操作类型暂时不考虑,后续逐步完善。
2. 执行弃牌操作
弃牌操作完成后,牌局状态会发生变化。弃牌后,我们需要从当前用户的手中删除这张牌。
为此,我们编写一个删除方法,删除指定的 card
。由于牌可能有重复,我们需要指定删除的数量。具体逻辑如下:
遍历当前用户的牌组,找到与
card
匹配的牌。检查牌的数量是否大于 0。
如果满足条件,删除指定数量的牌。
代码示例:
func deleteCard(cards []int, card int, count int) []int {
for i := 0; i < len(cards); i++ {
if cards[i] == card {
cards = append(cards[:i], cards[i+count:]...)
break
}
}
return cards
}
3. 记录操作
操作完成后,我们需要记录此次操作,方便后续追溯和逻辑判断。记录内容包括:
当前玩家的座位号。
操作的牌
card
。操作类型(如弃牌)。
记录示例:
logRecord := LogRecord{
Seat: currentSeat,
Card: card,
Action: "discard",
}
4. 清空当前玩家操作
弃牌后,当前玩家的操作状态需要清空,表示当前玩家已完成操作。这样在重新获取数据时,可以明确玩家的当前状态。
5. 切换到下一个玩家
弃牌完成后,轮到下一个玩家操作。我们需要确定下一个玩家的座位号,可以通过取模运算实现:
nextSeat = (currentSeat + 1) % totalSeats
6. 补充逻辑:碰牌
在弃牌后,下一个玩家摸牌之前,需要判断其他玩家是否可以进行碰牌操作。具体逻辑如下:
获取上一个玩家弃牌的牌
lastCard
。判断其他玩家的手牌中是否有与
lastCard
相同的牌,且数量大于等于 2。如果满足条件,允许玩家进行碰牌操作。
代码示例:
func canPong(cards []int, lastCard int) bool {
count := 0
for _, card := range cards {
if card == lastCard {
count++
}
}
return count >= 2
}
7. 线程安全
在操作游戏数据时,需要考虑线程安全问题。为了避免数据紊乱,我们在修改数据时加上锁:
mutex.Lock()
defer mutex.Unlock()
8. 逻辑优化
在判断其他玩家是否可以碰牌时,我们需要遍历所有玩家,并检查每个玩家的手牌。如果其他玩家可以碰牌,记录操作并等待玩家确认。
优化示例:
for i, player := range players {
if i != currentSeat {
if canPong(player.Cards, lastCard) {
player.Actions = append(player.Actions, "pong")
}
}
}