]> git.scottworley.com Git - slidingtile/blobdiff - sliding_tile_lib.cc
Generate successor boards
[slidingtile] / sliding_tile_lib.cc
index 5b2e798472d08e4b45f547461b71ff135fe787f5..b43cbbaa939df7b79172ecc7a528da67ebf23d79 100644 (file)
@@ -1,9 +1,13 @@
 #include "sliding_tile_lib.h"
 
+#include <cstdlib>
 #include <istream>
+#include <memory>
+#include <ostream>
 #include <stdexcept>
+#include <vector>
 
-signed char adjacent[BOARD_SIZE][5] = {
+signed char Step::adjacent[BOARD_SIZE][5] = {
   1,   4,   -1,  -1,  -1,
   0,   2,   5,   -1,  -1,
   1,   3,   6,   -1,  -1,
@@ -65,6 +69,16 @@ std::istream& operator>>(std::istream& is, Board& board) {
   return is;
 }
 
+std::ostream& operator<<(std::ostream& os, const Board& board) {
+  for (int i = 0; i < BOARD_SIZE; i++) {
+    if (i > 0) {
+      os << " ";
+    }
+    os << int(board.board[i]);
+  }
+  return os;
+}
+
 signed char Board::hole() const {
   for (int i = 0; i < BOARD_SIZE; i++) {
     if (board[i] == 0) {
@@ -73,3 +87,34 @@ signed char Board::hole() const {
   }
   throw std::runtime_error("Board with no hole");
 }
+
+InvertedBoard Board::invert() const {
+  InvertedBoard inv;
+  for (int i = 0; i < BOARD_SIZE; i++) {
+    inv.pos[board[i]] = i;
+  }
+  return inv;
+}
+
+int Board::distance(const Board& o) const {
+  return distance(o.invert());
+}
+
+int Board::distance(const InvertedBoard& invo) const {
+  int dist = 0;
+  for (int i = 0; i < BOARD_SIZE; i++) {
+    dist += std::abs(i % BOARD_DIM - invo.pos[board[i]] % BOARD_DIM) +
+            std::abs(i / BOARD_DIM - invo.pos[board[i]] / BOARD_DIM);
+  }
+  return dist;
+}
+
+std::vector<Step*> Step::successors(std::shared_ptr<Step> shared_this) {
+  std::vector<Step*> suc;
+  signed char hole_pos = board.hole();
+  for (int i = 0; adjacent[hole_pos][i] > 0; i++) {
+    suc.emplace_back(new Step{board, shared_this});
+    std::swap(suc.back()->board.board[hole_pos], suc.back()->board.board[adjacent[hole_pos][i]]);
+  }
+  return suc;
+}