当前位置:   article > 正文

注意看,这个小编叫小帅,居然用Python做出了可视化麻将,而且还有详细教学 | 附源码_可视化打牌

可视化打牌

前言

halo,包子们晚上好
今天给大家整一个基于pygame实现的可视化麻将
现在不是很多小伙伴都喜欢打麻将的嘛,逢年过节都会搓搓麻将的嘛,所以呀小编这边不就给大家安排上啦,源码啥的都可以直接给大家使用的哟
快跟你的小伙伴一起玩耍吧

相关文件

关注小编,私信小编领取哟!
当然别忘了一件三连哟~~
公众号:Python日志

开发工具

Python版本:3.7.8
相关模块:
pygame模块;
random模块;
GameTable模块;
Rule模块;
以及一些python自带的模块。

环境搭建

安装Python并添加到环境变量,pip安装需要的相关模块即可。

游戏规则

游戏中采取日麻无赤宝牌规则。共计 136 张麻将牌,其中包含 1-9 万/条/筒与东南西北中发白各 4 张(无花牌)。基本规则与国标麻将一致,区别主要在于:每轮对局中存在“宝牌”,胡牌时手牌中若持有宝牌则会有对应奖励;日麻胡牌需要满足特定条件,即为“役”,无役无法胡牌。

设计思路

在这里插入图片描述

效果展示

开始界面

玩家进入游戏后,首先会来到登录界面,登录界面中有我为这个游戏所设计的一个 Logo。此时玩家需要在 ID 栏中输入自己的 ID,并选择登录。登录后会来到欢迎界面,并提示玩家可以选择开始游戏
在这里插入图片描述
在这里插入图片描述

游戏界面

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码展示

基础操作

import copy
import pygame
import random
from GameTable import Gametable
from Rule import huJudge
from pygame.locals import *
from sys import exit


