想不到能这样摸鱼 | go 技术论坛-江南app体育官方入口
介绍
想不到有一天我也能在写代码的同时还能斗一把小地主!
这种休闲 摸鱼 模式想法来自逛掘金时看到这篇文章 介绍的ratel。有兴趣的小伙伴可以直接搜索ratel具体了解。本着一个探索瞎折腾的心,决定仿照ratel实现自己的fish项目。
这款游戏基于golang实现,目前仅支持pvp模式,后续有时间再支持更多的模式。
项目地址
技术栈
- golang
- socketio
安装
首先下载编译,确保本地安装有golang环境
git clone git@github.com:yangchen5710/fish_client.git
cd fish_client
go build fish_client
接下来在终端下执行可执行文件
windows
client.exe 47.101.212.202 8096
linux/macos
./client 47.101.212.202 8096
玩法
为啥论坛不能上传gif了?
出牌规则
所有牌型:
┌──┐──┐──┐──┐──┐──┐──┐──┐──┐──┐──┐──┐──┐──┐──┐
│3 |4 |5 |6 |7 |8 |9 |10|j |q |k |a |2 |s |x |
│♦ |♦ |♦ |♦ |♦ |♦ |♦ |♦ |♦ |♦ |♦ |♦ |♦ | | |
└──┘──┘──┘──┘──┘──┘──┘──┘──┘──┘──┘──┘──┘──┘──┘
- 王炸:
sx
- 顺子:
34567
- 三带一:
3334
- 三带二:
33344
- 飞机:
333444a2
- 单张10:
t
- 单张a:
a
- 封顶顺子:
3456789tjqka
- 不想出牌:
pass
算法实现
首先我们先定义相关结构和接口以及相关常量
const (
rocket = 12
bomb = 11
pair = 10
three = 9
threewithone = 8
threewithtwo = 7
singlestraight = 6
doublestraight = 5
threestraight = 4
aircraftwithwings = 3
fourwithtwo = 2
single = 1
)
type poker struct {
level string //牌的数值
type string //牌的类型
}
type pokermath struct {
pokertype int
minvalue int
pokerlength int
}
type pokeralgorithm interface {
isrocket(poker, poker) (bool, pokermath) //火箭 即大小王
isbomb([]poker) (bool, pokermath) //炸弹 四张同数值牌
ispair([]poker) (bool, pokermath) //对牌 数值相同的两张牌
isthree([]poker) (bool, pokermath) //三张牌 数值相同的三张牌
isthreewithone([]poker) (bool, pokermath) //三带一 数值相同的三张牌 一张单牌
isthreewithtwo([]poker) (bool, pokermath) //三带二 数值相同的三张牌 一张对牌
issinglestraight([]poker) (bool, pokermath) //单顺 五张或更多的连续单牌(如:45678 或 789tjqk)。不包括 2 点和双王
isdoublestraight([]poker) (bool, pokermath) //双顺 三对或更多的连续对牌(如:334455 、77 88 99 1010 jj)。不包括 2 点和双王
isthreestraight([]poker) (bool, pokermath) //三顺:二个或更多的连续三张牌(如:333444 、 555 666 777 888)。不包括 2 点和双王
isaircraftwithwings([]poker) (bool, pokermath) //飞机带翅膀:三顺 同数量的单牌(或同数量的对牌)
isfourwithtwo([]poker) (bool, pokermath) //四带二:四张牌 两手牌(注意:四带二不是炸弹)。
issingle(poker) (bool, pokermath) //单牌
comparepokers(pokermath, pokermath) bool //比较牌型和大小
}
然后去实现相关的接口算法
func (pm pokermath) isrocket(poker1, poker2 poker) (boolean bool, pokermath pokermath) {
boolean = (poker1.level == "level_small_king" && poker2.level == "level_big_king") ||
(poker1.level == "level_big_king" && poker2.level == "level_small_king")
if boolean {
pokermath = pokermath{pokertype: rocket, minvalue: 0, pokerlength: 2}
}
return
}
func (pm pokermath) isbomb(pokers []poker) (boolean bool, pokermath pokermath) {
boolean = false
if len(pokers) != 4 {
return
}
valuemap := make(map[string]int)
for _, poker := range pokers {
valuemap[poker.level]
}
for pokerlevel, count := range valuemap {
if count == 4 {
boolean = true
pokermath = pokermath{pokertype: bomb, minvalue: converttovalueinit(pokerlevel), pokerlength: 4}
return
}
}
return
}
func (pm pokermath) ispair(pokers []poker) (boolean bool, pokermath pokermath) {
boolean = false
if len(pokers) != 2 {
return
}
valuemap := make(map[string]int)
for _, poker := range pokers {
valuemap[poker.level]
}
for pokerlevel, count := range valuemap {
if count == 2 {
boolean = true
pokermath = pokermath{pokertype: pair, minvalue: converttovalueinit(pokerlevel), pokerlength: 2}
return
}
}
return
}
func (pm pokermath) isthree(pokers []poker) (boolean bool, pokermath pokermath) {
boolean = false
if len(pokers) != 3 {
return
}
valuemap := make(map[string]int)
for _, poker := range pokers {
valuemap[poker.level]
}
for pokerlevel, count := range valuemap {
if count == 3 {
boolean = true
pokermath = pokermath{pokertype: three, minvalue: converttovalueinit(pokerlevel), pokerlength: 3}
return
}
}
return
}
func (pm pokermath) isthreewithone(pokers []poker) (boolean bool, pokermath pokermath) {
boolean = false
if len(pokers) != 4 {
return
}
sort.slice(pokers, func(i, j int) bool {
return pokers[i].level < pokers[j].level
})
// 判断是否是三带一,即第一个三张牌点数相同,且第四张牌与其中一张牌的点数不同
if pokers[0].level == pokers[1].level && pokers[1].level == pokers[2].level &&
pokers[2].level != pokers[3].level {
boolean = true
pokermath = pokermath{pokertype: threewithone, minvalue: converttovalueinit(pokers[0].level), pokerlength: 4}
return
}
// 也可以判断最后三张牌是否相同点数
if pokers[1].level == pokers[2].level && pokers[2].level == pokers[3].level &&
pokers[0].level != pokers[1].level {
boolean = true
pokermath = pokermath{pokertype: threewithone, minvalue: converttovalueinit(pokers[1].level), pokerlength: 4}
return
}
return
}
func (pm pokermath) isthreewithtwo(pokers []poker) (boolean bool, pokermath pokermath) {
boolean = false
if len(pokers) != 5 {
return
}
sort.slice(pokers, func(i, j int) bool {
return pokers[i].level < pokers[j].level
})
// 判断是否是三带二
if pokers[0].level == pokers[1].level && pokers[1].level == pokers[2].level &&
pokers[3].level == pokers[4].level && pokers[2].level != pokers[3].level {
boolean = true
pokermath = pokermath{pokertype: threewithtwo, minvalue: converttovalueinit(pokers[0].level), pokerlength: 5}
return
}
// 也可以判断三张和两张的位置对调
if pokers[0].level == pokers[1].level && pokers[2].level == pokers[3].level &&
pokers[3].level == pokers[4].level && pokers[1].level != pokers[2].level {
boolean = true
pokermath = pokermath{pokertype: threewithtwo, minvalue: converttovalueinit(pokers[2].level), pokerlength: 5}
return
}
return
}
func (pm pokermath) issinglestraight(pokers []poker) (boolean bool, pokermath pokermath) {
boolean = false
if len(pokers) < 5 {
return
}
sort.slice(pokers, func(i, j int) bool {
// 将牌的值转换为对应的数值进行比较
val1 := converttovalue(pokers[i].level)
val2 := converttovalue(pokers[j].level)
return val1 < val2
})
// 检查牌是否连续
for i := 0; i < len(pokers)-1; i {
if converttovalue(pokers[i1].level)-converttovalue(pokers[i].level) != 1 {
return // 如果有间断,不是单顺
}
}
boolean = true
pokermath = pokermath{pokertype: singlestraight, minvalue: converttovalueinit(pokers[0].level), pokerlength: len(pokers)}
return
}
func (pm pokermath) isdoublestraight(pokers []poker) (boolean bool, pokermath pokermath) {
boolean = false
if len(pokers)%2 != 0 || len(pokers) < 6 {
return // 牌数必须是偶数且至少6张才可能是双顺
}
// 对牌进行排序
sort.slice(pokers, func(i, j int) bool {
// 将牌的值转换为对应的数值进行比较
val1 := converttovalue(pokers[i].level)
val2 := converttovalue(pokers[j].level)
return val1 < val2
})
fmt.println(pokers)
// 检查牌是否连续成对
for i := 0; i < len(pokers)-1; i = 2 {
if converttovalue(pokers[i].level) != converttovalue(pokers[i1].level) ||
(i > 0 && converttovalue(pokers[i].level)-converttovalue(pokers[i-1].level) != 1) {
return // 如果不是成对连续,不是双顺
}
}
boolean = true
pokermath = pokermath{pokertype: doublestraight, minvalue: converttovalueinit(pokers[0].level), pokerlength: len(pokers)}
return
}
func (pm pokermath) isthreestraight(pokers []poker) (boolean bool, pokermath pokermath) {
boolean = false
if len(pokers)%3 != 0 || len(pokers) < 6 {
return // 牌数必须是3的倍数且至少6张才可能是三顺
}
// 对牌进行排序
sort.slice(pokers, func(i, j int) bool {
// 将牌的值转换为对应的数值进行比较
val1 := converttovalue(pokers[i].level)
val2 := converttovalue(pokers[j].level)
return val1 < val2
})
// 检查牌是否连续三张
for i := 0; i < len(pokers)-2; i = 3 {
if converttovalue(pokers[i].level) != converttovalue(pokers[i1].level) ||
converttovalue(pokers[i].level) != converttovalue(pokers[i2].level) ||
(i > 0 && converttovalue(pokers[i].level)-converttovalue(pokers[i-1].level) != 1) {
return
}
}
boolean = true
pokermath = pokermath{pokertype: threestraight, minvalue: converttovalueinit(pokers[0].level), pokerlength: len(pokers)}
return
}
func (pm pokermath) isaircraftwithwings(pokers []poker) (boolean bool, pokermath pokermath) {
boolean = false
if len(pokers)%4 != 0 || len(pokers) < 8 {
return // 牌数必须是4的倍数且至少8张才可能是飞机带翅膀
}
// 对牌进行排序
sort.slice(pokers, func(i, j int) bool {
// 将牌的值转换为对应的数值进行比较
val1 := converttovalue(pokers[i].level)
val2 := converttovalue(pokers[j].level)
return val1 < val2
})
// 计算连续三张的数量
triplecount := 0
minvalue := ""
for i := 0; i < len(pokers)-2; i {
if converttovalue(pokers[i].level) == converttovalue(pokers[i1].level) &&
converttovalue(pokers[i].level) == converttovalue(pokers[i2].level) {
triplecount
if minvalue == "" {
minvalue = pokers[i].level
}
}
}
// 检查是否有连续三张的数量大于等于2
if triplecount < 2 {
return // 如果连续三张的数量不足2组,不是飞机带翅膀
}
boolean = true
pokermath = pokermath{pokertype: aircraftwithwings, minvalue: converttovalueinit(minvalue), pokerlength: len(pokers)}
return
}
func (pm pokermath) isfourwithtwo(pokers []poker) (boolean bool, pokermath pokermath) {
boolean = false
if len(pokers) != 6 {
return // 必须是六张牌才可能是四带二
}
// 对牌进行排序
sort.slice(pokers, func(i, j int) bool {
// 将牌的值转换为对应的数值进行比较
val1 := converttovalue(pokers[i].level)
val2 := converttovalue(pokers[j].level)
return val1 < val2
})
// 计算四张牌的数量
fourcount := 0
minvalue := ""
for i := 0; i < len(pokers)-3; i {
if converttovalue(pokers[i].level) == converttovalue(pokers[i1].level) &&
converttovalue(pokers[i].level) == converttovalue(pokers[i2].level) &&
converttovalue(pokers[i].level) == converttovalue(pokers[i3].level) {
fourcount
if minvalue == "" {
minvalue = pokers[i].level
}
}
}
// 检查是否有四张牌
if fourcount != 1 {
return // 如果不是四张牌,不是四带二
}
// 计算两张其他牌的数量
othercount := 0
for i := 0; i < len(pokers)-1; i {
if converttovalue(pokers[i].level) != converttovalue(pokers[i1].level) {
othercount
}
}
if othercount != 1 {
return // 如果不是两张其他牌,不是四带二
}
boolean = true
pokermath = pokermath{pokertype: fourwithtwo, minvalue: converttovalueinit(minvalue), pokerlength: len(pokers)}
return
}
func (pm pokermath) issingle(poker poker) (boolean bool, pokermath pokermath) {
boolean = true
pokermath = pokermath{pokertype: single, minvalue: converttovalueinit(poker.level), pokerlength: 1}
return
}
func (pm pokermath) comparepokers(roompokermath, playerpokermath pokermath) bool {
roompokertype := roompokermath.pokertype
roompokerlength := roompokermath.pokerlength
roomminvalue := roompokermath.minvalue
if roompokertype == playerpokermath.pokertype &&
roompokerlength == playerpokermath.pokerlength &&
roomminvalue < playerpokermath.minvalue {
return true
}
if roompokertype != playerpokermath.pokertype {
switch roompokertype {
case bomb:
if playerpokermath.pokertype == rocket {
return true
}
case pair, three, threewithone, threewithtwo, singlestraight, doublestraight, threestraight, aircraftwithwings, fourwithtwo, single:
if playerpokermath.pokertype == rocket || playerpokermath.pokertype == bomb {
return true
}
}
}
return false
}
func (pm pokermath) converttovaluestring(cardvalue string) string {
valuemap := map[string]string{
"3": "level_3", "4": "level_4", "5": "level_5", "6": "level_6",
"7": "level_7", "8": "level_8", "9": "level_9",
"0": "level_10", "t": "level_10", "t": "level_10",
"j": "level_j", "j": "level_j",
"q": "level_q", "q": "level_q",
"k": "level_k", "k": "level_k",
"a": "level_a", "a": "level_a", "1": "level_a",
"2": "level_2",
"s": "level_small_king", "s": "level_small_king",
"x": "level_big_king", "x": "level_big_king",
}
return valuemap[cardvalue]
}
// 辅助函数:将牌的值转换为数值
func converttovalueinit(cardvalue string) int {
valuemap := map[string]int{
"level_3": 3, "level_4": 4, "level_5": 5, "level_6": 6, "level_7": 7,
"level_8": 8, "level_9": 9, "level_10": 10, "level_j": 11, "level_q": 12,
"level_k": 13, "level_a": 14, "level_2": 15, "level_small_king": 16, "level_big_king": 17,
}
return valuemap[cardvalue]
}
func converttovalue(cardvalue string) int {
value := converttovalueinit(cardvalue)
if value == 15 || value == 16 || value == 17 {
value = -1
}
return value
}
计划
- 支持pve
- 支持个人得分
本作品采用《cc 协议》,转载必须注明作者和本文链接
to live is to change the world