用python写一个麻将游戏
时间: 2023-07-18 16:38:04 浏览: 318
下面是一个简单的Python麻将游戏实现,使用了Python标准库中的`random`和`collections`模块:
```python
import random
import collections
# 初始化牌堆
tiles = collections.Counter()
for i in range(1, 10):
for j in range(4):
tiles[str(i) + 'm'] += 1
tiles[str(i) + 'p'] += 1
tiles[str(i) + 's'] += 1
tiles['dong'] += 1
tiles['nan'] += 1
tiles['xi'] += 1
tiles['bei'] += 1
tiles['zhong'] += 1
tiles['fa'] += 1
tiles['bai'] += 1
# 定义牌局类
class Game:
def __init__(self, players):
self.players = players
self.winner = None
self.turn = 0
self.hand_tiles = [[] for _ in range(len(players))]
self.draw_tile = None
self.discard_tile = None
self.last_discard = None
self.river = collections.Counter()
# 生成一张牌
def draw(self):
tile = random.choice(list(tiles.elements()))
tiles.subtract(tile)
return tile
# 发牌
def deal(self):
for i in range(13):
for j in range(len(self.players)):
self.hand_tiles[j].append(self.draw())
# 玩家摸牌
def draw_from_wall(self, player):
self.draw_tile = self.draw()
self.hand_tiles[player].append(self.draw_tile)
# 玩家打牌
def discard(self, player, tile):
self.discard_tile = tile
self.hand_tiles[player].remove(tile)
self.river[tile] += 1
self.last_discard = player
# 碰牌
def pong(self, player):
tile_count = collections.Counter(self.hand_tiles[player])
for tile, count in tile_count.items():
if count == 2 and self.discard_tile == tile:
self.hand_tiles[player].remove(tile)
self.hand_tiles[player].remove(tile)
self.river[tile] += 3
self.last_discard = None
return True
return False
# 吃牌
def chow(self, player, tiles):
if (
self.last_discard is not None and
self.last_discard != player and
self.draw_tile is None
):
tile_set = set(tiles)
last_tile = self.hand_tiles[self.last_discard][-1]
last_tile_num = int(last_tile[0])
if last_tile_num > 2 and last_tile_num < 8:
chow_tiles = [str(last_tile_num - 2) + last_tile[1], last_tile, str(last_tile_num + 2) + last_tile[1]]
chow_tiles_set = set(chow_tiles)
if tile_set == chow_tiles_set:
for tile in chow_tiles:
self.hand_tiles[player].remove(tile)
self.river[last_tile] += 1
self.last_discard = None
return True
return False
# 杠牌
def kong(self, player):
tile_count = collections.Counter(self.hand_tiles[player])
for tile, count in tile_count.items():
if count == 3:
self.hand_tiles[player].remove(tile)
self.hand_tiles[player].remove(tile)
self.hand_tiles[player].remove(tile)
self.river[tile] += 4
self.draw_from_wall(player)
self.last_discard = None
return True
return False
# 胡牌
def is_win(self, player):
tile_count = collections.Counter(self.hand_tiles[player])
for tile in tile_count:
if self._is_win_with_pair(player, tile_count - collections.Counter([tile])):
return True
return False
# 判断是否可以胡牌
def _is_win_with_pair(self, player, tile_count):
if sum(tile_count.values()) == 0:
return True
tile_list = sorted(tile_count)
for i, tile in enumerate(tile_list):
if tile_count[tile] >= 2:
new_tile_count = tile_count - collections.Counter([tile, tile])
if self._is_win_without_pair(player, new_tile_count):
return True
if i < len(tile_list) - 2 and tile_list[i] == tile_list[i+1] - 1 and tile_list[i+1] == tile_list[i+2] - 1:
new_tile_count = tile_count - collections.Counter([tile_list[i], tile_list[i+1], tile_list[i+2]])
if self._is_win_with_pair(player, new_tile_count):
return True
return False
# 判断是否可以胡牌(没有将牌)
def _is_win_without_pair(self, player, tile_count):
if sum(tile_count.values()) == 0:
return True
tile_list = sorted(tile_count)
for i, tile in enumerate(tile_list):
if tile_count[tile] >= 3:
new_tile_count = tile_count - collections.Counter([tile, tile, tile])
if self._is_win_without_pair(player, new_tile_count):
return True
if i < len(tile_list) - 2 and tile_list[i] == tile_list[i+1] - 1 and tile_list[i+1] == tile_list[i+2] - 1:
new_tile_count = tile_count - collections.Counter([tile_list[i], tile_list[i+1], tile_list[i+2]])
if self._is_win_without_pair(player, new_tile_count):
return True
return False
# 执行一轮游戏
def play(self):
# 初始化牌局
self.deal()
self.turn = 0
# 主循环
while True:
# 玩家摸牌
self.draw_from_wall(self.turn)
# 输出玩家手牌和河
print('玩家', self.turn + 1, '的手牌:', self.hand_tiles[self.turn])
print('河:', self.river)
# 玩家打牌
discard_tile = input('请玩家' + str(self.turn + 1) + '打牌:')
self.discard(self.turn, discard_tile)
# 碰牌
while True:
if self.pong(self.turn):
print('玩家', self.turn + 1, '碰了', self.discard_tile)
break
else:
break
# 吃牌
while True:
tiles = input('请玩家' + str(self.turn + 1) + '选择要吃的牌(例如:234):')
if self.chow(self.turn, tiles):
print('玩家', self.turn + 1, '吃了', tiles)
break
else:
break
# 杠牌
while True:
if self.kong(self.turn):
print('玩家', self.turn + 1, '杠了', self.discard_tile)
break
else:
break
# 胡牌
if self.is_win(self.turn):
print('玩家', self.turn + 1, '胡了!')
self.winner = self.turn
break
# 下一个玩家
self.turn = (self.turn + 1) % len(self.players)
# 输出胜者
print('玩家', self.winner + 1, '获胜!')
# 运行游戏
game = Game(['A', 'B', 'C', 'D'])
game.play()
```
在这个游戏中,我们定义了一个`Game`类来管理牌局,并实现了发牌、摸牌、打牌、碰牌、吃牌、杠牌和胡牌等功能。在主循环中,程序会依次轮流让每个玩家摸牌、打牌和执行其他操作,直到有玩家胡牌。运行程序后,程序会提示玩家进行操作,并输出当前牌局状态和操作结果。
阅读全文