mirror of
https://github.com/InternLM/InternBootcamp.git
synced 2026-04-28 17:29:37 +00:00
init-commit
This commit is contained in:
commit
18a552597a
3461 changed files with 1150579 additions and 0 deletions
0
internbootcamp/libs/starbattle/__init__.py
Executable file
0
internbootcamp/libs/starbattle/__init__.py
Executable file
95
internbootcamp/libs/starbattle/dfs_solver.py
Executable file
95
internbootcamp/libs/starbattle/dfs_solver.py
Executable file
|
|
@ -0,0 +1,95 @@
|
|||
import random
|
||||
|
||||
|
||||
def print_grid(grid, stars=None):
|
||||
if stars is None:
|
||||
stars = []
|
||||
for i, row in enumerate(grid):
|
||||
row_str = ''
|
||||
for j, cell in enumerate(row):
|
||||
if (i, j) in stars:
|
||||
row_str += '★ '
|
||||
else:
|
||||
row_str += f'{cell:2} ' # Format the number to take up two spaces
|
||||
print(row_str)
|
||||
print()
|
||||
|
||||
def find_shapes(grid):
|
||||
shapes = {}
|
||||
for i, row in enumerate(grid):
|
||||
for j, cell in enumerate(row):
|
||||
if cell not in shapes:
|
||||
shapes[cell] = []
|
||||
shapes[cell].append((i, j))
|
||||
return shapes
|
||||
|
||||
def can_place_star(star_positions, pos):
|
||||
row, col = pos
|
||||
|
||||
for star_row, star_col in star_positions:
|
||||
if (star_row == row or star_col == col or
|
||||
(abs(star_row - row) == abs(star_col - col)) and abs(star_col - col) == 1):
|
||||
return False
|
||||
return True
|
||||
|
||||
def solve_star_battle(grid):
|
||||
shapes_dict = find_shapes(grid)
|
||||
shapes = [(k,v) for k,v in shapes_dict.items()]
|
||||
shape_ids = list(shapes_dict.keys())
|
||||
shapes.sort(key=lambda x:len(x[1])) # Sort by the size of the shapes
|
||||
shape_ids = [shape_id for _, shape_id in zip([len(shape) for shape in shapes], shape_ids)]
|
||||
|
||||
star_positions = []
|
||||
print("初始网格:")
|
||||
print_grid(grid)
|
||||
attempts = 0
|
||||
def backtrack(index=0):
|
||||
nonlocal attempts
|
||||
shapes.sort(key=lambda x:len(x[1])) # Sort by the size of the shapes
|
||||
if index == len(shapes):
|
||||
print("所有区域均已处理完毕")
|
||||
return True
|
||||
|
||||
current_shape_id = shapes[index][0]
|
||||
shape = shapes[index][1]
|
||||
print(f"尝试在 {current_shape_id} 区域合法位置填星")
|
||||
invalid_positions = []
|
||||
for pos in random.sample(shape,len(shape)):
|
||||
if can_place_star(star_positions, pos):
|
||||
|
||||
print(f"尝试放置星星在位置 {pos}")
|
||||
star_positions.append(pos)
|
||||
print(f"当前星星位置:")
|
||||
attempts += 1
|
||||
print_grid(grid, star_positions)
|
||||
|
||||
if backtrack(index + 1):
|
||||
return True
|
||||
|
||||
print(f"移除位置 {pos} 的星星,因为无法在后续区域中找到合适的放置点")
|
||||
star_positions.remove(pos)
|
||||
print(f"当前星星位置:")
|
||||
print_grid(grid, star_positions)
|
||||
else:
|
||||
# print(f"不能放置星星在位置 {pos},因为它违反了规则(与已有的星星相邻)")
|
||||
invalid_positions.append(pos)
|
||||
if invalid_positions:
|
||||
print(f"位置{','.join(str(pos) for pos in invalid_positions)}与规则冲突,不能放置星星")
|
||||
print(f"当前 {current_shape_id} 区域没有剩余合法的星星放置位置,回溯到 {shapes[index-1][0]} 区域,") if index > 0 else None
|
||||
return False
|
||||
|
||||
if backtrack():
|
||||
print("找到解决方案:")
|
||||
print_grid(grid,star_positions)
|
||||
print("星星位置:", [ [x,y] for x,y in star_positions])
|
||||
return star_positions, attempts
|
||||
else:
|
||||
print("没有找到解决方案")
|
||||
return None,None
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 示例网格,数字代表所在区域编号
|
||||
from grids import grids
|
||||
grid = grids[-1]
|
||||
star_positions, attempts = solve_star_battle(grid)
|
||||
print(f"尝试次数:{attempts}")
|
||||
147
internbootcamp/libs/starbattle/dfs_solver_cn.py
Executable file
147
internbootcamp/libs/starbattle/dfs_solver_cn.py
Executable file
|
|
@ -0,0 +1,147 @@
|
|||
import random
|
||||
from .dfs_solver_en import print_grid_in_kor
|
||||
|
||||
def print_grid(grid, stars=None):
|
||||
if stars is None:
|
||||
stars = []
|
||||
row_str_list = []
|
||||
for i, row in enumerate(grid):
|
||||
row_str = f'['
|
||||
for j, cell in enumerate(row):
|
||||
if (i, j) in stars:
|
||||
row_str += '*, ' if j + 1 < len(row) else '*'
|
||||
else:
|
||||
row_str += f'{cell}, ' if j + 1 < len(row) else f'{cell}'# Format the number to take up two spaces
|
||||
row_str += ']'
|
||||
row_str_list.append(row_str)
|
||||
# grid_str += "\n"
|
||||
return "```starmatrix\n[\n" + ',\n'.join(row_str_list) + "\n]\n```"
|
||||
|
||||
def print_stars(stars,grid):
|
||||
star_list = []
|
||||
stars.sort(key=lambda star: grid[star[0]][star[1]])
|
||||
for star in stars:
|
||||
star_list.append(f"{grid[star[0]][star[1]]}({star[0] + 1},{star[1] + 1})")
|
||||
return "[[" +',\n'.join(star_list)+ "]]"
|
||||
|
||||
def find_shapes(grid):
|
||||
shapes = {}
|
||||
for i, row in enumerate(grid):
|
||||
for j, cell in enumerate(row):
|
||||
if cell not in shapes:
|
||||
shapes[cell] = []
|
||||
shapes[cell].append((i, j))
|
||||
return shapes
|
||||
|
||||
def can_place_star(star_positions, pos):
|
||||
row, col = pos # 解构位置为行(row)和列(col)
|
||||
conflict_info = None
|
||||
|
||||
for star_row, star_col in star_positions: # 遍历已经放置的星星的位置
|
||||
if star_row == row:
|
||||
conflict_info = ('在同一行', (star_row, star_col))
|
||||
break
|
||||
elif star_col == col:
|
||||
conflict_info = ('在同一列', (star_row, star_col))
|
||||
break
|
||||
elif abs(star_row - row) == abs(star_col - col):
|
||||
if abs(star_col - col) == 1:
|
||||
conflict_info = ('对角线相邻', (star_row, star_col))
|
||||
break
|
||||
|
||||
if conflict_info is not None:
|
||||
return False, conflict_info # 返回False以及冲突的信息
|
||||
else:
|
||||
return True, None # 如果没有违反任何规则,则可以放置星星,且无冲突信息
|
||||
|
||||
def update_valid_positions(shapes, star_positions):
|
||||
updated_shapes = []
|
||||
for shape_id, positions in shapes:
|
||||
valid_positions = [pos for pos in positions if can_place_star(star_positions, pos)]
|
||||
updated_shapes.append((shape_id, valid_positions))
|
||||
updated_shapes.sort(key=lambda x: len(x[1]))
|
||||
return updated_shapes
|
||||
|
||||
def solve_star_battle(grid):
|
||||
original_grid = grid
|
||||
shapes_dict = find_shapes(grid)
|
||||
shapes = [(k, v) for k, v in shapes_dict.items()]
|
||||
shapes.sort(key=lambda x: len(x[1])) # 按区域大小排序
|
||||
star_positions = []
|
||||
|
||||
print("这是一个5x5的星战逻辑解谜游戏。我们需要在网格中放置星星,满足以下条件:\n1.任意两颗星星不能在同一列、同一行或在对角线上相邻\n2.每行、每列和每个标记区域必须放置1颗星星\n3.网格由字母标记区域,同一个字母属于同一个区域\n")
|
||||
print("解决这类问题需要:\n1.理解区域划分:相同字母属于同一区域\n2.排除法:通过已知星星位置排除不可能的位置\n3.唯一性:每个行、列、区域只能放一颗星星\n4.邻近规则:星星不能相邻(包括对角线)\n5.回溯法: 逐步构建解决方案并在发现当前路径不可行时“回溯”到上一步以尝试其他可能来探索所有潜在的解决方案,直到找到正确的答案或遍历完所有可能性。\n6.MRV策略:最少剩余值策略,每次处理可能值最少的情况即处理合法位置最少的区域,从而尽可能减少搜索空间。\n" )
|
||||
print("先拟定一个解题计划如下:")
|
||||
print("1. 识别所有区域,并收集每个区域的格子位置。\n2. 按区域合法位置数排序,每次优先处理合法位置最少的区域。\n3. 在每个区域内尝试放置星星,检查是否符合规则。\n4. 放置星星后重新计算各区域合法位置数,继续选择拥有最少合法位置的区域填星\n5. 使用回溯算法,如果当前区域无法放置,则回溯到上一步,尝试其他位置。\n6. 记录已放置的星星位置,确保不违反规则。\n7. 如果所有区域都处理完毕,输出解决方案。如果搜索完成后没有找到解,则该题无解。\n")
|
||||
print("现在开始尝试解题:")
|
||||
shape_str = ''
|
||||
for shape in [(k, v) for k, v in shapes_dict.items()]:
|
||||
shape_str += f"{shape[0]} 区域, 包含格子:{', '.join(f'{x[0] + 1,x[1] + 1}' for x in shape[1])}, 合法位置数: {len(shape[1])}\n"
|
||||
|
||||
print("初始网格:\n" + print_grid_in_kor(grid) + "\n识别所有区域,并收集每个区域的格子位置\n" + shape_str + "下面从合法位置最少的区域开始填星,用符号 * 标记已放置的星星位置\n")
|
||||
|
||||
|
||||
attempts = 0
|
||||
|
||||
def backtrack(shapes, last_shape_id):
|
||||
nonlocal attempts
|
||||
if not shapes:
|
||||
print("所有区域均填星成功,找到了一个满足所有条件的星星放置方案,具体位置如下:\n" + print_grid_in_kor(grid, star_positions) + "\n最终答案为:" + print_stars(star_positions,original_grid))
|
||||
return True
|
||||
|
||||
current_shape_id, shape = shapes[0]
|
||||
invalid_positions = []
|
||||
for pos in random.sample(shape, len(shape)):
|
||||
place_res, info= can_place_star(star_positions, pos)
|
||||
if place_res:
|
||||
print(f"在拥有最少合法位置的 {current_shape_id} 区域填星。\n" + f"尝试放置星星在位置 {(pos[0]+1,pos[1]+1)}\n")
|
||||
remaining_shapes = update_valid_positions(shapes[1:], star_positions)
|
||||
if len(remaining_shapes) > 0:
|
||||
print(f"位置 {(pos[0]+1,pos[1]+1)} 所在行、列及对角均无其余星星,符合规则。 星星位置已更新,重新计算剩余区域的合法位置数,继续选择拥有最少合法位置的 {remaining_shapes[0][0]} 区域填星\n")
|
||||
else:
|
||||
print(f"位置 {(pos[0]+1,pos[1]+1)} 所在行、列及对角均无其余星星,符合规则。 已无剩余区域,看来我们找到到一个满足所有条件的星星放置方案。\n")
|
||||
star_positions.append(pos)
|
||||
print(f"当前星星位置:{print_stars(star_positions,original_grid)}\n" + "当前网格:\n" + print_grid_in_kor(grid, star_positions))
|
||||
attempts += 1
|
||||
|
||||
|
||||
if backtrack(remaining_shapes, last_shape_id=current_shape_id):
|
||||
return True
|
||||
|
||||
print(f"移除位置 {(pos[0]+1,pos[1]+1)} 的星星,因为无法在后续区域中找到合适的放置点")
|
||||
star_positions.remove(pos)
|
||||
print(f"当前星星位置:{print_stars(star_positions,original_grid)}\n" + "当前网格:\n" + print_grid_in_kor(grid, star_positions))
|
||||
else:
|
||||
if random.random() < 0.2 and info[0] == '对角线相邻':
|
||||
print(f"在拥有最少合法位置的 {current_shape_id} 区域填星。\n" + f"尝试放置星星在位置 {(pos[0]+1,pos[1]+1)}\n")
|
||||
print(f'{(pos[0]+1,pos[1]+1)} 不合法,因为它与星星 {(info[1][0] + 1, info[1][1] + 1)} {info[0]}。再次尝试在{current_shape_id} 区域放置星星\n')
|
||||
attempts += 1
|
||||
elif random.random() < 0.1 and not info[0] == '对角线相邻':
|
||||
print(f"在拥有最少合法位置的 {current_shape_id} 区域填星。\n" + f"尝试放置星星在位置 {(pos[0]+1,pos[1]+1)}\n")
|
||||
print(f'{(pos[0]+1,pos[1]+1)} 不合法,因为它与星星 {(info[1][0] + 1, info[1][1] + 1)} {info[0]}。再次尝试在{current_shape_id} 区域放置星星\n')
|
||||
attempts += 1
|
||||
|
||||
invalid_positions.append(pos)
|
||||
|
||||
if invalid_positions:
|
||||
print(f"{current_shape_id} 区域所有位置{','.join(str(pos) for pos in invalid_positions)}与现有星星规则冲突,无合法位置,不能放置星星\n")
|
||||
if last_shape_id:
|
||||
print(f"当前 {current_shape_id} 区域没有剩余合法的星星放置位置,回溯到 {last_shape_id} 区域\n")
|
||||
else:
|
||||
# print_conclude("没有找到解决方案")
|
||||
pass
|
||||
return False
|
||||
|
||||
if backtrack(shapes, None):
|
||||
return print_stars(stars=star_positions,grid=original_grid), attempts
|
||||
else:
|
||||
print("我们已经尝试了所有可能情况,没有找到解决方案。该问题无解。\n")
|
||||
return None, None
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 示例网格,数字代表所在区域编号
|
||||
from grids import grids
|
||||
grid = grids[-2]
|
||||
star_positions, attempts = solve_star_battle(grid)
|
||||
print(f"尝试次数:{attempts}")
|
||||
156
internbootcamp/libs/starbattle/dfs_solver_en.py
Executable file
156
internbootcamp/libs/starbattle/dfs_solver_en.py
Executable file
|
|
@ -0,0 +1,156 @@
|
|||
import random
|
||||
import copy
|
||||
|
||||
def print_grid(grid, stars=None):
|
||||
if stars is None:
|
||||
stars = []
|
||||
row_str_list = []
|
||||
for i, row in enumerate(grid):
|
||||
row_str = f'['
|
||||
for j, cell in enumerate(row):
|
||||
if (i, j) in stars:
|
||||
row_str += '*, ' if j + 1 < len(row) else '*'
|
||||
else:
|
||||
row_str += f'{cell}, ' if j + 1 < len(row) else f'{cell}'# Format the number to take up two spaces
|
||||
row_str += ']'
|
||||
row_str_list.append(row_str)
|
||||
# grid_str += "\n"
|
||||
return "```starmatrix\n[\n" + ',\n'.join(row_str_list) + "\n]\n```"
|
||||
|
||||
def print_grid_in_kor(grid, stars=None):
|
||||
grid_cp = copy.deepcopy(grid)
|
||||
if stars:
|
||||
for i,j in stars:
|
||||
grid_cp[i][j] = '*'
|
||||
pass
|
||||
return '\n'.join(['\t'.join(row) for row in grid_cp])
|
||||
|
||||
def print_stars(stars,grid):
|
||||
star_list = []
|
||||
stars.sort(key=lambda star: grid[star[0]][star[1]])
|
||||
for star in stars:
|
||||
star_list.append(f"{grid[star[0]][star[1]]}({star[0] + 1},{star[1] + 1})")
|
||||
return "[[" +',\n'.join(star_list)+ "]]"
|
||||
|
||||
|
||||
def find_shapes(grid):
|
||||
shapes = {}
|
||||
for i, row in enumerate(grid):
|
||||
for j, cell in enumerate(row):
|
||||
if cell not in shapes:
|
||||
shapes[cell] = []
|
||||
shapes[cell].append((i, j))
|
||||
return shapes
|
||||
|
||||
def can_place_star(star_positions, pos):
|
||||
row, col = pos # Deconstruct position into row and column
|
||||
conflict_info = None
|
||||
|
||||
for star_row, star_col in star_positions: # Traverse the positions of already placed stars
|
||||
if star_row == row:
|
||||
conflict_info = ('in the same row', (star_row, star_col))
|
||||
break
|
||||
elif star_col == col:
|
||||
conflict_info = ('in the same column', (star_row, star_col))
|
||||
break
|
||||
elif abs(star_row - row) == abs(star_col - col):
|
||||
if abs(star_col - col) == 1:
|
||||
conflict_info = ('diagonally adjacent', (star_row, star_col))
|
||||
break
|
||||
|
||||
if conflict_info is not None:
|
||||
return False, conflict_info # Return False and conflict information
|
||||
else:
|
||||
return True, None # If no rules are violated, the star can be placed, and there is no conflict information
|
||||
|
||||
def update_valid_positions(shapes, star_positions):
|
||||
updated_shapes = []
|
||||
for shape_id, positions in shapes:
|
||||
valid_positions = [pos for pos in positions if can_place_star(star_positions, pos)]
|
||||
updated_shapes.append((shape_id, valid_positions))
|
||||
updated_shapes.sort(key=lambda x: len(x[1]))
|
||||
return updated_shapes
|
||||
|
||||
def solve_star_battle(grid):
|
||||
original_grid = grid
|
||||
shapes_dict = find_shapes(grid)
|
||||
shapes = [(k, v) for k, v in shapes_dict.items()]
|
||||
shapes.sort(key=lambda x: len(x[1])) # Sort by region size
|
||||
star_positions = []
|
||||
|
||||
print("This is a 5x5 Star Battle logic puzzle. We need to place stars in the grid, satisfying the following conditions:\n1. Any two stars cannot be in the same row, column, or diagonally adjacent\n2. Each row, column, and marked region must contain exactly one star\n3. The grid is divided into regions marked by letters, and the same letter belongs to the same region.\n")
|
||||
print("Solving this type of problem requires:\n1. Understanding region division: the same letter belongs to the same region\n2. Elimination method: exclude impossible positions based on known star positions\n3. Uniqueness: each row, column, and region can only contain one star\n4. Adjacency rule: stars cannot be adjacent (including diagonally)\n5. Backtracking: gradually build the solution and 'backtrack' to the previous step when the current path is found to be infeasible to try other possibilities, exploring all potential solutions until the correct answer is found or all possibilities are exhausted.\n6. MRV strategy: Minimum Remaining Values strategy, each time dealing with the situation with the fewest possible values, i.e., the region with the fewest legal positions, thereby reducing the search space as much as possible.\n")
|
||||
print("Here is the step-by-step process of solving this type of problem:\n")
|
||||
print("1. Identify all regions and collect the positions of each region.\n2. Sort regions by the number of legal positions, each time prioritizing the region with the fewest legal positions.\n3. Try to place a star in each region, checking if it complies with the rules.\n4. After placing a star, recalculate the number of legal positions in each region, continue to select the region with the fewest legal positions to place a star\n5. Use the backtracking algorithm, if the current region cannot be placed, backtrack to the previous step and try other positions.\n6. Record the positions of placed stars to ensure no rules are violated.\n7. If all regions are processed, output the solution. If no solution is found after the search is completed, the puzzle has no solution.\n")
|
||||
shape_str = ''
|
||||
for shape in [(k, v) for k, v in shapes_dict.items()]:
|
||||
shape_str += f"region {shape[0]}, contains cells: {', '.join(f'{x[0] + 1,x[1] + 1}' for x in shape[1])}, number of legal positions: {len(shape[1])}\n"
|
||||
|
||||
print("Try to solve the puzzle:")
|
||||
print("Initial grid:\n" + print_grid_in_kor(grid) + "\nIdentify all regions and collect the positions of each region\n" + shape_str + "Now, start placing stars from the region with the fewest legal positions, using the symbol * to mark the positions of placed stars.")
|
||||
|
||||
|
||||
attempts = 0
|
||||
|
||||
def backtrack(shapes, last_shape_id):
|
||||
nonlocal attempts
|
||||
if not shapes:
|
||||
print("All regions have been successfully filled with stars, a star placement solution that satisfies all conditions has been found, the specific positions are as follows:\n" + print_grid_in_kor(grid, star_positions) + "\nThe final answer is:\n" + print_stars(star_positions,original_grid))
|
||||
return True
|
||||
|
||||
current_shape_id, shape = shapes[0]
|
||||
invalid_positions = []
|
||||
for pos in random.sample(shape, len(shape)):
|
||||
place_res, info= can_place_star(star_positions, pos)
|
||||
if place_res:
|
||||
print(f"Placing a star in the {current_shape_id} region with the fewest legal positions.\n" + f"Attempting to place a star at position {(pos[0]+1,pos[1]+1)}\n")
|
||||
remaining_shapes = update_valid_positions(shapes[1:], star_positions)
|
||||
if len(remaining_shapes) > 0:
|
||||
print(f"Position {(pos[0]+1,pos[1]+1)} has no other stars in its row, column, or diagonals, complying with the rules. Star positions have been updated. Recalculate the number of legal positions in remaining regions, continue to select the {remaining_shapes[0][0]} region with the fewest legal positions to place a star\n")
|
||||
else:
|
||||
print(f"Position {(pos[0]+1,pos[1]+1)} has no other stars in its row, column, or diagonals, complying with the rules. There are no remaining regions, it seems we have found a star placement solution that satisfies all conditions.\n")
|
||||
star_positions.append(pos)
|
||||
print(f"Current star positions:\n{print_stars(star_positions,original_grid)}\n" + "Current grid:\n" + print_grid_in_kor(grid, star_positions))
|
||||
attempts += 1
|
||||
|
||||
|
||||
if backtrack(remaining_shapes, last_shape_id=current_shape_id):
|
||||
return True
|
||||
|
||||
print(f"Removing the star at position {(pos[0]+1,pos[1]+1)} because no suitable placement cell can be found in subsequent regions\n")
|
||||
star_positions.remove(pos)
|
||||
print(f"Current star positions:\n{print_stars(star_positions,original_grid)}\n" + "Current grid:\n" + print_grid_in_kor(grid, star_positions))
|
||||
else:
|
||||
if random.random() < 0.2 and info[0] == 'diagonally adjacent':
|
||||
print(f"Placing a star in the {current_shape_id} region with the fewest legal positions.\n" + f"Attempting to place a star at position {(pos[0]+1,pos[1]+1)}\n")
|
||||
print(f'{(pos[0]+1,pos[1]+1)} is invalid because it is {info[0]} with star {(info[1][0] + 1, info[1][1] + 1)}. Trying again to place a star in the {current_shape_id} region\n')
|
||||
attempts += 1
|
||||
elif random.random() < 0.1 and not info[0] == 'diagonally adjacent':
|
||||
print(f"Placing a star in the {current_shape_id} region with the fewest legal positions.\n" + f"Attempting to place a star at position {(pos[0]+1,pos[1]+1)}\n")
|
||||
print(f'{(pos[0]+1,pos[1]+1)} is invalid because it is {info[0]} with star {(info[1][0] + 1, info[1][1] + 1)}. Trying again to place a star in the {current_shape_id} region\n')
|
||||
attempts += 1
|
||||
|
||||
invalid_positions.append(pos)
|
||||
|
||||
if invalid_positions:
|
||||
print(f"All positions in the {current_shape_id} region {','.join(f'({pos[0]+1}, {pos[1]+1})' for pos in invalid_positions)} conflict with existing star rules, no legal positions, cannot place a star\n")
|
||||
if last_shape_id:
|
||||
print(f"Currently, the {current_shape_id} region has no remaining legal star placement positions, backtracking to the {last_shape_id} region\n")
|
||||
else:
|
||||
# print_conclude("No solution found")
|
||||
pass
|
||||
return False
|
||||
|
||||
if backtrack(shapes, None):
|
||||
return print_stars(star_positions,original_grid), attempts
|
||||
else:
|
||||
print("We have tried all possible solutions.No solution found.I'm afraid there is no solution for this puzzle.\n")
|
||||
return None, None
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Example grid, numbers represent region IDs
|
||||
from grids import grids
|
||||
grid = grids[-2]
|
||||
star_positions, attempts = solve_star_battle(grid)
|
||||
print(f"Number of attempts: {attempts}")
|
||||
128
internbootcamp/libs/starbattle/get_grid.py
Executable file
128
internbootcamp/libs/starbattle/get_grid.py
Executable file
|
|
@ -0,0 +1,128 @@
|
|||
import random
|
||||
|
||||
def generate_star_battle_grid(size):
|
||||
"""
|
||||
生成星战谜题的测试用例网格。
|
||||
|
||||
参数:
|
||||
size -- 网格的大小 (假设是正方形网格,size 表示边长)
|
||||
num_regions -- 区域的数量(等于星星数量)
|
||||
|
||||
返回:
|
||||
grid -- 生成的网格,每个区域由不同的数字表示,0 表示尚未分配区域的空位
|
||||
star_positions -- 星星的位置列表
|
||||
"""
|
||||
num_regions = size
|
||||
|
||||
# 初始化网格和可用单元格列表
|
||||
grid = [[0 for _ in range(size)] for _ in range(size)]
|
||||
available_cells = [(r, c) for r in range(size) for c in range(size)]
|
||||
available_cells_for_star = available_cells.copy()
|
||||
star_positions = []
|
||||
|
||||
def is_safe_to_place_star(row, col, star_positions):
|
||||
"""检查在给定位置放置星星是否安全"""
|
||||
for r, c in star_positions:
|
||||
if row == r or col == c or abs(row - r) == abs(col - c):
|
||||
return False
|
||||
return True
|
||||
|
||||
while True:
|
||||
try:
|
||||
# 随机确定所有星星的位置
|
||||
while len(star_positions) < num_regions:
|
||||
pos = random.choice(available_cells_for_star)
|
||||
star_positions.append(pos)
|
||||
available_cells_for_star.remove(pos)
|
||||
available_cells.remove(pos)
|
||||
# pos周围一层也从available_cells_for_star移除
|
||||
for r in range(pos[0] - 1, pos[0] ):
|
||||
for c in range(pos[1] - 1, pos[1] ):
|
||||
if (r, c) in available_cells_for_star:
|
||||
available_cells_for_star.remove((r, c))
|
||||
# pos 同行同列从available_cells_for_star移除
|
||||
for c in range(num_regions):
|
||||
if (pos[0], c) in available_cells_for_star:
|
||||
available_cells_for_star.remove((pos[0], c))
|
||||
for r in range(num_regions):
|
||||
if (r, pos[1]) in available_cells_for_star:
|
||||
available_cells_for_star.remove((r, pos[1]))
|
||||
break
|
||||
except:
|
||||
available_cells = [(r, c) for r in range(size) for c in range(size)]
|
||||
available_cells_for_star = available_cells.copy()
|
||||
star_positions = []
|
||||
pass
|
||||
|
||||
remaining_cells = list(available_cells)
|
||||
# 为每个星星创建一个区域
|
||||
regions = []
|
||||
for i, star_pos in enumerate(star_positions, start=1):
|
||||
region_id = chr(ord('A') + i - 1)
|
||||
cur_region,remaining_cells = expand_region_by_1_step(grid, star_pos, remaining_cells, region_id)
|
||||
regions.append(cur_region)
|
||||
# 继续扩展
|
||||
for i,region in enumerate(regions, start=1):
|
||||
region_id = chr(ord('A') + i - 1)
|
||||
remaining_cells = expand_region_from_star(grid, region, remaining_cells, region_id)
|
||||
|
||||
# 将最后剩余空位随机融合到附近的区域
|
||||
def find_nearest_region(grid, x, y):
|
||||
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
|
||||
random.shuffle(directions) # 随机化扩展顺序
|
||||
for dx, dy in directions:
|
||||
nx, ny = x + dx, y + dy
|
||||
try:
|
||||
if grid[nx][ny] != 0 and nx >= 0 and ny >= 0:
|
||||
return grid[nx][ny]
|
||||
except IndexError:
|
||||
continue
|
||||
return None
|
||||
|
||||
while remaining_cells:
|
||||
x, y = random.choice(remaining_cells)
|
||||
region_id = find_nearest_region(grid, x, y)
|
||||
if region_id is not None:
|
||||
grid[x][y] = region_id
|
||||
remaining_cells.remove((x, y))
|
||||
|
||||
return grid, star_positions
|
||||
|
||||
def expand_region_by_1_step(grid,star_pos,available_cells, region_id):
|
||||
"""从星星位置随机扩散出一个区域"""
|
||||
region = [star_pos]
|
||||
grid[star_pos[0]][star_pos[1]] = region_id
|
||||
# 定义可能的移动方向
|
||||
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
|
||||
random.shuffle(directions) # 随机化扩展顺序
|
||||
|
||||
for direction in directions:
|
||||
new_pos = (star_pos[0] + direction[0], star_pos[1] + direction[1])
|
||||
if new_pos in available_cells:
|
||||
available_cells.remove(new_pos)
|
||||
region.append(new_pos)
|
||||
grid[new_pos[0]][new_pos[1]] = region_id
|
||||
break
|
||||
return region,available_cells
|
||||
def expand_region_from_star(grid, region, available_cells, region_id):
|
||||
# 继续尝试扩展直到达到合理大小或没有更多可用单元格
|
||||
max_region_size = random.randint(1 ,len(available_cells) // len(grid))
|
||||
retry = 0
|
||||
while available_cells and len(region) < max_region_size and retry < len(grid) ** 2:
|
||||
next_cell = random.choice(available_cells)
|
||||
if any(abs(next_cell[0] - cell[0]) + abs(next_cell[1] - cell[1]) <= 1 for cell in region):
|
||||
available_cells.remove(next_cell)
|
||||
region.append(next_cell)
|
||||
grid[next_cell[0]][next_cell[1]] = region_id
|
||||
retry += 1
|
||||
return available_cells
|
||||
|
||||
# 示例使用:
|
||||
if __name__ == "__main__":
|
||||
size = 5 # 网格大小
|
||||
|
||||
grid, star_positions = generate_star_battle_grid(size)
|
||||
print("生成的网格:")
|
||||
for row in grid:
|
||||
print(row)
|
||||
print("星星的位置:", star_positions)
|
||||
64
internbootcamp/libs/starbattle/grids.py
Executable file
64
internbootcamp/libs/starbattle/grids.py
Executable file
|
|
@ -0,0 +1,64 @@
|
|||
grids = [
|
||||
[
|
||||
[1,1,2,3,3,3],
|
||||
[1,2,2,2,2,3],
|
||||
[1,4,4,4,4,4],
|
||||
[5,5,5,5,5,4],
|
||||
[6,6,5,5,5,5],
|
||||
[6,6,6,6,6,6]
|
||||
],
|
||||
[
|
||||
[1,2,2,2,2],
|
||||
[1,1,1,1,2],
|
||||
[1,1,1,4,2],
|
||||
[3,3,3,4,5],
|
||||
[3,3,3,5,5]
|
||||
],
|
||||
[
|
||||
[1,2,2,2,2,2],
|
||||
[1,1,1,2,2,3],
|
||||
[1,4,5,2,2,3],
|
||||
[1,4,5,2,2,3],
|
||||
[6,4,5,5,3,3],
|
||||
[6,6,6,5,5,5]
|
||||
],
|
||||
[
|
||||
[1,2,2,2,2,3],
|
||||
[1,1,1,2,2,3],
|
||||
[1,1,4,4,3,3],
|
||||
[1,5,5,5,5,3],
|
||||
[1,1,6,6,5,3],
|
||||
[1,1,1,6,6,6]
|
||||
],
|
||||
[
|
||||
[2, 2, 2, 2, 2],
|
||||
[5, 2, 2, 2, 4],
|
||||
[5, 5, 1, 2, 3],
|
||||
[5, 1, 1, 2, 3],
|
||||
[5, 1, 3, 3, 3],
|
||||
]
|
||||
,
|
||||
[
|
||||
[2, 2, 3, 3, 1, 4],
|
||||
[5, 2, 3, 3, 1, 4],
|
||||
[5, 5, 1, 1, 1, 4],
|
||||
[5, 5, 5, 1, 1, 4],
|
||||
[6, 5, 5, 5, 5, 5],
|
||||
[6, 6, 5, 5, 5, 5]
|
||||
],
|
||||
[
|
||||
['A', 'A', 'E', 'D', 'D'],
|
||||
['A', 'E', 'E', 'D', 'D'],
|
||||
['A', 'A', 'B', 'B', 'B'],
|
||||
['A', 'A', 'C', 'B', 'B'],
|
||||
['C', 'C', 'C', 'B', 'B'],
|
||||
],
|
||||
[
|
||||
['A', 'A', 'E', 'D', 'D'],
|
||||
['A', 'E', 'E', 'D', 'D'],
|
||||
['A', 'A', 'B', 'B', 'B'],
|
||||
['A', 'A', 'C', 'B', 'B'],
|
||||
['C', 'C', 'C', 'B', 'B'],
|
||||
]
|
||||
|
||||
]
|
||||
10
internbootcamp/libs/starbattle/starbattle.py
Executable file
10
internbootcamp/libs/starbattle/starbattle.py
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
import random
|
||||
from dfs_solver import solve_star_battle
|
||||
from get_grid import generate_star_battle_grid
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# from grids import grids
|
||||
size = random.randint(5, 8)
|
||||
grid, star_positions = generate_star_battle_grid(size=size)
|
||||
solve_star_battle(grid)
|
||||
Loading…
Add table
Add a link
Reference in a new issue