1use crate::{
2 utils::{
3 cube_utils::{Axis, Color},
4 },
5 cube::{
6 slice::{CubeMove, CubeSliceOrder}
7 }
8};
9
10const PRINT_CHAR: &str = "██";
11const ANSI_RESET: &str = "\x1b[0m";
12
13#[derive(Debug, Clone)]
14pub enum MoveDirection {
15 Clockwise,
16 CounterClockwise,
17 Double,
18}
19
20impl MoveDirection {
21 pub fn flip(self) -> MoveDirection {
22 match self {
23 Self::Clockwise => Self::CounterClockwise,
24 Self::CounterClockwise => Self::Clockwise,
25 Self::Double => Self::Double,
26 }
27 }
28}
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
31pub enum GridSide {
32 Top,
33 Front,
34 Bottom,
35 Left,
36 Right,
37 Back,
38 MiddleX,
39 MiddleY,
40 MiddleZ,
41}
42
43impl GridSide {
44 pub fn idx(&self) -> usize {
45 match self {
46 GridSide::Top => 0,
47 GridSide::Left => 1,
48 GridSide::Front => 2,
49 GridSide::Right => 3,
50 GridSide::Back => 4,
51 GridSide::Bottom => 5,
52 _ => panic!()
53 }
54 }
55
56 pub fn from_idx(idx: usize) -> GridSide {
57 match idx {
58 0 => GridSide::Top,
59 1 => GridSide::Left,
60 2 => GridSide::Front,
61 3 => GridSide::Right,
62 4 => GridSide::Back,
63 5 => GridSide::Bottom,
64 _ => panic!(),
65 }
66 }
67
68 pub fn middle_layer_from_axis(axis: &Axis) -> GridSide {
69 match axis {
70 Axis::X => GridSide::MiddleX,
71 Axis::Y => GridSide::MiddleY,
72 Axis::Z => GridSide::MiddleZ
73 }
74 }
75
76 pub fn axis(&self) -> Axis {
77 match self {
78 GridSide::Top => Axis::Y,
79 GridSide::Left => Axis::X,
80 GridSide::Front => Axis::Z,
81 GridSide::Right => Axis::X,
82 GridSide::Back => Axis::Z,
83 GridSide::Bottom => Axis::Y,
84 GridSide::MiddleX => Axis::X,
85 GridSide::MiddleY => Axis::Y,
86 GridSide::MiddleZ => Axis::Z,
87 }
88 }
89
90 pub fn order(&self) -> CubeSliceOrder {
91 match self {
92 GridSide::Top => CubeSliceOrder::FIRST,
93 GridSide::Left => CubeSliceOrder::FIRST,
94 GridSide::Front => CubeSliceOrder::FIRST,
95 GridSide::Right => CubeSliceOrder::LAST,
96 GridSide::Back => CubeSliceOrder::LAST,
97 GridSide::Bottom => CubeSliceOrder::LAST,
98 GridSide::MiddleX => CubeSliceOrder::MIDDLE,
99 GridSide::MiddleY => CubeSliceOrder::MIDDLE,
100 GridSide::MiddleZ => CubeSliceOrder::MIDDLE,
101 }
102 }
103
104 pub fn is_middle(&self) -> bool {
105 match self {
106 GridSide::MiddleX => true,
107 GridSide::MiddleY => true,
108 GridSide::MiddleZ => true,
109 _ => false
110 }
111 }
112
113 pub fn middle_layer_adjacent(self) -> GridSide {
114 match self {
115 GridSide::MiddleX => GridSide::Left,
116 GridSide::MiddleY => GridSide::Bottom,
117 GridSide::MiddleZ => GridSide::Front,
118 _ => self
119 }
120 }
121}
122
123enum SliceType {
124 Top,
125 Bottom,
126 Left,
127 Right,
128 Vertical,
129 VerticalFlipped,
130 Horizontal,
131 HorizontalFlipped,
132}
133
134pub struct NeighborSlice {
135 side: GridSide,
136 slice_type: SliceType,
137}
138
139impl NeighborSlice {
140 pub fn read_from(&self, grid: &Grid) -> [Color; 3] {
141 let face = &grid.faces[self.side.idx()];
142 match self.slice_type {
143 SliceType::Top => {
144 [
145 face.grid[0][0],
146 face.grid[0][1],
147 face.grid[0][2],
148 ]
149 },
150 SliceType::Bottom => {
151 [
152 face.grid[2][2],
153 face.grid[2][1],
154 face.grid[2][0],
155 ]
156 },
157 SliceType::Left => {
158 [
159 face.grid[2][0],
160 face.grid[1][0],
161 face.grid[0][0],
162 ]
163 },
164 SliceType::Right => {
165 [
166 face.grid[0][2],
167 face.grid[1][2],
168 face.grid[2][2],
169 ]
170 },
171 SliceType::Vertical => {
172 [
173 face.grid[2][1],
174 face.grid[1][1],
175 face.grid[0][1],
176 ]
177 },
178 SliceType::VerticalFlipped => {
179 [
180 face.grid[0][1],
181 face.grid[1][1],
182 face.grid[2][1],
183 ]
184 },
185 SliceType::Horizontal => {
186 [
187 face.grid[1][0],
188 face.grid[1][1],
189 face.grid[1][2],
190 ]
191 },
192 SliceType::HorizontalFlipped => {
193 [
194 face.grid[1][2],
195 face.grid[1][1],
196 face.grid[1][0],
197 ]
198 },
199 }
200 }
201
202 fn write_to(&self, grid: &mut Grid, colors: [Color; 3]) {
203 let face = &mut grid.faces[self.side.idx()];
204 match self.slice_type {
205 SliceType::Top => {
206 face.grid[0][0] = colors[0];
207 face.grid[0][1] = colors[1];
208 face.grid[0][2] = colors[2];
209 },
210 SliceType::Bottom => {
211 face.grid[2][2] = colors[0];
212 face.grid[2][1] = colors[1];
213 face.grid[2][0] = colors[2];
214 },
215 SliceType::Left => {
216 face.grid[2][0] = colors[0];
217 face.grid[1][0] = colors[1];
218 face.grid[0][0] = colors[2];
219 },
220 SliceType::Right => {
221 face.grid[0][2] = colors[0];
222 face.grid[1][2] = colors[1];
223 face.grid[2][2] = colors[2];
224 },
225 SliceType::Vertical => {
226 face.grid[2][1] = colors[0];
227 face.grid[1][1] = colors[1];
228 face.grid[0][1] = colors[2];
229 },
230 SliceType::VerticalFlipped => {
231 face.grid[2][1] = colors[2];
232 face.grid[1][1] = colors[1];
233 face.grid[0][1] = colors[0];
234 },
235 SliceType::Horizontal => {
236 face.grid[1][0] = colors[0];
237 face.grid[1][1] = colors[1];
238 face.grid[1][2] = colors[2];
239 },
240 SliceType::HorizontalFlipped => {
241 face.grid[1][0] = colors[2];
242 face.grid[1][1] = colors[1];
243 face.grid[1][2] = colors[0];
244 },
245 }
246 }
247}
248
249#[derive(Debug, Clone, Copy, PartialEq, Eq)]
250pub struct GridFace {
251 pub grid: [[Color; 3]; 3],
252}
253
254impl GridFace {
255 pub fn new(color: Color) -> GridFace {
256 GridFace {
257 grid: [[color; 3]; 3],
258 }
259 }
260
261 pub fn empty() -> GridFace {
262 Self::new(Color::Gray)
263 }
264
265 pub fn print(&self) {
266 for row in self.grid.iter() {
267 for color in row {
268 print!("{}{}{}", color.to_ansi(), PRINT_CHAR, ANSI_RESET);
269 }
270 println!();
271 }
272 }
273
274 pub fn print_row(&self, idx: usize) {
275 for color in self.grid[idx] {
276 print!("{}{}{}", color.to_ansi(), PRINT_CHAR, ANSI_RESET);
277 }
278 }
279
280 pub fn rotate(&mut self, direction: &MoveDirection) {
281 match direction {
282 MoveDirection::Clockwise => self.rotate_clockwise(),
283 MoveDirection::CounterClockwise => self.rotate_counter_clockwise(),
284 MoveDirection::Double => {
285 self.rotate_clockwise();
286 self.rotate_clockwise();
287 }
288 }
289 }
290
291 pub fn rotate_clockwise(&mut self) {
292 let tmp = self.grid[0][0];
294 self.grid[0][0] = self.grid[2][0];
295 self.grid[2][0] = self.grid[2][2];
296 self.grid[2][2] = self.grid[0][2];
297 self.grid[0][2] = tmp;
298
299 let tmp = self.grid[0][1];
301 self.grid[0][1] = self.grid[1][0];
302 self.grid[1][0] = self.grid[2][1];
303 self.grid[2][1] = self.grid[1][2];
304 self.grid[1][2] = tmp;
305 }
306
307 pub fn rotate_counter_clockwise(&mut self) {
308 let tmp = self.grid[0][0];
310 self.grid[0][0] = self.grid[0][2];
311 self.grid[0][2] = self.grid[2][2];
312 self.grid[2][2] = self.grid[2][0];
313 self.grid[2][0] = tmp;
314
315 let tmp = self.grid[0][1];
317 self.grid[0][1] = self.grid[1][2];
318 self.grid[1][2] = self.grid[2][1];
319 self.grid[2][1] = self.grid[1][0];
320 self.grid[1][0] = tmp;
321 }
322}
323
324pub struct Grid {
325 pub faces: [GridFace; 6],
326}
327
328impl Grid {
329 pub fn new() -> Grid {
330 Grid {
331 faces: [
332 GridFace::new(Color::White),
333 GridFace::new(Color::Orange),
334 GridFace::new(Color::Green),
335 GridFace::new(Color::Red),
336 GridFace::new(Color::Blue),
337 GridFace::new(Color::Yellow),
338 ]
339 }
340 }
341
342 pub fn apply_move(&mut self, mv: CubeMove) {
343 self.move_face(mv.grid_side, mv.direction);
344 }
345
346 pub fn print(&self) {
347 fn print_blank_row() {
348 for _ in 0..3 {
349 print!("{}{}{}", Color::Gray.to_ansi(), PRINT_CHAR, ANSI_RESET);
350 }
351 }
352
353 for row in 0..3 {
354 print_blank_row();
355 self.faces[0].print_row(row);
356 print_blank_row();
357 print_blank_row();
358 println!();
359 }
360
361 for row in 0..3 {
362 for face in 1..5 {
363 self.faces[face].print_row(row);
364 }
365 println!();
366 }
367
368 for row in 0..3 {
369 print_blank_row();
370 self.faces[5].print_row(row);
371 print_blank_row();
372 print_blank_row();
373 println!();
374 }
375
376 print!("\n\n\n");
377 }
378
379 fn rotate_buffers(buffers: &mut Vec<[Color; 3]>, grid_side: &GridSide, direction: MoveDirection) {
380 match grid_side {
381 GridSide::Left
382 | GridSide::Top
383 | GridSide::Front
384 | GridSide::MiddleX
385 | GridSide::MiddleZ => match direction {
386 MoveDirection::Clockwise => buffers.rotate_right(1),
387 MoveDirection::CounterClockwise => buffers.rotate_left(1),
388 MoveDirection::Double => buffers.rotate_right(2),
389 }
390 _ => match direction {
391 MoveDirection::Clockwise => buffers.rotate_left(1),
392 MoveDirection::CounterClockwise => buffers.rotate_right(1),
393 MoveDirection::Double => buffers.rotate_right(2),
394 }
395 };
396
397 }
398
399 pub fn move_face(&mut self, side: GridSide, direction: MoveDirection) {
400 if !side.is_middle() {
401 let idx = side.idx();
402 self.faces[idx].rotate(&direction);
403 }
404
405 let neighbors = self.get_neighbors(side);
406 let mut buffers: Vec<[Color; 3]> = neighbors.iter()
407 .map(|ns| {
408 ns.read_from(self)
409 }
410 )
411 .collect();
412
413 Grid::rotate_buffers(&mut buffers, &side, direction);
414
415 for (slice, colors) in neighbors.into_iter().zip(buffers) {
416 slice.write_to(self, colors);
417 }
418 }
419
420 pub fn get_neighbors(&self, side: GridSide) -> [NeighborSlice; 4] {
421 match side {
422 GridSide::Top => [
423 NeighborSlice {slice_type: SliceType::Top, side: GridSide::Back},
424 NeighborSlice {slice_type: SliceType::Top, side: GridSide::Right},
425 NeighborSlice {slice_type: SliceType::Top, side: GridSide::Front},
426 NeighborSlice {slice_type: SliceType::Top, side: GridSide::Left},
427 ],
428 GridSide::Front => [
429 NeighborSlice {slice_type: SliceType::Bottom, side: GridSide::Top},
430 NeighborSlice {slice_type: SliceType::Left, side: GridSide::Right},
431 NeighborSlice {slice_type: SliceType::Top, side: GridSide::Bottom},
432 NeighborSlice {slice_type: SliceType::Right, side: GridSide::Left},
433 ],
434 GridSide::Bottom => [
435 NeighborSlice {slice_type: SliceType::Bottom, side: GridSide::Back},
436 NeighborSlice {slice_type: SliceType::Bottom, side: GridSide::Right},
437 NeighborSlice {slice_type: SliceType::Bottom, side: GridSide::Front},
438 NeighborSlice {slice_type: SliceType::Bottom, side: GridSide::Left},
439 ],
440 GridSide::Left => [
441 NeighborSlice {slice_type: SliceType::Left, side: GridSide::Top},
442 NeighborSlice {slice_type: SliceType::Left, side: GridSide::Front},
443 NeighborSlice {slice_type: SliceType::Left, side: GridSide::Bottom},
444 NeighborSlice {slice_type: SliceType::Right, side: GridSide::Back},
445 ],
446 GridSide::Right => [
447 NeighborSlice {slice_type: SliceType::Right, side: GridSide::Top},
448 NeighborSlice {slice_type: SliceType::Right, side: GridSide::Front},
449 NeighborSlice {slice_type: SliceType::Right, side: GridSide::Bottom},
450 NeighborSlice {slice_type: SliceType::Left, side: GridSide::Back},
451 ],
452 GridSide::Back => [
453 NeighborSlice {slice_type: SliceType::Top, side: GridSide::Top},
454 NeighborSlice {slice_type: SliceType::Right, side: GridSide::Right},
455 NeighborSlice {slice_type: SliceType::Bottom, side: GridSide::Bottom},
456 NeighborSlice {slice_type: SliceType::Left, side: GridSide::Left},
457 ],
458 GridSide::MiddleX => [
459 NeighborSlice {slice_type: SliceType::Vertical, side: GridSide::Top},
460 NeighborSlice {slice_type: SliceType::Vertical, side: GridSide::Front},
461 NeighborSlice {slice_type: SliceType::Vertical, side: GridSide::Bottom},
462 NeighborSlice {slice_type: SliceType::VerticalFlipped, side: GridSide::Back},
463 ],
464 GridSide::MiddleY => [
465 NeighborSlice {slice_type: SliceType::Horizontal, side: GridSide::Back},
466 NeighborSlice {slice_type: SliceType::Horizontal, side: GridSide::Right},
467 NeighborSlice {slice_type: SliceType::Horizontal, side: GridSide::Front},
468 NeighborSlice {slice_type: SliceType::Horizontal, side: GridSide::Left},
469 ],
470 GridSide::MiddleZ => [
471 NeighborSlice {slice_type: SliceType::HorizontalFlipped, side: GridSide::Top},
472 NeighborSlice {slice_type: SliceType::Vertical, side: GridSide::Right},
473 NeighborSlice {slice_type: SliceType::Horizontal, side: GridSide::Bottom},
474 NeighborSlice {slice_type: SliceType::VerticalFlipped, side: GridSide::Left},
475 ],
476 }
477 }
478}
479
480#[cfg(test)]
481mod tests {
482 use super::*;
483 use crate::utils::cube_utils::Color;
484 use Color::*;
485
486 fn assert_whole_color(grid: &Grid, side: GridSide, color: Color) -> bool {
487 let face = &grid.faces[side.idx()];
488 for row in face.grid {
489 for c in row {
490 if c != color {
491 return false;
492 }
493 }
494 };
495 true
496 }
497
498 fn assert_right_color(grid: &Grid, side: GridSide, color: Color) -> bool {
499 let face_grid = &grid.faces[side.idx()].grid;
500 face_grid[0][2] == color && face_grid[1][2] == color && face_grid[2][2] == color
501 }
502
503 fn assert_left_color(grid: &Grid, side: GridSide, color: Color) -> bool {
504 let face_grid = &grid.faces[side.idx()].grid;
505 face_grid[0][0] == color && face_grid[1][0] == color && face_grid[2][0] == color
506 }
507
508 fn assert_top_color(grid: &Grid, side: GridSide, color: Color) -> bool {
509 let face_grid = &grid.faces[side.idx()].grid;
510 face_grid[0][0] == color && face_grid[0][1] == color && face_grid[0][2] == color
511 }
512
513 fn assert_bottom_color(grid: &Grid, side: GridSide, color: Color) -> bool {
514 let face_grid = &grid.faces[side.idx()].grid;
515 face_grid[2][0] == color && face_grid[2][1] == color && face_grid[2][2] == color
516 }
517
518 fn assert_solved_cube(grid: &Grid) -> bool {
519 assert_whole_color(grid, GridSide::Top, Color::White)
520 && assert_whole_color(grid, GridSide::Left, Color::Orange)
521 && assert_whole_color(grid, GridSide::Front, Color::Green)
522 && assert_whole_color(grid, GridSide::Right, Color::Red)
523 && assert_whole_color(grid, GridSide::Back, Color::Blue)
524 && assert_whole_color(grid, GridSide::Bottom, Color::Yellow)
525 }
526
527 fn new_custom_face(grid: [[Color; 3]; 3]) -> GridFace {
528 GridFace { grid }
529 }
530
531 fn create_solved_grid() -> Grid {
532 Grid {
533 faces: [
534 GridFace::new(White), GridFace::new(Orange), GridFace::new(Green), GridFace::new(Red), GridFace::new(Blue), GridFace::new(Yellow), ],
541 }
542 }
543
544 fn create_mixed_grid() -> Grid {
545 Grid {
546 faces: [
547 new_custom_face([
549 [Red, White, Green],
550 [Green, White, Blue],
551 [White, Blue, Blue],
552 ]),
553 new_custom_face([
555 [Blue, Orange, Red],
556 [Yellow, Orange, Yellow],
557 [Green, Green, Orange],
558 ]),
559 new_custom_face([
561 [Blue, Red, Orange],
562 [Green, Green, Orange],
563 [Yellow, Yellow, Green],
564 ]),
565 new_custom_face([
567 [White, Orange, Orange],
568 [Yellow, Red, Orange],
569 [Red, Red, Green],
570 ]),
571 new_custom_face([
573 [Yellow, Green, Yellow],
574 [White, Blue, Red],
575 [White, White, White],
576 ]),
577 new_custom_face([
579 [Blue, Blue, Yellow],
580 [Red, Yellow, White],
581 [Orange, Blue, Red],
582 ]),
583 ],
584 }
585 }
586
587 #[test]
588 fn test_move_right() {
589 let mut grid = create_solved_grid();
590 grid.move_face(GridSide::Right, MoveDirection::Clockwise);
591
592 assert!(assert_whole_color(&grid, GridSide::Right, Color::Red));
593 assert!(assert_right_color(&grid, GridSide::Front, Color::Yellow));
594 assert!(assert_right_color(&grid, GridSide::Top, Color::Green));
595 assert!(assert_left_color(&grid, GridSide::Back, Color::White));
596 assert!(assert_right_color(&grid, GridSide::Bottom, Color::Blue));
597
598 grid.move_face(GridSide::Right, MoveDirection::CounterClockwise);
599
600 assert!(assert_solved_cube(&grid));
601 }
602
603 #[test]
604 fn test_move_left() {
605 let mut grid = create_solved_grid();
606 grid.move_face(GridSide::Left, MoveDirection::Clockwise);
607
608 assert!(assert_whole_color(&grid, GridSide::Left, Color::Orange));
609 assert!(assert_left_color(&grid, GridSide::Front, Color::White));
610 assert!(assert_left_color(&grid, GridSide::Top, Color::Blue));
611 assert!(assert_right_color(&grid, GridSide::Back, Color::Yellow));
612 assert!(assert_left_color(&grid, GridSide::Bottom, Color::Green));
613
614 grid.move_face(GridSide::Left, MoveDirection::CounterClockwise);
615
616 assert!(assert_solved_cube(&grid));
617 }
618
619 #[test]
620 fn test_move_front() {
621 let mut grid = create_solved_grid();
622 grid.move_face(GridSide::Front, MoveDirection::Clockwise);
623
624 assert!(assert_whole_color(&grid, GridSide::Front, Color::Green));
625 assert!(assert_bottom_color(&grid, GridSide::Top, Color::Orange));
626 assert!(assert_left_color(&grid, GridSide::Right, Color::White));
627 assert!(assert_top_color(&grid, GridSide::Bottom, Color::Red));
628 assert!(assert_right_color(&grid, GridSide::Left, Color::Yellow));
629
630 grid.move_face(GridSide::Front, MoveDirection::CounterClockwise);
631
632 assert!(assert_solved_cube(&grid));
633 }
634
635 #[test]
636 fn test_move_top() {
637 let mut grid = create_solved_grid();
638 grid.move_face(GridSide::Top, MoveDirection::Clockwise);
639
640 assert!(assert_whole_color(&grid, GridSide::Top, Color::White));
641 assert!(assert_top_color(&grid, GridSide::Front, Color::Red));
642 assert!(assert_top_color(&grid, GridSide::Left, Color::Green));
643 assert!(assert_top_color(&grid, GridSide::Right, Color::Blue));
644 assert!(assert_top_color(&grid, GridSide::Back, Color::Orange));
645
646 grid.move_face(GridSide::Top, MoveDirection::CounterClockwise);
647
648 assert!(assert_solved_cube(&grid));
649 }
650
651 #[test]
652 fn test_move_bottom() {
653 let mut grid = create_solved_grid();
654 grid.move_face(GridSide::Bottom, MoveDirection::Clockwise);
655
656 assert!(assert_whole_color(&grid, GridSide::Bottom, Color::Yellow));
657 assert!(assert_bottom_color(&grid, GridSide::Front, Color::Orange));
658 assert!(assert_bottom_color(&grid, GridSide::Left, Color::Blue));
659 assert!(assert_bottom_color(&grid, GridSide::Right, Color::Green));
660 assert!(assert_bottom_color(&grid, GridSide::Back, Color::Red));
661
662 grid.move_face(GridSide::Bottom, MoveDirection::CounterClockwise);
663
664 assert!(assert_solved_cube(&grid));
665 }
666
667 #[test]
668 fn test_move_back() {
669 let mut grid = create_solved_grid();
670 grid.move_face(GridSide::Back, MoveDirection::Clockwise);
671
672 assert!(assert_whole_color(&grid, GridSide::Back, Color::Blue));
673 assert!(assert_top_color(&grid, GridSide::Top, Color::Red));
674 assert!(assert_right_color(&grid, GridSide::Right, Color::Yellow));
675 assert!(assert_left_color(&grid, GridSide::Left, Color::White));
676 assert!(assert_bottom_color(&grid, GridSide::Bottom, Color::Orange));
677
678 grid.move_face(GridSide::Back, MoveDirection::CounterClockwise);
679
680 assert!(assert_solved_cube(&grid));
681 }
682
683 #[test]
684 fn test_middle_move_m() {
685 use GridSide::*;
686 use MoveDirection::*;
687
688 let mut grid = create_solved_grid();
689
690 grid.move_face(Top, Clockwise);
691 grid.move_face(Bottom, Clockwise);
692 grid.move_face(Front, Clockwise);
693 grid.move_face(Right, Clockwise);
694 grid.move_face(Top, Clockwise);
695
696 grid.move_face(MiddleX, Clockwise);
697
698 let front = &grid.faces[Front.idx()];
699 assert_eq!(front, &new_custom_face([
700 [White, White, White],
701 [Orange, White, Yellow],
702 [Orange, Red, Yellow],
703 ]));
704
705 let top = &grid.faces[Top.idx()];
706 assert_eq!(top, &new_custom_face([
707 [Blue, Red, White],
708 [Orange, Blue, White],
709 [Red, Green, Red],
710 ]));
711
712 let back = &grid.faces[Back.idx()];
713 assert_eq!(back, &new_custom_face([
714 [Green, Yellow, Yellow],
715 [White, Yellow, Blue],
716 [White, Red, Red],
717 ]));
718
719 let bottom = &grid.faces[Bottom.idx()];
720 assert_eq!(bottom, &new_custom_face([
721 [Green, White, Red],
722 [Yellow, Green, Blue],
723 [Yellow, Green, Orange],
724 ]));
725 }
726
727 #[test]
728 fn test_middle_move_m_counter_clockwise() {
729 use GridSide::*;
730 use MoveDirection::*;
731
732 let mut grid = create_solved_grid();
733
734 grid.move_face(Top, Clockwise);
735 grid.move_face(Bottom, Clockwise);
736 grid.move_face(Front, Clockwise);
737 grid.move_face(Right, Clockwise);
738 grid.move_face(Top, Clockwise);
739
740 grid.move_face(MiddleX, CounterClockwise);
741
742 let front = &grid.faces[Front.idx()];
743 assert_eq!(front, &new_custom_face([
744 [White, Red, White],
745 [Orange, Yellow, Yellow],
746 [Orange, Yellow, Yellow],
747 ]));
748
749 let top = &grid.faces[Top.idx()];
750 assert_eq!(top, &new_custom_face([
751 [Blue, White, White],
752 [Orange, Green, White],
753 [Red, Green, Red],
754 ]));
755
756 let back = &grid.faces[Back.idx()];
757 assert_eq!(back, &new_custom_face([
758 [Green, Red, Yellow],
759 [White, White, Blue],
760 [White, White, Red],
761 ]));
762
763 let bottom = &grid.faces[Bottom.idx()];
764 assert_eq!(bottom, &new_custom_face([
765 [Green, Red, Red],
766 [Yellow, Blue, Blue],
767 [Yellow, Green, Orange],
768 ]));
769 }
770
771 #[test]
772 fn test_middle_move_s() {
773 use GridSide::*;
774 use MoveDirection::*;
775
776 let mut grid = create_solved_grid();
777
778 grid.move_face(Top, Clockwise);
779 grid.move_face(Bottom, Clockwise);
780 grid.move_face(Right, Clockwise);
781 grid.move_face(Back, Clockwise);
782 grid.move_face(Top, Clockwise);
783
784 grid.move_face(MiddleZ, Clockwise);
785
786 let top = &grid.faces[Top.idx()];
787 assert_eq!(top, &new_custom_face([
788 [White, White, Blue],
789 [Blue, Orange, Red],
790 [Orange, Green, Blue],
791 ]));
792
793 let right = &grid.faces[Right.idx()];
794 assert_eq!(right, &new_custom_face([
795 [White, White, White],
796 [Green, White, Yellow],
797 [Green, Blue, Yellow],
798 ]));
799
800 let bottom = &grid.faces[Bottom.idx()];
801 assert_eq!(bottom, &new_custom_face([
802 [Yellow, Yellow, Red],
803 [Red, Red, White],
804 [Green, Orange, Blue],
805 ]));
806
807 let left = &grid.faces[Left.idx()];
808 assert_eq!(left, &new_custom_face([
809 [Red, Yellow, Yellow],
810 [White, Yellow, Orange],
811 [White, Blue, Blue],
812 ]));
813
814 }
815
816 #[test]
817 fn test_middle_move_s_counter_clockwise() {
818 use GridSide::*;
819 use MoveDirection::*;
820
821 let mut grid = create_solved_grid();
822
823 grid.move_face(Top, Clockwise);
824 grid.move_face(Bottom, Clockwise);
825 grid.move_face(Right, Clockwise);
826 grid.move_face(Back, Clockwise);
827 grid.move_face(Top, Clockwise);
828
829 grid.move_face(MiddleZ, CounterClockwise);
830
831 let top = &grid.faces[Top.idx()];
832 assert_eq!(top, &new_custom_face([
833 [White, White, Blue],
834 [White, Red, Red],
835 [Orange, Green, Blue],
836 ]));
837
838 let right = &grid.faces[Right.idx()];
839 assert_eq!(right, &new_custom_face([
840 [White, Blue, White],
841 [Green, Yellow, Yellow],
842 [Green, Yellow, Yellow],
843 ]));
844
845 let bottom = &grid.faces[Bottom.idx()];
846 assert_eq!(bottom, &new_custom_face([
847 [Yellow, Yellow, Red],
848 [Red, Orange, Blue],
849 [Green, Orange, Blue],
850 ]));
851
852 let left = &grid.faces[Left.idx()];
853 assert_eq!(left, &new_custom_face([
854 [Red, Blue, Yellow],
855 [White, White, Orange],
856 [White, White, Blue],
857 ]));
858
859 }
860
861 #[test]
862 fn test_middle_move_e() {
863 use GridSide::*;
864 use MoveDirection::*;
865
866 let mut grid = create_solved_grid();
867
868 grid.move_face(Front, Clockwise);
869 grid.move_face(Back, Clockwise);
870 grid.move_face(Right, Clockwise);
871 grid.move_face(Top, Clockwise);
872 grid.move_face(Front, Clockwise);
873
874 grid.move_face(MiddleY, Clockwise);
875
876 let front = &grid.faces[Front.idx()];
877 assert_eq!(front, &new_custom_face([
878 [Green, Green, White],
879 [White, Orange, Red],
880 [Orange, Yellow, White],
881 ]));
882
883 let right = &grid.faces[Right.idx()];
884 assert_eq!(right, &new_custom_face([
885 [Green, Blue, Blue],
886 [Green, Green, White],
887 [Green, Yellow, Yellow],
888 ]));
889
890 let back = &grid.faces[Back.idx()];
891 assert_eq!(back, &new_custom_face([
892 [White, Orange, Yellow],
893 [Green, Red, Red],
894 [Red, Blue, Blue],
895 ]));
896
897 let left = &grid.faces[Left.idx()];
898 assert_eq!(left, &new_custom_face([
899 [Green, Green, Red],
900 [White, Blue, Blue],
901 [White, Orange, Blue],
902 ]));
903
904 }
905
906 #[test]
907 fn test_middle_move_e_counter_clockwise() {
908 use GridSide::*;
909 use MoveDirection::*;
910
911 let mut grid = create_solved_grid();
912
913 grid.move_face(Front, Clockwise);
914 grid.move_face(Back, Clockwise);
915 grid.move_face(Right, Clockwise);
916 grid.move_face(Top, Clockwise);
917 grid.move_face(Front, Clockwise);
918
919 grid.move_face(MiddleY, CounterClockwise);
920
921 let front = &grid.faces[Front.idx()];
922 assert_eq!(front, &new_custom_face([
923 [Green, Green, White],
924 [Green, Red, Red],
925 [Orange, Yellow, White],
926 ]));
927
928 let right = &grid.faces[Right.idx()];
929 assert_eq!(right, &new_custom_face([
930 [Green, Blue, Blue],
931 [White, Blue, Blue],
932 [Green, Yellow, Yellow],
933 ]));
934
935 let back = &grid.faces[Back.idx()];
936 assert_eq!(back, &new_custom_face([
937 [White, Orange, Yellow],
938 [White, Orange, Red],
939 [Red, Blue, Blue],
940 ]));
941
942 let left = &grid.faces[Left.idx()];
943 assert_eq!(left, &new_custom_face([
944 [Green, Green, Red],
945 [Green, Green, White],
946 [White, Orange, Blue],
947 ]));
948
949 }
950
951 #[test]
952 fn test_solving_mixed_cube() {
953 use GridSide::*;
954 use MoveDirection::*;
955
956 let mut grid = create_mixed_grid();
957
958 let moves = vec![
959 (Bottom, Clockwise),
960 (Left, CounterClockwise),
961 (Front, Clockwise),
962 (Right, CounterClockwise),
963
964 (Bottom, Clockwise),
965 (Right, Clockwise),
966 (Right, Clockwise),
967 (Left, Clockwise),
968
969 (Front, Clockwise),
970 (Left, CounterClockwise),
971 (Right, Clockwise),
972 (Right, Clockwise),
973
974 (Front, CounterClockwise),
975 (Top, Clockwise),
976 (Top, Clockwise),
977 (Back, CounterClockwise),
978
979 (Right, Clockwise),
980 (Right, Clockwise),
981 (Back, Clockwise),
982 (Top, Clockwise),
983 (Top, Clockwise),
984
985 (Front, CounterClockwise),
986 (Left, Clockwise),
987 (Left, Clockwise),
988
989 (Top, Clockwise),
990 (Top, Clockwise),
991 (Back, Clockwise),
992 ];
993
994 for (side, direction) in moves {
995 grid.move_face(side, direction);
996 }
997
998 assert!(assert_solved_cube(&grid))
999 }
1000}