单元测试中move_car函数无法更新车辆坐标,但主文件运行正常的问题排查求助
单元测试中move_car函数无法更新车辆坐标,但主文件运行正常的问题排查求助
各位好,我正在开发一个《高峰时刻》(Rush Hour)游戏,车辆在6x6网格上移动。每辆车用起始坐标、方向('v'垂直/'h'水平)和长度来表示,通过更新游戏状态里的x、y坐标实现移动。
问题描述
现在遇到一个奇怪的问题:在主文件里正常运行游戏时,车辆移动完全符合预期,坐标更新正确;但通过单元测试调用同一个move_car函数时,车辆位置却没有按预期变化。
示例场景(车辆B)
- 起始位置:
(2, 0) - 方向:
'v'(垂直) - 长度:3
相关测试代码
def test_move_car(self): game = deepcopy(TEST_GAME_GAME) move_car(game, 1, 'DOWN') # Moving car B down self.assertTupleEqual( game['cars'][1][0], (2, 1), "The coordinates of car B are incorrect. It should have moved down to (2, 1)" )
测试失败错误信息
AssertionError: Tuples differ: (2, 0) != (2, 1) First differing element 1: 0 1
但在主文件里手动调用同一个move_car函数时,车辆B的坐标会正确更新到(2,1)。
完整代码与测试常量
游戏核心代码
def parse_game(game_file_path: str) -> dict: with open(game_file_path, 'r') as file: grid_data = file.read() lines = [line.strip() for line in grid_data.splitlines() if line.strip()] #print(f"Initial lines (with borders): {lines}") max_moves = int(lines[-1]) lines = lines[:-1] grid = [line[1:-1] for line in lines[1:-1]] #print(f"Grid without borders: {grid}") height = len(grid) width = len(grid[0]) #print(f"Height: {height}, Width: {width}") game = { 'width': width, 'height': height, 'max_moves': max_moves, 'cars': [], } car_coordinates = {} for y in range(height): for x in range(width): char = grid[y][x] if char.isalpha(): # If it's a letter (representing a car) if char not in car_coordinates: car_coordinates[char] = [] car_coordinates[char].append((x, y)) # Debugging: Show the car coordinates dictionary print(f"Car coordinates: {car_coordinates}") car_index = 0 for car in sorted(car_coordinates.keys()): # Sort the cars so they are processed in alphabetical order coords = car_coordinates[car] is_vertical = False is_horizontal = False length = len(coords) if length > 1: #if the car has more than one coordinate, check if it's vertical or horizontal if coords[0][0] == coords[1][0]: # Same X means vertical is_vertical = True else: # Same Y means horizontal is_horizontal = True print(f"Processing car {car}: coordinates {coords}, is_vertical={is_vertical}, is_horizontal={is_horizontal}, length={length}") #adds car data to the game dictionary, including the car index umu if is_vertical: start_x, start_y = coords[0] game['cars'].append([(start_x, start_y), 'v', length]) # Append as vertical car elif is_horizontal: start_x, start_y = coords[0] game['cars'].append([(start_x, start_y), 'h', length]) # Append as horizontal car car_index += 1 # Increment car index for the next car in the index # Final game state debugging print(f"Final game state: {game}") return game def is_win(game: dict) -> bool: car_a = game["cars"][0] (x, y), orientation, size = car_a width = game["width"] return orientation == 'h' and x + size == width def move_car(game: dict, car_index: int, direction: str) -> bool: cars = game['cars'] width = game["width"] height = game["height"] car = cars[car_index] (x, y), orientation, size = car def get_occupied_coords(game, exclude_index=None): occupied = set() for i, other_car in enumerate(game["cars"]): if i == exclude_index: continue (ox, oy), o_orientation, o_size = other_car if o_orientation == "h": occupied.update((ox + j, oy) for j in range(o_size)) elif o_orientation == "v": occupied.update((ox, oy + j) for j in range(o_size)) return occupied occupied_coords = get_occupied_coords(game, car_index) if orientation == "h": if direction == "left": if x - 1 >= 0 and (x - 1, y) not in occupied_coords: x -= 1 else: return False elif direction == "right": if x + size < width and (x + size, y) not in occupied_coords: x += 1 else: return False else: return False elif orientation == "v": if direction == "up": if y - 1 >= 0 and (x, y - 1) not in occupied_coords: y -= 1 cars[car_index] = [(x, y + j) for j in range(size)] #Recalculate positions #print(f"After move: {cars[car_index]}") #prints the updated state of the car else: return False elif direction == "down": if y + size < height and (x, y + size) not in occupied_coords: y += 1 cars[car_index] = [(x, y + j) for j in range(size)] #Recalculate positions #print(f"After move: {cars[car_index]}") #prints the updated state of the car else: return False else: return False cars[car_index] = ((x, y), orientation, size) #print(f"After move: {cars[car_index]}") return True def get_game_str(game: dict, current_move: int) -> str: width = game["width"] height = game["height"] cars = game["cars"] car_letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" colors = [ "\u001b[47m", "\u001b[41m", "\u001b[42m", "\u001b[43m", "\u001b[44m", "\u001b[45m", "\u001b[46m", "\u001b[48;5;1m" ] grid = [["\u001b[40m" + "." + "\u001b[0m" for _ in range(width)] for _ in range(height)] for i, car in enumerate(cars): (x, y), orientation, size = car if x < 0 or y < 0 or x >= width or y >= height: continue car_letter = car_letters[i] car_color = colors[i % len(colors)] if orientation == "h": for j in range(size): if x + j < width: grid[y][x + j] = car_color + car_letter + "\u001b[0m" elif orientation == "v": for j in range(size): if y + j < height: grid[y + j][x] = car_color + car_letter + "\u001b[0m" grid_str = '' for row in grid: grid_str += "|" + "".join(row) + "|" + "\n" grid_str = "+" + "-" * width + "+" + "\n" + grid_str + "+" + "-" * width + "+" max_moves = game.get('max_moves', 0) grid_str += f"\nCurrent Move: {current_move}/{max_moves}" return grid_str def play_game(game: dict) -> int: current_move = 0 max_moves = game['max_moves'] while current_move < max_moves: print(get_game_str(game, current_move)) if is_win(game): print("Car A has exited! You win!") return 0 car_index = int(input("Enter car index to move (0 for A, 1 for B, etc.): ")) if car_index < 0 or car_index >= len(game["cars"]): print("Invalid car index. Try again.") continue direction = input("Enter direction (left, right, up, down): ").lower() if direction not in ['left', 'right', 'up', 'down']: print("Invalid direction. Try again.") continue print("Game state before move: ") print(game['cars']) if move_car(game, car_index, direction): print("Game state after move:") print(game['cars']) current_move += 1 else: print("Move not possible. Try again.") print("Out of moves! Game over.") return 1 if __name__ == '__main__': game = parse_game('game_file.txt') play_game(game)
测试用常量
TEST_GAME_STR = """\ +------+ |..BCCC| |..B...| |AAB.... |D..EEF| |D...GF| |.HHHGF| +------+ 40 """ TEST_GAME_GAME = { 'width': 6, 'height': 6, 'max_moves': 40, 'cars': ( [(0, 2), 'h', 2], # Car A [(2, 0), 'v', 3], # Car B [(3, 0), 'h', 3], # Car C [(0, 3), 'v', 2], # Car D [(3, 3), 'h', 2], # Car E [(5, 3), 'v', 3], # Car F [(4, 4), 'v', 2], # Car G [(1, 5), 'h', 3] # Car H ) }
已尝试的排查步骤
- 确认车辆B的属性:方向为垂直
'v',起始位置(2,0)正确无误。 - 添加打印语句,验证调用
move_car前后车辆B的位置:测试中调用后位置仍为(2,0),未发生变化。 - 在主文件中手动调用
move_car函数,车辆B的坐标能正确更新到(2,1)。
希望各位能帮我找出问题所在,谢谢!
备注:内容来源于stack exchange,提问作者godah
相关产品推荐
相关产品推荐

