1use rlwfc::{GridError, Tile, TileId, TileSet, TileSetVirtual};
12
13struct SimpleTileSet {
22 tiles: TileSet<&'static str>,
23}
24
25impl SimpleTileSet {
26 fn new() -> Self {
27 Self {
28 tiles: TileSet::new(),
29 }
30 }
31
32 fn get_all_tiles(&self) -> &[Tile<&'static str>] {
33 self.tiles.get_all_tiles()
34 }
35}
36
37impl TileSetVirtual<&'static str> for SimpleTileSet {
38 fn build_tile_set(&mut self) -> Result<(), GridError> {
39 self.tiles.clear();
41
42 self.tiles
44 .add_tile(vec!["grass", "grass", "grass", "grass"], 50);
45
46 self.tiles
48 .add_tile(vec!["water", "water", "water", "water"], 30);
49
50 self.tiles
52 .add_tile(vec!["grass", "water", "grass", "water"], 20);
53 self.tiles
54 .add_tile(vec!["water", "grass", "water", "grass"], 20);
55
56 println!("构建完成:添加了 {} 个瓷砖", self.tiles.get_tile_count());
57 Ok(())
58 }
59
60 fn judge_possibility(&self, neighbor_possibilities: &[Vec<TileId>], candidate: TileId) -> bool {
61 if neighbor_possibilities.is_empty() {
63 return true;
64 }
65
66 self.tiles.get_tile(candidate).is_some()
68 }
69
70 fn get_tile(&self, tile_id: TileId) -> Option<&Tile<&'static str>> {
71 self.tiles.get_tile(tile_id)
72 }
73
74 fn get_tile_count(&self) -> usize {
75 self.tiles.get_tile_count()
76 }
77
78 fn get_all_tile_ids(&self) -> Vec<TileId> {
79 self.tiles.get_all_tile_ids()
80 }
81}
82
83struct NumericTileSet {
91 tiles: TileSet<i32>,
92}
93
94impl NumericTileSet {
95 fn new() -> Self {
96 Self {
97 tiles: TileSet::new(),
98 }
99 }
100}
101
102impl TileSetVirtual<i32> for NumericTileSet {
103 fn build_tile_set(&mut self) -> Result<(), GridError> {
104 self.tiles.clear();
106
107 self.tiles.add_tile(vec![1, 1, 1, 1], 40); self.tiles.add_tile(vec![0, 0, 0, 0], 30); self.tiles.add_tile(vec![1, 0, 1, 0], 20); self.tiles.add_tile(vec![0, 1, 0, 1], 20); println!("数值瓷砖集构建完成:{} 个瓷砖", self.tiles.get_tile_count());
114 Ok(())
115 }
116
117 fn judge_possibility(&self, neighbor_possibilities: &[Vec<TileId>], candidate: TileId) -> bool {
118 let Some(candidate_tile) = self.tiles.get_tile(candidate) else {
119 return false;
120 };
121
122 for (direction, neighbor_ids) in neighbor_possibilities.iter().enumerate() {
123 if neighbor_ids.is_empty() {
124 continue;
125 }
126
127 let is_compatible = neighbor_ids.iter().any(|&neighbor_id| {
128 if let Some(neighbor_tile) = self.tiles.get_tile(neighbor_id) {
129 let opposite_direction = (direction + 2) % 4;
130 if let (Some(¤t_edge), Some(&neighbor_edge)) = (
131 candidate_tile.get_edge(direction),
132 neighbor_tile.get_edge(opposite_direction),
133 ) {
134 current_edge == neighbor_edge
136 } else {
137 false
138 }
139 } else {
140 false
141 }
142 });
143
144 if !is_compatible {
145 return false;
146 }
147 }
148
149 true
150 }
151
152 fn get_tile(&self, tile_id: TileId) -> Option<&Tile<i32>> {
153 self.tiles.get_tile(tile_id)
154 }
155
156 fn get_tile_count(&self) -> usize {
157 self.tiles.get_tile_count()
158 }
159
160 fn get_all_tile_ids(&self) -> Vec<TileId> {
161 self.tiles.get_all_tile_ids()
162 }
163}
164
165fn main() -> Result<(), Box<dyn std::error::Error>> {
170 println!("=== 瓷砖系统综合示例 ===\n");
171
172 println!("1. 基础TileSet使用:");
174 demonstrate_basic_tileset()?;
175
176 println!("\n2. 简单瓷砖集 (字符串边):");
178 demonstrate_simple_tileset()?;
179
180 println!("\n3. 数字瓷砖集 (整数边):");
182 demonstrate_numeric_tileset()?;
183
184 println!("\n4. 约束判断测试:");
186 demonstrate_constraint_checking()?;
187
188 println!("\n=== 示例完成 ===");
189 Ok(())
190}
191
192fn demonstrate_basic_tileset() -> Result<(), Box<dyn std::error::Error>> {
194 let mut tile_set = TileSet::new();
195
196 println!(" 创建基础瓷砖集...");
197
198 let tile1 = tile_set.add_tile(vec!["A", "B", "C", "D"], 10);
200 let tile2 = tile_set.add_tile(vec!["B", "A", "D", "C"], 15);
201 let _tile3 = tile_set.add_tile(vec!["C", "D", "A", "B"], 5);
202
203 println!(" 添加了 {} 个瓷砖", tile_set.get_tile_count());
204
205 for (i, tile) in tile_set.get_all_tiles().iter().enumerate() {
207 println!(
208 " 瓷砖 {}: ID={}, 权重={}, 边={:?}",
209 i, tile.id, tile.weight, tile.edges
210 );
211 }
212
213 if let (Some(t1), Some(t2)) = (tile_set.get_tile(tile1), tile_set.get_tile(tile2)) {
215 let compatible = t1.is_compatible_with(t2, 0); println!(" 瓷砖0和瓷砖1在方向0兼容: {}", compatible);
217 }
218
219 Ok(())
220}
221
222fn demonstrate_simple_tileset() -> Result<(), Box<dyn std::error::Error>> {
224 let mut simple_tileset = SimpleTileSet::new();
225
226 simple_tileset.build_tile_set()?;
228
229 println!("\n 瓷砖详情:");
231 for (i, tile) in simple_tileset.get_all_tiles().iter().enumerate() {
232 println!(" 瓷砖 {}: 边={:?}, 权重={}", i, tile.edges, tile.weight);
233 }
234
235 println!("\n 约束判断测试:");
237 test_constraint_judgment(&simple_tileset);
238
239 Ok(())
240}
241
242fn demonstrate_numeric_tileset() -> Result<(), Box<dyn std::error::Error>> {
244 let mut numeric_tileset = NumericTileSet::new();
245
246 numeric_tileset.build_tile_set()?;
248
249 println!("\n 瓷砖统计:");
251 let mut edge_types = std::collections::HashMap::new();
252 for tile in numeric_tileset.tiles.get_all_tiles() {
253 for &edge in &tile.edges {
254 *edge_types.entry(edge).or_insert(0) += 1;
255 }
256 }
257
258 for (edge_type, count) in edge_types {
259 let type_name = match edge_type {
260 0 => "平原",
261 1 => "山脉",
262 2 => "河流",
263 _ => "未知",
264 };
265 println!(" 边类型 {} ({}): {} 个边", edge_type, type_name, count);
266 }
267
268 Ok(())
269}
270
271fn demonstrate_constraint_checking() -> Result<(), Box<dyn std::error::Error>> {
273 let mut tileset = SimpleTileSet::new();
274 tileset.build_tile_set()?;
275
276 println!(" 测试不同约束情况:");
277
278 let no_constraints: Vec<Vec<TileId>> = vec![];
280 let result1 = tileset.judge_possibility(&no_constraints, 0);
281 println!(
282 " 无约束情况: {}",
283 if result1 { "可放置" } else { "不可放置" }
284 );
285
286 let single_constraint = vec![vec![0], vec![], vec![], vec![]]; let result2 = tileset.judge_possibility(&single_constraint, 1);
289 println!(
290 " 单方向约束: {}",
291 if result2 { "可放置" } else { "不可放置" }
292 );
293
294 let multi_constraints = vec![vec![0], vec![1], vec![], vec![]]; let result3 = tileset.judge_possibility(&multi_constraints, 2);
297 println!(
298 " 多方向约束: {}",
299 if result3 { "可放置" } else { "不可放置" }
300 );
301
302 let result4 = tileset.judge_possibility(&single_constraint, 999);
304 println!(
305 " 不存在瓷砖: {}",
306 if result4 { "可放置" } else { "不可放置" }
307 );
308
309 Ok(())
310}
311
312fn test_constraint_judgment(tileset: &SimpleTileSet) {
314 let grass_tile_id = 0; let water_tile_id = 1; let same_type_constraint = vec![vec![grass_tile_id], vec![], vec![], vec![]];
320 let compatible_with_same = tileset.judge_possibility(&same_type_constraint, grass_tile_id);
321 println!(" 草地瓷砖与草地瓷砖兼容: {}", compatible_with_same);
322
323 let diff_type_constraint = vec![vec![water_tile_id], vec![], vec![], vec![]];
325 let compatible_with_diff = tileset.judge_possibility(&diff_type_constraint, grass_tile_id);
326 println!(" 草地瓷砖与水面瓷砖兼容: {}", compatible_with_diff);
327
328 if let Some(transition_tile) = tileset.get_tile(2) {
330 println!(" 过渡瓷砖边: {:?}", transition_tile.edges);
331 let transition_compatible = tileset.judge_possibility(&same_type_constraint, 2);
332 println!(" 过渡瓷砖与草地瓷砖兼容: {}", transition_compatible);
333 }
334}