left_forward/forward_left,...

main
serr 2025-06-25 16:12:48 +03:00
parent 8b47d9904e
commit ec47191a4d
5 changed files with 102 additions and 33 deletions

BIN
imgs/circle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
imgs/square.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -1,19 +1,45 @@
mod turtle; mod turtle;
use turtle::Turtle; use turtle::{defaults, Turtle};
fn square(turtle: &mut turtle::Turtle) { #[allow(dead_code)]
turtle.left(90.0); fn square() {
turtle.forward(5); let mut turtle = Turtle::new();
let default_pos = defaults::position();
let steps_count = 20;
turtle.set_pos((
default_pos.0 - (turtle.step_length() * steps_count / 2) as i32,
default_pos.1 + (turtle.step_length() * steps_count / 2) as i32
));
turtle.left_forward(90.0, steps_count);
for _ in 0..3 { for _ in 0..3 {
turtle.right(90.0); turtle.right_forward(90.0, steps_count);
turtle.forward(5);
} }
turtle.save("imgs/square.png").unwrap();
}
#[allow(dead_code)]
fn circle() {
let mut turtle = Turtle::new();
let default_pos = defaults::position();
let circumference = (36 * 2 * defaults::STEP_LENGTH) as f64;
let radius = circumference / (2.0 * std::f64::consts::PI);
turtle.set_pos((
default_pos.0 - (turtle.step_length() * 2 / 2) as i32,
default_pos.1 - radius as i32
));
for _ in 0..36 {
turtle.forward_right(2, 10.0);
}
turtle.save("imgs/circle.png").unwrap();
} }
fn main() { fn main() {
let mut turtle = Turtle::new(); square();
circle();
square(&mut turtle);
turtle.save("output.png").unwrap();
} }

View File

@ -8,36 +8,50 @@ type ImgBufU8 = ImageBuffer<Rgb<u8>, Vec<u8>>;
type Colour = Rgb<u8>; type Colour = Rgb<u8>;
type Coord = (i32, i32); type Coord = (i32, i32);
const DEFAULT_WIDTH: u32 = 300; pub mod defaults {
const DEFAULT_HEIGHT: u32 = 300; use super::{Colour, Coord, Rgb};
const DEFAULT_BACKGROUND_COLOUR: Colour = Rgb([255u8, 255u8, 255u8]);
const DEFAULT_COLOUR: Colour = Rgb([0u8, 0u8, 0u8]); pub const WIDTH: u32 = 300;
const DEFAULT_POS: Coord = ((DEFAULT_WIDTH as f64/2.0) as i32, (DEFAULT_HEIGHT as f64/2.0) as i32); pub const HEIGHT: u32 = 300;
pub const BACKGROUND_COLOUR: Colour = Rgb([255u8, 255u8, 255u8]);
pub const COLOUR: Colour = Rgb([0u8, 0u8, 0u8]);
pub const STEP_LENGTH: u32 = 10;
pub const ANGLE: f64 = 0.0;
pub fn position() -> Coord {
((WIDTH as f64 / 2.0) as i32,
(HEIGHT as f64 / 2.0) as i32)
}
}
pub struct Turtle { pub struct Turtle {
buf: ImgBufU8, buf: ImgBufU8,
colour: Colour, colour: Colour,
pos: Coord, pos: Coord,
step_length: u32, step_length: u32,
angle: f64, // угол в радианах angle: f64,
} }
impl Turtle { impl Turtle {
pub fn new() -> Self { pub fn new() -> Self {
let mut buf = ImageBuffer::new(DEFAULT_WIDTH, DEFAULT_HEIGHT); let mut buf = ImageBuffer::new(defaults::WIDTH, defaults::HEIGHT);
for pixel in buf.pixels_mut() { for pixel in buf.pixels_mut() {
*pixel = DEFAULT_BACKGROUND_COLOUR; *pixel = defaults::BACKGROUND_COLOUR;
} }
Turtle { Turtle {
buf, buf,
colour: DEFAULT_COLOUR, colour: defaults::COLOUR,
pos: DEFAULT_POS, pos: defaults::position(),
step_length: 10, step_length: defaults::STEP_LENGTH,
angle: 0.0, angle: defaults::ANGLE,
} }
} }
pub fn step_length(&self) -> u32 {
self.step_length
}
pub fn position(&self) -> Coord { pub fn position(&self) -> Coord {
self.pos self.pos
} }
@ -46,26 +60,55 @@ impl Turtle {
self.angle.to_degrees() self.angle.to_degrees()
} }
pub fn set_pos(&mut self, coord: Coord) {
self.pos.0 = coord.0;
self.pos.1 = coord.1;
}
pub fn right(&mut self, degrees: f64) {
self.angle += degrees.to_radians();
self.angle = self.angle.rem_euclid(2.0 * std::f64::consts::PI);
}
pub fn right_forward(&mut self, degrees: f64, steps_count: u32) {
self.right(degrees);
self.forward(steps_count);
}
pub fn forward_right(&mut self, steps_count: u32, degrees: f64) {
self.forward(steps_count);
self.right(degrees);
}
pub fn left(&mut self, degrees: f64) {
self.angle -= degrees.to_radians();
self.angle = self.angle.rem_euclid(2.0 * std::f64::consts::PI);
}
pub fn left_forward(&mut self, degrees: f64, steps_count: u32) {
self.left(degrees);
self.forward(steps_count);
}
pub fn forward_left(&mut self, steps_count: u32, degrees: f64) {
self.forward(steps_count);
self.left(degrees);
}
pub fn forward(&mut self, steps_count: u32) { pub fn forward(&mut self, steps_count: u32) {
let start_pos = self.pos; let start_pos = self.pos;
let dy = self.angle.sin() * steps_count as f64 * self.step_length as f64; let dy = self.angle.sin() * steps_count as f64 * self.step_length as f64;
let dx = self.angle.cos() * steps_count as f64 * self.step_length as f64; let dx = self.angle.cos() * steps_count as f64 * self.step_length as f64;
self.pos.0 += dx.round() as i32; self.set_pos((
self.pos.1 += dy.round() as i32; self.pos.0 + dx.round() as i32,
self.pos.1 + dy.round() as i32
));
self.draw_line(start_pos, self.pos); self.draw_line(start_pos, self.pos);
} }
pub fn right(&mut self, degrees: f64) {
self.angle += degrees.to_radians();
}
pub fn left(&mut self, degrees: f64) {
self.angle -= degrees.to_radians();
}
pub fn save<P>(&self, output_path: P) -> ImageResult<()> pub fn save<P>(&self, output_path: P) -> ImageResult<()>
where where
P: AsRef<Path> P: AsRef<Path>