class Mahjong():
    def __init__(self):
        self.__clock = pygame.time.Clock()
        self.screenSet()   # 游戏画面设置
        self.playerSet()   # 玩家设置
        self.sitSet()      # 座次设置
        self.gameStart()   # 游戏开始

    def screenSet(self):
        pygame.init()
        screen = pygame.display.set_mode((600, 400))
        # screen 的本质上就是一个 Surface 对象,它是游戏的主窗口,
        # 也就是整个游戏中尺寸最大的“纸”,任何其他的 Surface 对象都需要附着在这张最大的“纸”上
        pygame.display.set_caption('Mahjong 源码领取QQ群:494958217')

    def playerSet(self):
        # self.__playername = input("请输入您的昵称:")
        self.__playername = "飞翔大神天使"   # 方便测试用
        print("您好,{}!欢迎来到麻将世界!".format(self.__playername))

    def sitSet(self):
        self.__sit = random.randint(0, 3)
        # self.__sit = 3
        print("您这把{}起!".format("东南西北"[self.__sit]))

    def prepare(self):
        print("\n\n正在清理牌桌...")
        self.__table = Gametable()    # 清理牌桌
        print("正在获取初始手牌...")
        self.__hands = self.getfHands(self.__sit)
        print(self.__hands)

    def reset(self):
        print("\n\n正在清理牌桌...")
        self.__table = Gametable()  # 清理牌桌
        print("正在获取初始手牌...")
        self.__hands = self.getfHands(self.__sit)
        print(self.__hands)

    def getfHands(self, sit):
        hands = []
        base = (sit-1) * 4   # 摸牌起始位置
        # 东起 0,南起 4, 西起 8, 北起 12
        for i in range(3):  # 分3次摸2垛
            hands.append(self.__table.getTiles()[i * 16 + base])
            hands.append(self.__table.getTiles()[i * 16 + base + 1])
            hands.append(self.__table.getTiles()[i * 16 + base + 2])
            hands.append(self.__table.getTiles()[i * 16 + base + 3])
        hands.append(self.__table.getTiles()[48 + base])
        self.handsSort(hands)
        return hands

    def handsSort(self, hands):
        hands.sort(key=Gametable.tiles.index)
        return hands

    def gameStart(self):
        self.__game_num = 0       # 当前对局数
        # self.__current_turn = 0   # 当前局数
        self.__wind = "东"        # 从东场开始
        gamepara = self.__sit     # 参数记录起始位置
        while(self.__game_num < 8):
            self.reset()          # 准备下一局对局
            print("sit:", self.__sit, "gamenum:", self.__game_num)
            self.__sit = (gamepara - self.__game_num) % 4

            print("欢迎来到{}{}场!".format(self.__wind, self.__game_num % 4 + 1))

            print("您这把是{}家.".format("东南西北"[self.__sit]))
            self.__game_num += 1
            if self.__game_num % 4 == 0:
                self.__wind = "南"    # 进行4局后进入南场
            if self.game() == 0:     # 连庄则对局数不增加
                self.__game_num -= 1

    def game(self):
        winner = -1
        print("本局的宝牌指示牌为:", self.__table.getDoraPointer()[0])
        self.__cardremain = 70   # 牌山余量
        self.__cardgiver = 0     # 当前出牌人
        self.__tilepointer = 52  # 牌山位置指针
        self.__GangCount = 0     # 记录开杠次数
        self.__Ganglist = []     # 杠牌
        self.__Chowlist = []     # 吃牌
        self.__PUNGlist = []     # 碰牌
        self.__Reddora = [0, 0, 0]  # 是否有赤宝牌
        while(self.__cardremain > 0 and winner == -1):
            brand = self.cardplay(self.__cardgiver)
            if brand == "自摸":
                return self.__sit
            if self.__cardgiver % 4 != self.__sit:
                self.can_gang(brand)
                self.can_pung(brand)
                if self.__cardgiver % 4 == (self.__sit + 3) % 4:
                    self.can_chow(brand)
                winner = self.can_Hu(brand)
            self.__cardgiver += 1
        return winner

    def cardplay(self, giver):
        self.__cardremain -= 1
        self.__tilepointer += 1
        curCard = self.__table.getTiles()[self.__tilepointer - 1]
        if giver % 4 != self.__sit:
            print("{}家打出{}".format("东南西北"[giver % 4], curCard))
            return self.__table.getTiles()[self.__tilepointer - 1]  # 如果不是玩家直接摸切
        # 如果是玩家本人
        self.handsShow()
        print("您摸到了:", curCard)
        # 判断是否能开杠
        self.can_gang(curCard)
        # 判断是否自摸
        if self.can_Hu(curCard, 1) != -1:
            return "自摸"

        self.__hands.append(curCard)
        self.brand()  # 舍牌
        self.handsSort(self.__hands)
        self.handsShow()
        print()

    def can_gang(self, card):
        if self.__cardremain == 0 or self.__GangCount == 4:
            return False
        if card not in self.__hands:
            return False
        index = self.__hands.index(card)
        if index > len(self.__hands) - 3:
            return False
        if self.__hands[index] == self.__hands[index + 1] == self.__hands[index + 2]:
            ifGANG = input("杠?Y/N")
            if ifGANG in "Yy1":
                self.GANG(card)
            return True
        return False

    def GANG(self, card):
        self.__cardremain -= 1
        self.__GangCount += 1
        self.__cardgiver = self.__sit
        for _ in range(3):
            self.__hands.remove(card)
        print("新的宝牌指示牌为:", self.__table.getDoraPointer()[self.__GangCount])
        self.cardplay(self.__sit)
        self.__Ganglist.append(card)
        self.__hands.append(self.__table.getTiles()[-self.__GangCount])

    def can_pung(self, card):
        if card not in self.__hands:
            return False
        index = self.__hands.index(card)
        if index > len(self.__hands) - 2:
            return False
        if self.__hands[index] == self.__hands[index + 1]:
            ifPUNG = input("碰?Y/N")
            if ifPUNG in "Yy1":
                self.PUNG(card)
            return True
        return False

    def PUNG(self, card):
        self.__cardgiver = self.__sit
        for _ in range(2):
            self.__hands.remove(card)
        self.__PUNGlist.append(card)
        self.brand()
        self.handsShow()
        print()

    def can_chow(self, card):
        if card[0] in "fd":
            return
        lis = []
        canchow = []
        num = int(card[0])
        for i in self.__hands:
            if i[1] == card[1]:
                lis.append(int(i[0]))
        lis.sort()
        # case 1: 1 2 (3)
        if num > 2:
            if num-1 in lis and num-2 in lis:
                print(str(num - 2)+card[1] + str(num - 1)+card[1] + card, card, end="  ")
                canchow.append(0)
        # case 2: 1 (2) 3
        if num > 1:
            if num-1 in lis and num+1 in lis:
                print(str(num - 1)+card[1] + card + str(num + 1)+card[1], card, end="  ")
                canchow.append(1)
        # case 3: (1) 2 3
        if num < 8:
            if num+1 in lis and num+2 in lis:
                print(card + str(num + 1)+card[1] + str(num + 2)+card[1], card, end="  ")
                canchow.append(2)

        if len(canchow) == 1:
            ifCHOW = input("吃?Y/N")
            if ifCHOW in "Yy1":
                self.CHOW(card, 0, canchow)
        elif len(canchow) > 1:
            ifCHOW = input("吃?1-{}/N".format(len(canchow)))
            if ifCHOW in "123":
                self.CHOW(card, eval(ifCHOW)-1, canchow)
        return canchow

    def CHOW(self, card, mode, lis):
        self.__cardgiver = self.__sit
        mode = lis[mode]
        if mode == 0:  # case 1: 1 2 (3)
           for i in [str(int(card[0])-2)+card[1], str(int(card[0])-1)+card[1], card]:
               if i != card:
                   self.__hands.remove(i)
               self.__Chowlist.append(i)
        elif mode == 1:  # case 2: 1 (2) 3
           for i in [str(int(card[0])-1)+card[1], card, str(int(card[0])+1)+card[1]]:
               if i != card:
                   self.__hands.remove(i)
               self.__Chowlist.append(i)
        elif mode == 2:  # case 3: (1) 2 3
           for i in [card, str(int(card[0])+1)+card[1], str(int(card[0])+2)+card[1]]:
               if i != card:
                   self.__hands.remove(i)
               self.__Chowlist.append(i)
        self.brand()
        self.handsShow()
        print()

    def can_Hu(self, card, Self=0):
        handstry = copy.deepcopy(self.__hands)
        handstry.append(card)
        if huJudge(self.handsSort(handstry), self.__Chowlist, self.__PUNGlist, self.__Ganglist):
            if Self:
                ifHU = input("自摸?Y/N")
            else:
                ifHU = input("胡?Y/N")
            if ifHU in "Yy1":
                self.__hands = handstry
                self.HU(handstry)
                return self.__sit
        return -1

    def HU(self, hands):
        print("胡牌手牌:", end='')
        self.handsShow()
        print("恭喜{}家获得胜利!".format("东南西北"[self.__sit]))

    def handsShow(self):
        print(self.__hands, end='  ')
        if self.__Ganglist != []:
            print("已杠:", end='')
            for i in self.__Ganglist:
                print(i*4, end=' ')
        if self.__PUNGlist != []:
            print("已碰:", end='')
            for i in self.__PUNGlist:
                print(i*3, end=' ')
        if self.__Chowlist != []:
            print("已吃:", end='')
            count = 0
            for i in self.__Chowlist:
                count += 1
                print(i, end='')
                if count % 3 == 0:
                    print(end=' ')

    def brand(self):
        brand = input("您要打出?")  # 舍牌
        if brand in self.__hands:
            self.__hands.remove(brand)
        elif brand in [str(i) for i in range(1, len(self.__hands)+1)]:
            self.__hands.pop(eval(brand) - 1)
        else:
            self.__hands.pop()


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284

