这个函数在定义棋盘类游戏环境的时候经常见到,用来把动作转换成棋盘的行和列。
divmod()
函数是 Python 的内置函数,它接收两个参数(被除数和除数)并返回一对结果,即商和余数。函数返回一个包含两个元素的元组,第一个元素是商,第二个元素是余数。
result = divmod(10, 3)
print(result) # 输出: (3, 1),因为 10 除以 3 的商是 3,余数是 1
result = divmod(-10, 3)
print(result) # 输出: (-4, 2)
result = divmod(10.0, 3)
print(result) # 输出: (3.0, 1.0),这里余数是浮点数
# 注意:当使用浮点数时,最好直接进行除法和取模操作,因为 divmod 对于浮点数可能不会按预期工作。
使用 divmod
函数将一个线性索引转换为一个二维网格的行和列索引:
# 假设有一个 3x3 的网格,要通过线性索引访问它
# 线性索引 0-2 对应第一行,3-5 对应第二行,6-8 对应第三行
# 定义一个函数,将线性索引转换为行和列索引
def linear_to_2d_index(linear_index, width=3):
row, col = divmod(linear_index, width)
return row, col
# 将线性索引转换为行和列
for linear_index in range(9):
row, col = linear_to_2d_index(linear_index)
print(f"线性索引 {linear_index} 对应于 行 {row}, 列 {col}")
# 输出应该是:
# 线性索引 0 对应于 行 0, 列 0
# 线性索引 1 对应于 行 0, 列 1
# 线性索引 2 对应于 行 0, 列 2
# 线性索引 3 对应于 行 1, 列 0
# 线性索引 4 对应于 行 1, 列 1
# 线性索引 5 对应于 行 1, 列 2
# 线性索引 6 对应于 行 2, 列 0
# 线性索引 7 对应于 行 2, 列 1
# 线性索引 8 对应于 行 2, 列 2
写一个井字棋的小环境:
import numpy as np
# 定义一个TicTacToe类,用来模拟井字棋游戏
class TicTacToe:
# 初始化游戏状态
def __init__(self):
self.reset() # 重置游戏到初始状态
# 重置游戏棋盘和玩家状态
def reset(self):
self.state = np.zeros((3, 3), dtype=np.int8) # 3x3的棋盘,初始为空(0)
self.current_player = 1 # 当前玩家设置为1,假设玩家1使用1,玩家2使用-1
self.done = False # 游戏结束标志,初始为False
# 执行一步动作,并更新游戏状态
def step(self, action):
row, col = divmod(action, 3) # 将动作转换为行和列
if self.state[row, col] != 0: # 如果选中的格子已经被占用,则抛出错误
raise ValueError("Invalid move")
self.state[row, col] = self.current_player # 否则,占用该格子
self.done = self.check_win() or self.check_draw() # 检查游戏是否结束
self.current_player *= -1 # 切换当前玩家
return self.state, self.done # 返回新的游戏状态和结束标志
# 检查当前玩家是否赢得游戏
def check_win(self):
# 检查所有行、列和对角线
for i in range(3):
if self.state[i, 0] == self.state[i, 1] == self.state[i, 2] != 0: # 检查行
return True
if self.state[0, i] == self.state[1, i] == self.state[2, i] != 0: # 检查列
return True
if self.state[0, 0] == self.state[1, 1] == self.state[2, 2] != 0: # 检查主对角线
return True
if self.state[0, 2] == self.state[1, 1] == self.state[2, 0] != 0: # 检查副对角线
return True
return False # 如果没有胜利的情况,返回False
# 检查游戏是否平局
def check_draw(self):
return np.all(self.state != 0) # 如果所有格子都被占用,则平局