00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <cctype>
00039
00040 #include "examples/support.hh"
00041 #include "gecode/minimodel.hh"
00042
00043 namespace {
00044 extern const char *specs[];
00045 extern const unsigned int n_examples;
00046 int spec_size(const char *s);
00047 int mineField(const char *s, int n, int i, int j);
00048 }
00049
00061 class MineSweeper : public Example {
00062 private:
00063 const char *spec;
00064 int size;
00065 BoolVarArray b;
00066
00068 BoolVar pos(int h, int w) {
00069 return b[h*size + w];
00070 }
00071
00073 BoolVarArgs fieldsAround(MiniModel::Matrix<BoolVarArray>& m,
00074 int x, int y) {
00075 int bvsize=0;
00076 for (int ix = std::max(0, x-1); ix<=x+1 && ix<size; ix++)
00077 for (int iy = std::max(0, y-1); iy<=y+1 && iy<size; iy++)
00078 bvsize++;
00079 bvsize--;
00080 BoolVarArgs b(bvsize);
00081 int count=0;
00082 for (int ix = std::max(0, x-1); ix<=x+1 && ix<size; ix++)
00083 for (int iy = std::max(0, y-1); iy<=y+1 && iy<size; iy++)
00084 if (ix != x || iy != y)
00085 b[count++] = m(ix,iy);
00086
00087 return b;
00088 }
00089
00090 public:
00092 MineSweeper(const SizeOptions& opt)
00093 : spec(specs[opt.size()]),
00094 size(spec_size(spec)),
00095 b(this,size*size,0,1) {
00096 MiniModel::Matrix<BoolVarArray> m(b, size, size);
00097
00098
00099 for (int h=0; h<size; h++)
00100 for (int w=0; w<size; w++) {
00101 int v = mineField(spec, size, h, w);
00102 if (v != -1) {
00103 rel(this, m(w, h), IRT_EQ, 0);
00104 linear(this, fieldsAround(m, w, h), IRT_EQ, v);
00105 }
00106 }
00107
00108
00109 branch(this, b, INT_VAR_NONE, INT_VAL_MAX);
00110 }
00111
00113 virtual void
00114 print(std::ostream& os) {
00115 for (int h = 0; h < size; ++h) {
00116 os << '\t';
00117 for (int w = 0; w < size; ++w) {
00118 int v = mineField(spec, size, h, w);
00119 if ( v != -1)
00120 os << v << " ";
00121 else if (pos(h,w).val() == 1)
00122 os << "* ";
00123 else
00124 os << ". ";
00125 }
00126 os << std::endl;
00127 }
00128 os << std::endl;
00129 }
00130
00132 MineSweeper(bool share, MineSweeper& s) :
00133 Example(share,s), spec(s.spec), size(s.size) {
00134 b.update(this, share, s.b);
00135 }
00137 virtual Space*
00138 copy(bool share) {
00139 return new MineSweeper(share,*this);
00140 }
00141
00142 };
00143
00144
00148 int
00149 main(int argc, char* argv[]) {
00150 SizeOptions opt("MineSweeper");
00151 opt.size(0);
00152 opt.parse(argc,argv);
00153 if (opt.size() >= n_examples) {
00154 std::cerr << "Error: size must be between 0 and "
00155 << n_examples-1 << std::endl;
00156 return 1;
00157 }
00158 Example::run<MineSweeper,DFS,SizeOptions>(opt);
00159 return 0;
00160 }
00161
00162
00163 namespace {
00164
00174
00176 const char* specs[] = {
00177
00178 "..2.3."
00179 "2....."
00180 "..24.3"
00181 "1.34.."
00182 ".....3"
00183 ".3.3..",
00184
00185 ".2.211.."
00186 "..4.2..2"
00187 "2..2..3."
00188 "2.22.3.3"
00189 "..1...4."
00190 "1...2..3"
00191 ".2.22.3."
00192 "1.1..1.1",
00193
00194 "1..2.2.2.."
00195 ".32...4..1"
00196 "...13...4."
00197 "3.1...3..."
00198 ".21.1..3.2"
00199 ".3.2..2.1."
00200 "2..32..2.."
00201 ".3...32..3"
00202 "..3.33...."
00203 ".2.2...22.",
00204
00205 "2...3.1."
00206 ".5.4...1"
00207 "..5..4.."
00208 "2...4.5."
00209 ".2.4...2"
00210 "..5..4.."
00211 "2...5.4."
00212 ".3.3...2",
00213
00214 "0.0.1..11."
00215 "1.2.2.22.."
00216 "......2..2"
00217 ".23.11...."
00218 "0......2.1"
00219 "...22.1..."
00220 ".....3.32."
00221 ".5.2...3.1"
00222 ".3.1..3..."
00223 ".2...12..0",
00224
00225 ".21.2.2..."
00226 ".4..3...53"
00227 "...4.44..3"
00228 "4.4..5.6.."
00229 "..45....54"
00230 "34....55.."
00231 "..4.4..5.5"
00232 "2..33.6..."
00233 "36...3..4."
00234 "...4.2.21.",
00235
00236 ".32..1.."
00237 "....1..3"
00238 "3..2...4"
00239 ".5...5.."
00240 "..6...5."
00241 "3...5..4"
00242 "2..5...."
00243 "..2..34.",
00244
00245 ".1.....3."
00246 "...343..."
00247 "244...443"
00248 "...4.4..."
00249 ".4.4.3.6."
00250 "...4.3..."
00251 "123...133"
00252 "...322..."
00253 ".2.....3.",
00254
00255 "......."
00256 ".23435."
00257 ".1...3."
00258 "...5..."
00259 ".1...3."
00260 ".12234."
00261 ".......",
00262
00263 "2...2...2"
00264 ".4.4.3.4."
00265 "..4...1.."
00266 ".4.3.3.4."
00267 "2.......2"
00268 ".5.4.5.4."
00269 "..3...3.."
00270 ".4.3.5.6."
00271 "2...1...2"
00272 };
00273
00275 const unsigned int n_examples = sizeof(specs)/sizeof(char*);
00276
00278 int spec_size(const char *s) {
00279 int l = std::strlen(s);
00280 int res = static_cast<int>(std::sqrt(static_cast<float>(l)));
00281 return res;
00282 }
00283
00285 int mineField(const char *s, int n, int i, int j) {
00286 assert(spec_size(s) == n);
00287 assert(i >= 0 && i < n);
00288 assert(j >= 0 && j < n);
00289 char c = s[i*n + j];
00290 if (!std::isalnum(c))
00291 return -1;
00292 if (std::isdigit(c))
00293 return c - '0';
00294 if (std::islower(c))
00295 c = static_cast<char>(std::toupper(c));
00296
00297 int res = (c - 'A') + 10;
00298 if (res > n) return 0;
00299 else return res;
00300 }
00302 }
00303
00304