人机大战之五子棋 设计储存五子棋类结构及积分规则制定为特定棋型分类给定积分及积分计算步骤以及代码实现对落子位置pxy计算积分即该点的估价函数以及设计五子棋胜负判定设计有代码
一、五子棋类结构设计
五子棋类包含以下属性和方法:
属性:
- 棋盘:二维数组,表示棋盘上每个点的状态,0表示空,1表示黑子,2表示白子。
- 当前玩家:表示当前下棋的玩家。
- 玩家1:表示黑方玩家。
- 玩家2:表示白方玩家。
方法:
- 初始化棋盘:将棋盘上所有点的状态设置为0。
- 落子:根据当前玩家下棋,将对应位置的状态设置为1或2。
- 判断胜负:根据棋盘状态判断当前局面是否有胜负。
- 切换玩家:切换当前下棋的玩家。
代码如下:
class Gobang: def init(self, player1, player2): self.board = [[0 for i in range(15)] for j in range(15)] self.current_player = player1 self.player1 = player1 self.player2 = player2
def drop_piece(self, x, y):
if self.current_player == self.player1:
self.board[x][y] = 1
self.current_player = self.player2
else:
self.board[x][y] = 2
self.current_player = self.player1
def check_win(self):
for i in range(15):
for j in range(15):
if self.board[i][j] == 0:
continue
if i + 4 < 15 and self.board[i][j] == self.board[i+1][j] == self.board[i+2][j] == self.board[i+3][j] == self.board[i+4][j]:
return self.board[i][j]
if j + 4 < 15 and self.board[i][j] == self.board[i][j+1] == self.board[i][j+2] == self.board[i][j+3] == self.board[i][j+4]:
return self.board[i][j]
if i + 4 < 15 and j + 4 < 15 and self.board[i][j] == self.board[i+1][j+1] == self.board[i+2][j+2] == self.board[i+3][j+3] == self.board[i+4][j+4]:
return self.board[i][j]
if i - 4 >= 0 and j + 4 < 15 and self.board[i][j] == self.board[i-1][j+1] == self.board[i-2][j+2] == self.board[i-3][j+3] == self.board[i-4][j+4]:
return self.board[i][j]
return 0
def switch_player(self):
if self.current_player == self.player1:
self.current_player = self.player2
else:
self.current_player = self.player1
二、积分规则制定
在五子棋中,每个位置的价值是不同的,有些位置更有利于下棋。因此需要制定一些积分规则,对每个位置进行估价,以便选择更优的落子位置。
积分规则有很多种,这里只列举几个常用的规则:
- 基本规则
- 空位:基本分数为1分。
- 已有棋子的位置:分数为0分。
- 位置较为靠近中心的位置:分数较高。
- 连子规则
- 单子:基本分数为10分。
- 活二:基本分数为100分。
- 死二:基本分数为50分。
- 活三:基本分数为1000分。
- 死三:基本分数为100分。
- 活四:基本分数为10000分。
- 死四:基本分数为1000分。
- 活五:基本分数为100000分。
- 棋型规则
- 眠二:如果一个位置可以形成两个死二,分数为100分。
- 眠三:如果一个位置可以形成两个死三,分数为1000分。
- 眠四:如果一个位置可以形成两个死四,分数为10000分。
以上规则只是基本规则,根据实际情况可以进行调整。
三、特定棋型分类给定积分及积分计算步骤
给定特定棋型的积分,可以根据棋盘上的棋子情况计算当前位置的积分。具体步骤如下:
-
判断当前位置是否为空,如果不为空直接返回0分。
-
根据当前位置向四个方向(水平、竖直、左上到右下、右上到左下)扩展,记录每个方向的棋子数和空位数。
-
根据每个方向的棋子数和空位数,确定棋型,给出相应的积分。
-
将四个方向的积分相加,得到当前位置的总积分。
代码如下:
class Score: def init(self): self.patterns = { (1, 0, 0, 0, 0): 10, # 单子 (1, 1, 0, 0, 0): 100, # 活二 (0, 1, 1, 0, 0): 100, # 活二 (0, 0, 1, 1, 0): 100, # 活二 (0, 0, 0, 1, 1): 100, # 活二 (2, 1, 0, 0, 0): 50, # 死二 (1, 2, 0, 0, 0): 50, # 死二 (0, 1, 2, 0, 0): 50, # 死二 (0, 0, 1, 2, 0): 50, # 死二 (0, 0, 0, 1, 2): 50, # 死二 (1, 1, 1, 0, 0): 1000, # 活三 (1, 1, 0, 1, 0): 1000, # 活三 (1, 0, 1, 1, 0): 1000, # 活三 (0, 1, 1, 1, 0): 1000, # 活三 (2, 1, 1, 0, 0): 100, # 死三 (1, 2, 1, 0, 0): 100, # 死三 (1, 1, 2, 0, 0): 100, # 死三 (0, 1, 1, 2, 0): 100, # 死三 (0, 0, 1, 1, 2): 100, # 死三 (3, 1, 0, 0, 0): 10000, # 活四 (1, 3, 0, 0, 0): 10000, # 活四 (1, 0, 3, 0, 0): 10000, # 活四 (0, 1, 3, 0, 0): 10000, # 活四 (0, 0, 1, 3, 0): 10000, # 活四 (0, 0, 0, 1, 3): 10000, # 活四 (2, 2, 0, 0, 0): 1000, # 死四 (2, 1, 1, 0, 0): 1000, # 死四 (1, 2, 1, 0, 0): 1000, # 死四 (1, 1, 2, 0, 0): 1000, # 死四 (0, 2, 2, 0, 0): 1000, # 死四 (0, 1, 2, 1, 0): 1000, # 死四 (0, 1, 1, 2, 0): 1000, # 死四 (0, 0, 2, 2, 0): 1000, # 死四 (0, 0, 1, 2, 1): 1000, # 死四 (1, 1, 1, 1, 0): 100000, # 活五 (1, 1, 1, 0, 1): 100000, # 活五 (1, 1, 0, 1, 1): 100000, # 活五 (1, 0, 1, 1, 1): 100000, # 活五 }
def calculate_score(self, board, x, y):
if board[x][y] != 0:
return 0
total_score = 0
for dx, dy in [(0, 1), (1, 0), (1, 1), (1, -1)]:
count = [0, 0, 0, 0, 0]
for i in range(1, 5):
tx, ty = x + i*dx, y + i*dy
if tx < 0 or tx >= 15 or ty < 0 or ty >= 15:
break
count[board[tx][ty]] += 1
score = self.patterns.get(tuple(count), 0)
total_score += score
return total_score
四、落子位置的估价函数实现
落子位置的估价函数就是根据积分规则和特定棋型的积分来计算当前位置的积分。具体实现如下:
class Evaluator: def init(self): self.score = Score()
def evaluate(self, board):
values = [[0 for i in range(15)] for j in range(15)]
for i in range(15):
for j in range(15):
values[i][j] = self.score.calculate_score(board, i, j)
return values
五、五子棋胜负判定设计
判断胜负的方法已经在五子棋类中实现了,代码如下:
def check_win(self): for i in range(15): for j in range(15): if self.board[i][j] == 0: continue if i + 4 < 15 and self.board[i][j] == self.board[i+1][j] == self.board[i+2][j] == self.board[i+3][j] == self.board[i+4][j]: return self.board[i][j] if j + 4 < 15 and self.board[i][j] == self.board[i][j+1] == self.board[i][j+2] == self.board[i][j+3] == self.board[i][j+4]: return self.board[i][j] if i + 4 < 15 and j + 4 < 15 and self.board[i][j] == self.board[i+1][j+1] == self.board[i+2][j+2] == self.board[i+3][j+3] == self.board[i+4][j+4]: return self.board[i][j] if i - 4 >= 0 and j + 4 < 15 and self.board[i][j] == self.board[i-1][j+1] == self.board[i-2][j+2] == self.board[i-3][j+3] == self.board[i-4][j+4]: return self.board[i][j] return 0
如果返回值为1,则黑方胜利;如果返回值为2,则白方胜利;如果返回值为0,则表示当前局面没有胜负
原文地址: https://www.cveoy.top/t/topic/eolO 著作权归作者所有。请勿转载和采集!