Generated on Mon Aug 25 11:35:32 2008 for Gecode by doxygen 1.5.6

minesweeper.cc

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Guido Tack <tack@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Guido Tack, 2006
00008  *
00009  *  Last modified:
00010  *     $Date: 2007-11-30 13:58:34 +0100 (Fri, 30 Nov 2007) $ by $Author: tack $
00011  *     $Revision: 5524 $
00012  *
00013  *  This file is part of Gecode, the generic constraint
00014  *  development environment:
00015  *     http://www.gecode.org
00016  *
00017  *  Permission is hereby granted, free of charge, to any person obtaining
00018  *  a copy of this software and associated documentation files (the
00019  *  "Software"), to deal in the Software without restriction, including
00020  *  without limitation the rights to use, copy, modify, merge, publish,
00021  *  distribute, sublicense, and/or sell copies of the Software, and to
00022  *  permit persons to whom the Software is furnished to do so, subject to
00023  *  the following conditions:
00024  *
00025  *  The above copyright notice and this permission notice shall be
00026  *  included in all copies or substantial portions of the Software.
00027  *
00028  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00029  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00030  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00031  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00032  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00033  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00034  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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--; // remove (x,y) itself
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     // Initialize matrix and post constraints
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     // Install branching
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       // 0
00178       "..2.3."
00179       "2....."
00180       "..24.3"
00181       "1.34.."
00182       ".....3"
00183       ".3.3..",
00184       // 1
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       // 2
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       // 3
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       // 4
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       // 5
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       // 6
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       // 7
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       // 8
00255       "......."
00256       ".23435."
00257       ".1...3."
00258       "...5..."
00259       ".1...3."
00260       ".12234."
00261       ".......",
00262       // 9
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     // std::alpha(c) == true
00297     int res = (c - 'A') + 10;
00298     if (res > n) return 0;
00299     else return res;
00300   }
00302 }
00303 
00304 // STATISTICS: example-any