1 module dkh.dungeon; 2 3 /// [+row, +col, -row, -col] 4 immutable static int[2][4] direction4 = [ 5 [1, 0], [0, 1], [-1, 0], [0, -1], 6 ]; 7 8 /// [+col, +row+col, +row, +row-col, ...] 9 immutable static int[2][8] direction8 = [ 10 [1, 0], 11 [1, 1], 12 [0, 1], 13 [-1, 1], 14 [-1, 0], 15 [-1, -1], 16 [0, -1], 17 [1, -1], 18 ]; 19 20 static int[2] addInt2(in int[2] a, in int[2] b) { 21 int[2] c; 22 c[] = a[] + b[]; 23 return c; 24 } 25 26 /** 27 プロコンでよくある2Dダンジョン探索を支援するライブラリ 28 $(D int[2] = [row, column])をベースとする 29 */ 30 struct Dungeon { 31 /// pからdir方向に移動したときの座標 32 static int[2] move4(int[2] p, int dir) { 33 return addInt2(p, direction4[dir]); 34 } 35 /// pからdir方向に移動したときの座標, 8方向 36 static int[2] move8(int[2] p, int dir) { 37 return addInt2(p, direction8[dir]); 38 } 39 40 immutable int R, C; 41 /** 42 Params: 43 R = row_max 44 C = column_max 45 */ 46 this(int R, int C) { 47 this.R = R; 48 this.C = C; 49 } 50 /// pが[0, 0] ~ [R-1, C-1]に入っているか? 51 bool isInside(int[2] p) const { 52 int r = p[0], c = p[1]; 53 return 0 <= r && r < R && 0 <= c && c < C; 54 } 55 /// 1次元に潰したときのID, r*R+c 56 int getID(int[2] p) const { 57 int r = p[0], c = p[1]; 58 return r*R+c; 59 } 60 } 61 62 /// 63 auto neighbors4(int[2] p) { 64 static struct Rng { 65 int[2] center; 66 size_t i; 67 bool empty() const { return i == 4;} 68 int[2] front() const { return addInt2(center, direction4[i]); } 69 void popFront() { i++; } 70 } 71 return Rng(p, 0); 72 } 73 74 /// 75 unittest { 76 import std.algorithm : equal; 77 assert(equal( 78 [3, 5].neighbors4, 79 [[4, 5], [3, 6], [2, 5], [3, 4]], 80 )); 81 } 82 83 /// list neighbors only inside 84 auto neighbors4(int[2] p, in Dungeon dg) { 85 static struct Rng { 86 int[2] center; 87 Dungeon dg; 88 size_t i; 89 this(in int[2] center, in Dungeon dg) { 90 this.center = center; 91 this.dg = dg; 92 while (!empty() && !dg.isInside(front)) i++; 93 } 94 bool empty() const { return i == 4;} 95 int[2] front() const { return addInt2(center, direction4[i]); } 96 void popFront() { 97 i++; 98 while (!empty() && !dg.isInside(front)) i++; 99 } 100 } 101 return Rng(p, dg); 102 } 103 104 /// 105 unittest { 106 import std.algorithm : equal; 107 assert(equal( 108 [0, 0].neighbors4(Dungeon(3, 3)), 109 [[1, 0], [0, 1]], 110 )); 111 }