python实现五子棋游戏(pygame版)

目录

  • 简介
  • 实现过程
  • 结语

简介

使用python实现pygame版的五子棋游戏;

  环境:Windows系统+python3.8.0

  游戏规则:

    1.分两位棋手对战,默认黑棋先下;当在棋盘点击左键,即在该位置绘制黑棋;

    2.自动切换到白棋,当在棋盘点击左键,即在该位置绘制白棋;

    3.轮流切换棋手下棋,当那方先形成5子连线者获胜(横、竖、斜、反斜四个方向都可以)。

  游戏运行效果如下:

实现过程

  1. 新建文件settings.py,用来定义一些必须的基本属性和初始值;
    class Settings():
    	def __init__(self):
    		"""初始化的游戏配置"""
    		# 屏幕宽高
    		self.width = 700
    		self.height = 554
    		# 文字颜色和大小
    		self.fontsize = 14
    		self.fonttype = 'simsunnsimsun'
    		# 棋盘格数
    		self.number = 15
    		# 棋盘左边距、上边距和间隔
    		self.bd_left = 30
    		self.bd_top = 30
    		self.bd_space = 36
    		# 判断游戏是否结束(默认开始)
    		self.game_active = True
    		# 判断哪方下棋(默认黑子先写)
    		self.chess_player = 1
    		self.prompt_info = '当前棋手:黑棋'
    		# 开始校验输赢(两边合计9,因为已经有一边5步)
    		self.win_number = 0
    		# 设置背景图、黑棋图片、白棋图片路径
    		self.checkerboard_bg = 'images/checkerboard_bg.png'
    		self.black_chess = 'images/black_chess.png'
    		self.white_chess = 'images/white_chess.png'
    		# 存储落子数据
    		self.move_chess = []

  2. 新建文件checkerboard.py,主要用来绘制背景图和棋格线;
    import sys
    import pygame
    
    class Checkerboard():
    	def __init__(self, ck_settings, screen, position):
    		self.ck_settings = ck_settings
    		self.screen = screen
    		self.position = position
    		
    		# 颜色和坐标大小
    		self.text_color = (0, 0, 0)
    		self.font = pygame.font.SysFont(ck_settings.fonttype, ck_settings.fontsize)
    		# 存储棋子坐标
    		self.checkerboard = []
    		# 加载背景图、黑棋和白棋(当有图片不存在时,打印错误并退出游戏)
    		try:
    			self.bg_image = pygame.image.load(ck_settings.checkerboard_bg)		
    			self.black_image = pygame.image.load(ck_settings.black_chess).convert_alpha() # convert_alpha背景透明
    			self.white_image = pygame.image.load(ck_settings.white_chess).convert_alpha()
    			self.chess_rect = self.black_image.get_rect()
    		except Exception as e:
    			print('error:', e)
    			sys.exit()
    
    	def draw_board(self):		
    		# 存储棋子坐标		
    		for i in range(self.ck_settings.number):
    			self.checkerboard.append([])
    			for j in range(self.ck_settings.number):
    				self.checkerboard[i].append(self.position(self.ck_settings.bd_left + i * self.ck_settings.bd_space, self.ck_settings.bd_top + j * self.ck_settings.bd_space))
    		# 绘制棋盘坐标
    		for i in range(0, self.ck_settings.number):
    			# ord返回字符的ASCII数值,chr再返回字符
    			x_text = self.font.render(chr(ord('A') + i), True, self.text_color) # A-O
    			y_text = self.font.render(str(i + 1), True, self.text_color) # 1-15
    
    			# 绘制xy轴坐标(在棋盘背景图绘制)
    			self.bg_image.blit(x_text, (self.checkerboard[i][0].x - x_text.get_width() / 2, self.checkerboard[i][0].y - 20))
    			self.bg_image.blit(y_text, (self.checkerboard[0][i].x - 20, self.checkerboard[0][i].y - y_text.get_height() / 2))
    						
    			# 绘制横竖线(在棋盘背景图绘制)
    			pygame.draw.line(self.bg_image, self.text_color, self.checkerboard[0][i], self.checkerboard[self.ck_settings.number-1][i])
    			pygame.draw.line(self.bg_image, self.text_color, self.checkerboard[i][0], self.checkerboard[i][self.ck_settings.number-1])
    		# 绘制棋盘背景图
    		self.screen.blit(self.bg_image, (0, 0))

  3. 新建文件infopanel.py,主要用来绘制棋盘右边提示信息(暂时只有显示下棋方和获胜信息);
    import pygame.font
    class Infopanel():
    	def __init__(self, ck_settings, screen):
    		"""初始化属性"""
    		self.settings = ck_settings
    		self.screen = screen
    		self.screen_rect = screen.get_rect()
    		# 设置文字颜色和字体大小
    		self.info_color = (217, 8, 10)
    		self.font = pygame.font.SysFont(ck_settings.fonttype, 16)
    		
    	def draw_info(self, info):
    		"""将文字渲染为图像,并定位到右边水平居中"""
    		self.info_image = self.font.render(info, True, self.info_color)
    		self.info_image_rect = self.info_image.get_rect()
    		self.info_image_rect.right = self.screen_rect.right - (self.screen_rect.width - 536 - self.info_image_rect.width) / 2
    		self.info_image_rect.top = 50
    		# 绘制到屏幕
    		self.screen.blit(self.info_image, self.info_image_rect)

  4. 新建文件“game_functions.py”,存放跟游戏有关的所有业务逻辑函数;
    import sys
    import pygame
     
    # 棋
    def update_board(ck_settings, cb, index_coordinates, position):
    	"""更新棋盘信息"""
    	# 判断棋手(黑棋或白棋)
    	if ck_settings.chess_player == 1:
    		ck_settings.prompt_info = '当前棋手:白棋'
    		img = cb.black_image
    		chess_type = 'black'
    	else:
    		ck_settings.prompt_info = '当前棋手:黑棋'
    		img = cb.white_image
    		chess_type = 'white'
     
    	"""落棋"""
    	dropState = check_at(ck_settings, index_coordinates)
    	if dropState:
    		i, j = index_coordinates
    		chess_x = cb.checkerboard[j][i].x - cb.chess_rect.width / 2
    		chess_y = cb.checkerboard[j][i].y - cb.chess_rect.height / 2
    		# 累计步数(两边合计)
    		ck_settings.win_number += 1
    		# 落子并转换棋手
    		ck_settings.move_chess.append({'type': chess_type, 'coord': position(i, j)})
    		cb.bg_image.blit(img, (chess_x, chess_y))
    		ck_settings.chess_player *= -1
    		# 合计9步开始校验输赢
    		if ck_settings.win_number >= 9:
    			check_stats(ck_settings, (i, j))			
    	else:
    		ck_settings.prompt_info = '已经有其他棋子'
    		
    
    # 检查(i,j)位置是否已占用	
    def check_at(ck_settings, index_coordinates):
    	for item in ck_settings.move_chess:
    		if index_coordinates == item['coord']:
    			return False
    	return True
     
    def check_stats(ck_settings, pos):
    	"""校验四个方向,是否有了输赢"""
    	pos_i, pos_j = pos
    	directs = [(1, 0), (0, 1), (1, 1), (1, -1)]	# 横、竖、斜、反斜 四个方向检查	
    	for direct in directs:
    		line_checkerboard = []
    		d_x, d_y = direct
     
    		last = ck_settings.move_chess[-1]
    		line_ball = []	# 存放在一条线上的棋子
    		for ball in ck_settings.move_chess:
    			# 跟最后落子判断
    			if ball['type'] == last['type']:
    				x = ball['coord'].x - last['coord'].x 
    				y = ball['coord'].y - last['coord'].y
    				if d_x == 0:
    					if x == 0:
    						line_ball.append(ball['coord'])
    				if d_y == 0:
    					if y == 0:
    						line_ball.append(ball['coord'])
    				if x * d_y == y * d_x:
    					line_ball.append(ball['coord'])
     
    		if len(line_ball) >= 5:	# 只有5子及以上才继续判断
    			sorted_line = sorted(line_ball)
    			for i, item in enumerate(sorted_line): 
    				index = i + 4
    				if index < len(sorted_line):
    					if d_x == 0:
    						y1 = item.y
    						y2 = sorted_line[index].y
    						# 此点和第5个点比较y值,如相差为4则连成5子
    						if abs(y1 - y2) == 4:
    							ck_settings.prompt_info = '黑棋获胜' if last['type'] == 'black' else '白棋获胜'
    					else:
    						x1 = item.x
    						x2 = sorted_line[index].x
    						# 此点和第5个点比较x值,如相差为4则连成5子
    						if abs(x1 - x2) == 4:
    							ck_settings.prompt_info = '黑棋获胜' if last['type'] == 'black' else '白棋获胜'
    				else:
    					break
    		
    # 事件
    def check_events(ck_settings, cb, position):
    	"""监听事件"""
    	for event in pygame.event.get():
    		if event.type == pygame.QUIT:
    			sys.exit()
    		elif event.type == pygame.MOUSEBUTTONDOWN:
    			# 点击左键
    			if event.button == 1:
    				pos = pygame.mouse.get_pos() # 获取点击实际坐标
    				# 判断是否溢出
    				x_first = cb.checkerboard[0][0].x
    				x_last = cb.checkerboard[ck_settings.number - 1][ck_settings.number - 1].x
    				y_first = cb.checkerboard[0][0].y
    				y_last = cb.checkerboard[ck_settings.number - 1][ck_settings.number - 1].y
    				if pos[0] < x_first or pos[0] > x_last or pos[1] < y_first or pos[1] > y_last:
    					ck_settings.prompt_info = '落子位置不正确!'
    				else:
    					index_coordinates = to_index(ck_settings, pos)
    					update_board(ck_settings, cb, index_coordinates, position)
     
    def to_index(ck_settings, pos):
    	"""实际坐标转换为棋盘下标"""
    	i = round((pos[1] - ck_settings.bd_top) / ck_settings.bd_space)
    	j = round((pos[0] - ck_settings.bd_left) / ck_settings.bd_space)
    	return (i, j)
    

  5. 新建文件gobang.py,主函数用来初始化程序,并同步更新程序的信息;
    import pygame
    from settings import Settings
    from checkerboard import Checkerboard
    from collections import namedtuple
    import game_functions as gf
    from infopanel import Infopanel
    
    def run_game():
    	"""运行游戏"""
    	# 初始化游戏屏幕
    	pygame.init()
    	# 创建时钟对象 (可以控制游戏循环频率)
    	clock = pygame.time.Clock()
    	# 配置实例化
    	ck_settings = Settings()	
    	screen = pygame.display.set_mode((ck_settings.width, ck_settings.height))
    	pygame.display.set_caption('五子棋游戏')
    	# namedtuple创建类似于元组的数据类型,除了可以用索引访问,能够迭代,还能用属性名访问数据
    	position = namedtuple('Position', ['x', 'y'])
    	# 创建实例
    	cb = Checkerboard(ck_settings, screen, position)
    	
    	# 实例化面板信息
    	infopanel = Infopanel(ck_settings, screen)
    
    	while ck_settings.game_active:
    		# 绘制棋盘
    		cb.draw_board()
    		# 绘制面板信息
    		infopanel.draw_info(ck_settings.prompt_info)
    		# 检查玩家事件并更新棋盘
    		gf.check_events(ck_settings, cb, position)
    		# 让最近绘制的屏幕可见
    		pygame.display.flip()
    
    		# 通过时钟对象指定循环频率
    		clock.tick(60) # 每秒循环60次
    
    run_game()

  6. 在文件gobang.py目录路径下,执行命令“python gobang.py”弹出窗口,即可对其操作游玩。

