游戏棋盘当前状态保存与下一步可行状态生成技术求助
棋盘状态保存与可行状态生成方案
一、先优化棋盘的存储方式
你现在把棋盘拆成单独的row1~row5列表,后续操作会很麻烦。建议直接用二维列表存储整个棋盘,不管是保存状态还是遍历操作都更方便。
优化后的初始化代码
def initialize(lines): board = [] for line in lines: # 去掉每行首尾的换行、空格,再转成列表 cleaned_line = line.strip() board.append(list(cleaned_line)) return board
调用后会得到一个5行4列的二维列表,比如初始状态就是:
[ ['3', '1', '1', '3'], ['3', '1', '1', '3'], ['3', '2', '2', '3'], ['3', '4', '4', '3'], ['4', '0', '0', '4'] ]
要保存当前状态,必须用深拷贝,因为直接赋值是引用传递,修改新列表会影响原状态。用copy模块的deepcopy就行:
import copy current_state = initialize(Lines) saved_state = copy.deepcopy(current_state)
二、生成所有可行的下一步状态
核心逻辑是:先找到所有空白格(0),然后检查空白格四周的棋子是否符合移动规则,符合的话就生成新的棋盘状态。
先明确各棋子的移动规则
- 棋子1:2x2大棋子,需整体移动,移动方向上要有足够的空白区域容纳它
- 棋子2:水平1x2,只能左右移动,移动时两个格子整体移动
- 棋子3:垂直1x2,只能上下移动,移动时两个格子整体移动
- 棋子4:单格,可上下左右移动,只要相邻是空白格就能交换位置
实现代码示例
import copy def get_all_next_states(current_board): next_states = [] rows = len(current_board) cols = len(current_board[0]) if rows else 0 # 先找到所有空白格的坐标 empty_pos = [(i, j) for i in range(rows) for j in range(cols) if current_board[i][j] == '0'] for empty_i, empty_j in empty_pos: # 检查空白格的上下左右四个方向 directions = [(-1,0), (1,0), (0,-1), (0,1)] for di, dj in directions: piece_i = empty_i + di piece_j = empty_j + dj # 确保棋子坐标在棋盘范围内 if not (0 <= piece_i < rows and 0 <= piece_j < cols): continue piece_type = current_board[piece_i][piece_j] if piece_type == '0': continue # 跳过空白格 new_board = copy.deepcopy(current_board) can_move = False # 处理单格棋子4 if piece_type == '4': # 直接和空白格交换位置 new_board[empty_i][empty_j] = '4' new_board[piece_i][piece_j] = '0' can_move = True # 处理2x2的大棋子1 elif piece_type == '1': # 先定位大棋子的左上角坐标(它占据4个格子) ones = [(x,y) for x in range(rows) for y in range(cols) if current_board[x][y] == '1'] min_i = min(x for x,y in ones) min_j = min(y for x,y in ones) # 尝试向下移动:需要下方两行对应列是空白 if di == 1: if min_i + 2 < rows and current_board[min_i+2][min_j] == '0' and current_board[min_i+2][min_j+1] == '0': # 清除原位置的1,设置新位置的1 for x,y in ones: new_board[x][y] = '0' new_board[min_i+1][min_j] = '1' new_board[min_i+1][min_j+1] = '1' new_board[min_i+2][min_j] = '1' new_board[min_i+2][min_j+1] = '1' can_move = True # 同理可实现向上、向左、向右的移动逻辑 # 处理水平双格棋子2 elif piece_type == '2': # 找到同个棋子的另一个格子(水平方向) other_j = piece_j + 1 if dj == -1 else piece_j - 1 if 0 <= other_j < cols and current_board[piece_i][other_j] == '2': # 向左移动:空白格在棋子左侧,且相邻位置也是空白 if dj == 1 and current_board[piece_i][piece_j-1] == '0': new_board[piece_i][piece_j-1] = '2' new_board[piece_i][other_j-1] = '2' new_board[piece_i][piece_j] = '0' new_board[piece_i][other_j] = '0' can_move = True # 向右移动:空白格在棋子右侧,且相邻位置也是空白 elif dj == -1 and current_board[piece_i][other_j+1] == '0': new_board[piece_i][piece_j+1] = '2' new_board[piece_i][other_j+1] = '2' new_board[piece_i][piece_j] = '0' new_board[piece_i][other_j] = '0' can_move = True # 处理垂直双格棋子3 elif piece_type == '3': # 找到同个棋子的另一个格子(垂直方向) other_i = piece_i + 1 if di == -1 else piece_i - 1 if 0 <= other_i < rows and current_board[other_i][piece_j] == '3': # 向上移动:空白格在棋子上方,且相邻位置也是空白 if di == 1 and current_board[piece_i-1][piece_j] == '0': new_board[piece_i-1][piece_j] = '3' new_board[other_i-1][piece_j] = '3' new_board[piece_i][piece_j] = '0' new_board[other_i][piece_j] = '0' can_move = True # 向下移动:空白格在棋子下方,且相邻位置也是空白 elif di == -1 and current_board[other_i+1][piece_j] == '0': new_board[piece_i+1][piece_j] = '3' new_board[other_i+1][piece_j] = '3' new_board[piece_i][piece_j] = '0' new_board[other_i][piece_j] = '0' can_move = True # 避免重复状态,添加到列表 if can_move and new_board not in next_states: next_states.append(new_board) return next_states
调用示例
# 从文件读取初始棋盘 with open('board.txt', 'r') as f: Lines = f.readlines() current_board = initialize(Lines) next_states = get_all_next_states(current_board) # 打印所有可行状态 for idx, state in enumerate(next_states): print(f"可行状态 {idx+1}:") for row in state: print(''.join(row)) print("---")
调试建议
- 先测试单格棋子4的移动逻辑,确认能正确生成新状态
- 再逐步完善大棋子1和双格棋子2、3的移动逻辑,每写一部分就调试一次
- 可以打印中间过程的坐标,帮助排查移动逻辑的问题
内容的提问来源于stack exchange,提问作者new_to_python
相关产品推荐
相关产品推荐

