use rlwfc::{GridError, Tile, TileId, TileSet, TileSetVirtual};
struct SimpleTileSet {
tiles: TileSet<&'static str>,
}
impl SimpleTileSet {
fn new() -> Self {
Self {
tiles: TileSet::new(),
}
}
fn get_all_tiles(&self) -> &[Tile<&'static str>] {
self.tiles.get_all_tiles()
}
}
impl TileSetVirtual<&'static str> for SimpleTileSet {
fn build_tile_set(&mut self) -> Result<(), GridError> {
self.tiles.clear();
self.tiles
.add_tile(vec!["grass", "grass", "grass", "grass"], 50);
self.tiles
.add_tile(vec!["water", "water", "water", "water"], 30);
self.tiles
.add_tile(vec!["grass", "water", "grass", "water"], 20);
self.tiles
.add_tile(vec!["water", "grass", "water", "grass"], 20);
println!("构建完成:添加了 {} 个瓷砖", self.tiles.get_tile_count());
Ok(())
}
fn judge_possibility(&self, neighbor_possibilities: &[Vec<TileId>], candidate: TileId) -> bool {
if neighbor_possibilities.is_empty() {
return true;
}
self.tiles.get_tile(candidate).is_some()
}
fn get_tile(&self, tile_id: TileId) -> Option<&Tile<&'static str>> {
self.tiles.get_tile(tile_id)
}
fn get_tile_count(&self) -> usize {
self.tiles.get_tile_count()
}
fn get_all_tile_ids(&self) -> Vec<TileId> {
self.tiles.get_all_tile_ids()
}
}
struct NumericTileSet {
tiles: TileSet<i32>,
}
impl NumericTileSet {
fn new() -> Self {
Self {
tiles: TileSet::new(),
}
}
}
impl TileSetVirtual<i32> for NumericTileSet {
fn build_tile_set(&mut self) -> Result<(), GridError> {
self.tiles.clear();
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());
Ok(())
}
fn judge_possibility(&self, neighbor_possibilities: &[Vec<TileId>], candidate: TileId) -> bool {
let Some(candidate_tile) = self.tiles.get_tile(candidate) else {
return false;
};
for (direction, neighbor_ids) in neighbor_possibilities.iter().enumerate() {
if neighbor_ids.is_empty() {
continue;
}
let is_compatible = neighbor_ids.iter().any(|&neighbor_id| {
if let Some(neighbor_tile) = self.tiles.get_tile(neighbor_id) {
let opposite_direction = (direction + 2) % 4;
if let (Some(¤t_edge), Some(&neighbor_edge)) = (
candidate_tile.get_edge(direction),
neighbor_tile.get_edge(opposite_direction),
) {
current_edge == neighbor_edge
} else {
false
}
} else {
false
}
});
if !is_compatible {
return false;
}
}
true
}
fn get_tile(&self, tile_id: TileId) -> Option<&Tile<i32>> {
self.tiles.get_tile(tile_id)
}
fn get_tile_count(&self) -> usize {
self.tiles.get_tile_count()
}
fn get_all_tile_ids(&self) -> Vec<TileId> {
self.tiles.get_all_tile_ids()
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== 瓷砖系统综合示例 ===\n");
println!("1. 基础TileSet使用:");
demonstrate_basic_tileset()?;
println!("\n2. 简单瓷砖集 (字符串边):");
demonstrate_simple_tileset()?;
println!("\n3. 数字瓷砖集 (整数边):");
demonstrate_numeric_tileset()?;
println!("\n4. 约束判断测试:");
demonstrate_constraint_checking()?;
println!("\n=== 示例完成 ===");
Ok(())
}
fn demonstrate_basic_tileset() -> Result<(), Box<dyn std::error::Error>> {
let mut tile_set = TileSet::new();
println!(" 创建基础瓷砖集...");
let tile1 = tile_set.add_tile(vec!["A", "B", "C", "D"], 10);
let tile2 = tile_set.add_tile(vec!["B", "A", "D", "C"], 15);
let _tile3 = tile_set.add_tile(vec!["C", "D", "A", "B"], 5);
println!(" 添加了 {} 个瓷砖", tile_set.get_tile_count());
for (i, tile) in tile_set.get_all_tiles().iter().enumerate() {
println!(
" 瓷砖 {}: ID={}, 权重={}, 边={:?}",
i, tile.id, tile.weight, tile.edges
);
}
if let (Some(t1), Some(t2)) = (tile_set.get_tile(tile1), tile_set.get_tile(tile2)) {
let compatible = t1.is_compatible_with(t2, 0); println!(" 瓷砖0和瓷砖1在方向0兼容: {}", compatible);
}
Ok(())
}
fn demonstrate_simple_tileset() -> Result<(), Box<dyn std::error::Error>> {
let mut simple_tileset = SimpleTileSet::new();
simple_tileset.build_tile_set()?;
println!("\n 瓷砖详情:");
for (i, tile) in simple_tileset.get_all_tiles().iter().enumerate() {
println!(" 瓷砖 {}: 边={:?}, 权重={}", i, tile.edges, tile.weight);
}
println!("\n 约束判断测试:");
test_constraint_judgment(&simple_tileset);
Ok(())
}
fn demonstrate_numeric_tileset() -> Result<(), Box<dyn std::error::Error>> {
let mut numeric_tileset = NumericTileSet::new();
numeric_tileset.build_tile_set()?;
println!("\n 瓷砖统计:");
let mut edge_types = std::collections::HashMap::new();
for tile in numeric_tileset.tiles.get_all_tiles() {
for &edge in &tile.edges {
*edge_types.entry(edge).or_insert(0) += 1;
}
}
for (edge_type, count) in edge_types {
let type_name = match edge_type {
0 => "平原",
1 => "山脉",
2 => "河流",
_ => "未知",
};
println!(" 边类型 {} ({}): {} 个边", edge_type, type_name, count);
}
Ok(())
}
fn demonstrate_constraint_checking() -> Result<(), Box<dyn std::error::Error>> {
let mut tileset = SimpleTileSet::new();
tileset.build_tile_set()?;
println!(" 测试不同约束情况:");
let no_constraints: Vec<Vec<TileId>> = vec![];
let result1 = tileset.judge_possibility(&no_constraints, 0);
println!(
" 无约束情况: {}",
if result1 { "可放置" } else { "不可放置" }
);
let single_constraint = vec![vec![0], vec![], vec![], vec![]]; let result2 = tileset.judge_possibility(&single_constraint, 1);
println!(
" 单方向约束: {}",
if result2 { "可放置" } else { "不可放置" }
);
let multi_constraints = vec![vec![0], vec![1], vec![], vec![]]; let result3 = tileset.judge_possibility(&multi_constraints, 2);
println!(
" 多方向约束: {}",
if result3 { "可放置" } else { "不可放置" }
);
let result4 = tileset.judge_possibility(&single_constraint, 999);
println!(
" 不存在瓷砖: {}",
if result4 { "可放置" } else { "不可放置" }
);
Ok(())
}
fn test_constraint_judgment(tileset: &SimpleTileSet) {
let grass_tile_id = 0; let water_tile_id = 1;
let same_type_constraint = vec![vec![grass_tile_id], vec![], vec![], vec![]];
let compatible_with_same = tileset.judge_possibility(&same_type_constraint, grass_tile_id);
println!(" 草地瓷砖与草地瓷砖兼容: {}", compatible_with_same);
let diff_type_constraint = vec![vec![water_tile_id], vec![], vec![], vec![]];
let compatible_with_diff = tileset.judge_possibility(&diff_type_constraint, grass_tile_id);
println!(" 草地瓷砖与水面瓷砖兼容: {}", compatible_with_diff);
if let Some(transition_tile) = tileset.get_tile(2) {
println!(" 过渡瓷砖边: {:?}", transition_tile.edges);
let transition_compatible = tileset.judge_possibility(&same_type_constraint, 2);
println!(" 过渡瓷砖与草地瓷砖兼容: {}", transition_compatible);
}
}