结语

该游戏只是实现了基础功能,还有很多可优化的功能:

1.根据实际情况加上更详细的面板信息(比如倒计时等);

2.加上开始游戏按钮,可参考前面python实例;

3.胜负榜单等,可参考前面python实例。

  • 35
    点赞
  • 183
    收藏
    觉得还不错? 一键收藏
  • 44
    评论
### 回答1: 五子棋游戏是一种非常有趣的策略游戏,使用 Python 实现五子棋游戏可以提高你的编程水平,以下是一个简单的示例代码: ```python import numpy as np # 定义棋盘大小 BOARD_SIZE = 15 # 定义棋盘状态 EMPTY = 0 BLACK = 1 WHITE = 2 # 初始化棋盘 board = np.zeros((BOARD_SIZE, BOARD_SIZE), dtype=int) # 定义函数:判断是否胜利 def check_win(player): # 判断行是否连成五子 for i in range(BOARD_SIZE): for j in range(BOARD_SIZE - 4): if board[i][j] == player and board[i][j+1] == player and board[i][j+2] == player and board[i][j+3] == player and board[i][j+4] == player: return True # 判断列是否连成五子 for i in range(BOARD_SIZE - 4): for j in range(BOARD_SIZE): if board[i][j] == player and board[i+1][j] == player and board[i+2][j] == player and board[i+3][j] == player and board[i+4][j] == player: return True # 判断正对角线是否连成五子 for i in range(4, BOARD_SIZE): for j in range(BOARD_SIZE - 4): if board[i][j] == player and board[i-1][j+1] == player and board[i-2][j+2] == player and board[i-3][j+3] == player and board[i-4][j+4] == player: return True # 判断反对角线是否连成五子 for i in range(BOARD_SIZE - 4): for j in range(BOARD_SIZE - 4): if board[i][j] == player and board[i+1][j+1] == player and board[i+2][j+2] == player and board[i+3][j+3] == player and board[i+4][j+4] == player: return True return False # 定义函数:打印棋盘 def print_board(): for i in range(BOARD_SIZE): for j in range(BOARD_SIZE): if board[i][j] == BLACK: print('●', end=' ') elif board[i][j] == WHITE: print('○', end=' ') else: print('+', end=' ') print('') # 游戏开始 print('五子棋游戏开始!') # 定义当前玩家为黑色 current_player = BLACK # 游戏循环 while True: # 打印当前棋盘 print_board() # 询问当前玩家落子位置 while True: try: row = int(input('请输入落子行数(1-{}): '.format(BOARD_SIZE))) - 1 col = int(input('请输入落子列数(1-{}): '.format(BOARD_SIZE))) - 1 if board[row][col] != EMPTY: print('此处已有棋子,请重新输入!') else: break except: print('请输入有效数字!') # 玩家落子 board[row][col] = current_player # 判断是否胜利 if check_win(current_player): print_board() print('玩家 {} 获胜!'.format(current_player)) break # 判断是否平局 if np.count_nonzero(board == EMPTY) == 0: print_board() print('平局!') break # 切换下一个玩家 if current_player == BLACK: current_player = WHITE else: current_player = BLACK ``` 以上示例代码实现五子棋游戏的基本功能,包括棋盘的初始化、落子、判断胜负等。你也可以根据需要对代码进行修改和扩展,实现更多功能。 ### 回答2: 要实现五子棋游戏,首先需要了解五子棋的规则和棋盘的布局。五子棋是一种轮流下子的两人对弈游戏,目标是先在横、竖、斜线上连成五子的一方胜利。 在Python实现五子棋游戏,可以使用图形库如Tkinter或Pygame来创建游戏界面,并用鼠标事件来实现玩家的下子操作。 首先,创建一个棋盘类,包含初始化棋盘、绘制棋盘和判断胜负等方法。初始化棋盘可以使用二维列表表示,每个位置的状态用0表示空,1表示黑子,2表示白子。通过循环绘制网格线和棋子图案来绘制棋盘。判断胜负可以检查横、竖、斜线上是否有连续的五子相同。 然后,创建一个游戏类,包括创建窗口、显示棋盘、切换玩家和处理鼠标点击事件等方法。创建窗口可以使用Tkinter库的相关方法,设置窗口标题和大小。显示棋盘可以调用棋盘类的绘制棋盘方法,并绑定鼠标点击事件。切换玩家可以设置一个变量来表示当前玩家,每次下子后切换变量的值。处理鼠标点击事件可以获取鼠标点击坐标,将其转换为棋盘上的位置,然后调用棋盘类的下子方法进行操作。 最后,创建一个游戏实例并运行游戏循环,通过不断监听鼠标点击事件和刷新屏幕来实现游戏的交互和展示。 通过以上步骤,我们可以利用Python实现一个简单的五子棋游戏,让玩家可以与电脑或其他玩家对战,享受五子棋的乐趣。 ### 回答3: 要实现五子棋游戏,可以使用Python编程语言。下面是一种可能的实现方法: 首先,我们可以使用一个二维列表(即嵌套列表)来表示棋盘。以一个15x15的棋盘为例,可以创建一个15x15的二维列表,将每个元素初始化为空(表示空白格子),表示该位置没有棋子。 接下来,可以定义一个游戏进行的函数,该函数可以接收玩家的输入,更新棋盘,并进行判断胜负的操作。 在游戏开始时,可以打印出初始化的棋盘。玩家可以轮流输入坐标来下棋,比如输入(2,3)表示在第2行第3列下子。可以使用一个变量来表示当前轮到的玩家,比如使用1表示黑棋,2表示白棋。 在每次玩家下棋后,都需要更新棋盘,并检查是否有任何一方胜出。可以编写一个函数来判断当前玩家是否获胜。该函数可以遍历棋盘中的每一个位置,检查每个位置的横向、纵向、正斜线和反斜线上是否有五连续的同色棋子,如果有则表示该玩家胜利。 在更新棋盘和胜负判断之后,需要切换当前玩家,让对方继续下棋,直到有一方获胜或者棋盘下满。如果棋盘下满仍然没有获胜者,则游戏结束,宣布平局。 以上就是使用Python实现五子棋游戏的基本思路。当然,还可以优化游戏体验,比如增加游戏界面的美观性、提供悔棋和重新开始的功能等。
评论 44
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值