python實現五子棋遊戲(控制檯版)

一、簡介

  使用python實現控制檯版的五子棋遊戲;

  環境:Windows系統+python3.8.0

  遊戲規則:

    1.分兩位棋手對戰,默認*棋手先下;當按照提示輸入座標(A1),並按回車鍵<Enter>即可在棋盤上顯示下的棋(*);

    2.自動切換到o棋手下棋,當按照提示輸入座標(C1),並按回車鍵<Enter>即可在棋盤上顯示下的棋(o);

    3.輪流切換棋手下棋,當那方先形成5子連線者獲勝(橫、豎、斜、反斜四個方向都可以)。

  遊戲運行界面如下(如果運行後,中文部分顯示亂碼,可右鍵定位到options--Text,修改“Locale”爲“zh_CN”、“Character set”爲“GBK”): 

二、實現過程

  1. 新建文件settings.py,用來定義一些必須的基本屬性和初始值:
    class Settings():
    	def __init__(self):
    		"""初始化的遊戲配置"""
    		# 棋盤格數
    		self.number = 10
    		# 判斷遊戲是否結束(默認開始)
    		self.game_active = True
    		# 判斷哪方下棋
    		self.chess_player = 1
    		# 開始校驗輸贏(兩邊合計9,因爲已經有一邊5步)
    		self.win_number = 0

     

  2. 新建文件checkerboard.py,主要是利用二維列表(數組)存放棋盤數據,棋子位置都用“-”表示;
    class Checkerboard():
    	def __init__(self, ck_settings):
    		self.number = ck_settings.number
    	def draw(self):
    		# 繪製棋盤
    		checkerboard = []
    		for i in range(self.number):
    			checkerboard.append([])
    			for j in range(self.number):
    				checkerboard[i].append('-')
    		return checkerboard

     

  3. 新建文件“game_functions.py”,存放跟遊戲有關的所有業務邏輯函數:
    def printed_board(checkerboard):
    	"""打印棋盤(黃底黑色字體)"""
    	# 設置字體和背景色格式:\033[顯示方式;前景色;背景色m;而後面的\033[0m用來關閉屬性,不加會影響後面
    	print('\033[1;41m--------------簡易五子棋遊戲(控制檯版)---------------\033[0m')
    	print('\033[1;30;43m-------------------------------------------------------')
    	print('     1    2    3    4    5    6    7    8    9    10   ')
    	for i in range(len(checkerboard)):
    		# ord返回字符的ASCII數值,chr再返回字符;end=''設置不換行
    		print(chr(ord('A') + i) + '    ', end='')
    		for j in range(len(checkerboard[i])):
    			print(checkerboard[i][j] + '    ', end='')
    		print()
    	print('-------------------------------------------------------\033[0m')
    
    def update_board(ck_settings, checkerboard, position):
    	"""更新棋盤信息"""
    	if ck_settings.chess_player == 1:
    		print('請棋手*輸入棋子座標(例如A1,輸入exit可退出程序):', end='')
    		check_input(ck_settings, checkerboard, '*', position)
    	else:
    		print('請棋手o輸入棋子座標(例如C1,輸入exit可退出程序):', end='')
    		check_input(ck_settings, checkerboard, 'o', position)
    
    def check_input(ck_settings, checkerboard, char, position):
    	"""校驗輸入數據,正確則把座標打印到棋盤"""
    	inputStr = input() # 獲取輸入數據
    	if len(inputStr) == 0:
    		# 判斷空情況
    		print('\033[1;31m***請輸入座標(例如A1)!***\033[0m')
    	elif inputStr == 'exit':
    		# 退出程序
    		exit()
    	elif not inputStr[1].isdigit():
    		# 第二位不爲數字情況
    		print('\033[1;31m***您輸入的座標不正確,請重新輸入(例如A1)!***\033[0m')	
    	else:
    		# 獲取棋盤下標
    		ch = inputStr[0].upper() # 獲取第一個字符並轉換爲大寫
    		i = ord(ch) - 65 # A的ASCII是65
    		j = int(inputStr[1:3]) - 1 # 最大允許10,所以必須獲取兩位
    		# 判斷是否輸入溢出
    		if (i < 0 or i > 9 or j < 0 or j > 9):
    			print('\033[1;31m***您輸入的座標不正確,請重新輸入(例如A1)!***\033[0m')
    		# 判斷輸入的是否已經有棋子
    		else:
    			if checkerboard[i][j] == '-':
    				# 累計步數(兩邊合計)
    				ck_settings.win_number += 1
    				# 未落子則替換棋手符號,並轉換棋手
    				checkerboard[i][j] = char
    				ck_settings.chess_player *= -1
    				# 合計9步開始校驗輸贏
    				if ck_settings.win_number >= 9:
    					check_stats(ck_settings, checkerboard, (i, j), char, position)				
    			else:
    				print('\033[1;31m***您輸入的座標已經有其他棋子,請重新輸入(例如A1)!***\033[0m')
    
    def check_stats(ck_settings, checkerboard, pos, char, position):
    	"""校驗四個方向,是否有了輸贏"""
    	pos_i, pos_j = pos
    	directs = [(1, 0), (0, 1), (1, 1), (1, -1)]	# 橫、豎、斜、反斜 四個方向檢查	
    	for direct in directs:
    		line_checkerboard = []
    		d_i, d_j = direct
    		# 橫排
    		if d_j == 0:
    			# 橫排成數組
    			for j in range(ck_settings.number):
    				# 判斷是“*”或“o”才添加
    				if checkerboard[pos_i][j] == char:
    					line_checkerboard.append(position(pos_i, j))
    			# print('橫排', line_checkerboard)
    			win_condition(ck_settings, checkerboard, line_checkerboard, d_j, char)
    		elif d_i == 0:
    			# 豎排成數組
    			for i in range(ck_settings.number):
    				# 判斷是“*”或“o”才添加
    				if checkerboard[i][pos_j] == char:
    					line_checkerboard.append(position(i, pos_j))
    			# print('豎排', line_checkerboard)
    			win_condition(ck_settings, checkerboard, line_checkerboard, d_j, char)
    		elif d_i == 1 and d_j == 1:
    			# 斜線成數組			
    			# 左部分
    			minValue = min(pos_i, pos_j) # 獲取較小值
    			for i in range(minValue):
    				# 判斷是“*”或“o”才添加
    				if checkerboard[pos_i - minValue + i][pos_j - minValue + i] == char:
    					line_checkerboard.append(position(pos_i - minValue + i, pos_j - minValue + i))
    			
    			# 右部分
    			maxValue = max(pos_i, pos_j)
    			maxValue = ck_settings.number - maxValue # 獲取可疊加的最大數值
    			for i in range(maxValue):
    				# 判斷是“*”或“o”才添加
    				if checkerboard[pos_i + i][pos_j + i] == char:
    					line_checkerboard.append(position(pos_i + i, pos_j + i))
    			# print('斜線', line_checkerboard)
    			win_condition(ck_settings, checkerboard, line_checkerboard, d_j, char)
    		else:
    			# 反斜線成數組
    			# 左部分
    			minValue = min(ck_settings.number - pos_i, pos_j) # 獲取較小值
    			for i in range(minValue):
    				# 判斷是“*”或“o”才添加
    				if checkerboard[pos_i + minValue - 1 - i][pos_j - minValue + i] == char:
    					line_checkerboard.append(position(pos_i + minValue - 1 - i, pos_j - minValue + i))
    			
    			# 右部分
    			maxValue = min(pos_i, ck_settings.number - pos_j) # 獲取可疊加的最大數值
    			for i in range(maxValue):
    				# 判斷是“*”或“o”才添加
    				if checkerboard[pos_i - i][pos_j + i] == char:
    					line_checkerboard.append(position(pos_i - i, pos_j + i))
    			# print('反斜線', line_checkerboard)
    			win_condition(ck_settings, checkerboard, line_checkerboard, d_j, char)
    
    def win_condition(ck_settings, checkerboard, line_checkerboard, d_j, char):
    	"""判斷是否連續5個一樣"""
    	if len(line_checkerboard) >= 5:
    		for i, item in enumerate(line_checkerboard):
    			index = i + 4
    			if index < len(line_checkerboard):
    				# 橫排情況
    				if d_j == 0:
    					j1 = item.y
    					j2 = line_checkerboard[index].y
    					if (j2 - j1) == 4:
    						printed_board(checkerboard)
    						print('\033[1;32m' + char + '選手獲勝!\033[0m')
    						ck_settings.game_active = False
    						break
    				# 豎排、斜、反斜情況
    				else:
    					i1 = item.x
    					i2 = line_checkerboard[index].x
    					# 取絕對值,因爲反斜線是負數
    					if abs(i2 - i1) == 4:
    						printed_board(checkerboard)
    						print('\033[1;32m' + char + '選手獲勝!\033[0m')
    						ck_settings.game_active = False
    						break

     

  4. 新建文件gobang.py,主函數用來初始化程序,並同步更新程序的信息;
    from settings import Settings
    from checkerboard import Checkerboard
    from collections import namedtuple
    import game_functions as gf
    
    def run_game():
    	"""運行遊戲"""
    	# 配置實例化
    	ck_settings = Settings()
    	# 棋盤實例化並調用繪製方法
    	ck = Checkerboard(ck_settings)
    	checkerboard = ck.draw()
    	# namedtuple創建類似於元組的數據類型,除了可以用索引訪問,能夠迭代,還能用屬性名訪問數據
    	position = namedtuple('Position', ['x', 'y'])
    
    	while ck_settings.game_active:
    		# 打印棋盤
    		gf.printed_board(checkerboard)
    		# 更新棋盤
    		gf.update_board(ck_settings, checkerboard, position)		
    
    run_game()

     

  5. 在文件gobang.py目錄路徑下,執行命令“python gobang.py”打印棋盤,並可對其操作遊玩。
  6. 總結:代碼都有詳盡的備註說明,如果還有不明白,可參考網址https://jingyan.baidu.com/article/5225f26b328388a6fb09084e.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章