程序化自动布局多尺寸图片数组及推箱子游戏棋盘展示方案求助
搞定推箱子游戏的棋盘布局与图片展示方案
嘿,针对你开发推箱子(Sokoban)时遇到的棋盘展示和自适应布局问题,我整理了一套实用的解决方案,直接就能整合到你的代码里:
核心思路:动态适配不同尺寸关卡
你现有代码里的x0和y0是固定值,只能适配特定大小的关卡。咱们改成根据关卡尺寸动态计算起始位置,让棋盘始终居中显示,不管是5x5还是10x10的关卡都能完美适配。
完整优化代码示例
// 示例关卡地图(可从文件/配置加载不同尺寸的关卡) let sampleLevelMap: [String] = [ "##########", "#........#", "#.$..$...#", "#..##....#", "#.@......#", "##########" ] func makeLevel(with levelMap: [String]) { // 先清理旧视图,避免重复叠加占用内存 cellImageView.forEach { row in row.forEach { $0.removeFromSuperview() } } floorImageView.forEach { row in row.forEach { $0.removeFromSuperview() } } cellImageView.removeAll() floorImageView.removeAll() let cellSize = CGSize(width: 35, height: 35) let rows = levelMap.count guard rows > 0 else { return } let cols = levelMap[0].count // 计算棋盘总尺寸 let totalBoardWidth = CGFloat(cols) * cellSize.width let totalBoardHeight = CGFloat(rows) * cellSize.height // 计算居中起始位置(基于父视图尺寸动态计算) guard let parentView = self.view else { return } let startX = (parentView.bounds.width - totalBoardWidth) / 2 let startY = (parentView.bounds.height - totalBoardHeight) / 2 // 定义元素图片映射(添加可选绑定,避免图片加载失败崩溃) let imageMap: [Character: UIImage?] = [ ".": UIImage(named: "poopgoal30x30"), "#": UIImage(named: "wall30x30"), "$": UIImage(named: "box30x30"), // 补全你箱子图片的名称 "@": UIImage(named: "player30x30"), // 玩家角色图片 " ": UIImage(named: "floor30x30") // 空白地板背景 ] // 遍历地图创建视图 for rowIndex in 0..<rows { var cellRow: [UIImageView] = [] var floorRow: [UIImageView] = [] let rowStr = levelMap[rowIndex] for colIndex in 0..<cols { let currentChar = rowStr[rowStr.index(rowStr.startIndex, offsetBy: colIndex)] // 计算当前单元格的位置 let x = startX + CGFloat(colIndex) * cellSize.width let y = startY + CGFloat(rowIndex) * cellSize.height let cellFrame = CGRect(x: x, y: y, width: cellSize.width, height: cellSize.height) // 创建底层地板视图(每个格子都需要) let floorView = UIImageView(frame: cellFrame) floorView.image = imageMap[" "]! ?? UIImage(named: "defaultFloor") // 兜底默认图 parentView.addSubview(floorView) floorRow.append(floorView) // 创建上层元素视图(墙、箱子、目标点、玩家) let cellView = UIImageView(frame: cellFrame) cellView.image = imageMap[currentChar] ?? nil if cellView.image != nil { parentView.addSubview(cellView) cellRow.append(cellView) } } cellImageView.append(cellRow) floorImageView.append(floorRow) } } // 调用示例:加载示例关卡 makeLevel(with: sampleLevelMap)
关键优化点说明
- 自适应居中布局:通过父视图尺寸和关卡总尺寸的差值,自动计算起始坐标,不管关卡大小都能居中显示
- 安全的图片加载:用可选绑定处理
UIImage(named:)的返回值,避免图片不存在导致崩溃,还加了兜底默认图 - 视图清理逻辑:每次创建新关卡前移除旧视图,防止视图叠加占用内存
- 模块化传入关卡数据:把关卡地图作为参数传入,方便快速切换不同尺寸的关卡
这样你就能轻松展示任意尺寸的推箱子棋盘啦!
内容的提问来源于stack exchange,提问作者Simon.T
相关产品推荐
相关产品推荐