胡牌算法

def huJudge(hands, Chowlis, Punglis, Ganglis):
count = len(Chowlis)/3 + len(Punglis) + len(Ganglis)
if count == 0:
if nanaJudge(hands) or kokushimusoJudge(hands):
return True
return tanyaoJudge(hands, count)
def nanaJudge(hands):
i = 0
temp = "0"
while i < 12:
if temp == hands[i]:
return False
if hands[i] != hands[i+1]:
return False
temp = hands[i]
i += 2
return True
def kokushimusoJudge(hands):
handscopy = copy.deepcopy(hands)
yaolist = ["1m", "9m", "1p", "9p", "1s", "9s", "d1", "d2", "d3",
"f1", "f2", "f3", "f4"]
for i in yaolist:
if i in handscopy:
handscopy.remove(i)
if len(handscopy) == 1 and handscopy[0] in yaolist:
return True
else:
return False
def tanyaoJudge(hands, count):
for i in hands:
if i[0] in "19fd":
return False
i = 0
while(i < len(hands)-1):
handscopy = copy.deepcopy(hands)
if hands[i] == hands[i + 1]:
handscopy.pop(i+1)
handscopy.pop(i)
if NormalJudge(handscopy, count):
return True
i += 1
return False
def NormalJudge(hands, count): # 如果是一般型
i = 0
while count < 4 and i < len(hands) - 2:
if hands[i+2] == hands[i+1] == hands[i]: # 刻子判断
count += 1
for _ in range(3):
hands.pop(i)
i -= 1
else: # 顺子判断
if str(int(hands[i][0])+1) + hands[i][1] in hands and
str(int(hands[i][0])+2) + hands[i][1] in hands:
count += 1
hands.remove(str(int(hands[i][0]) + 1) + hands[i][1])
hands.remove(str(int(hands[i][0]) + 2) + hands[i][1])
hands.pop(i)
i -= 1
else:
return False
i += 1
return True
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/378332
推荐阅读
相关标签
  

闽ICP备14008679号