• Skip to content
  • Skip to link menu
KDE 4.0 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

libkdegames

kgrid2d.h

Go to the documentation of this file.
00001 /*
00002     This file is part of the KDE games library
00003     Copyright (C) 2001-02 Nicolas Hadacek (hadacek@kde.org)
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License version 2 as published by the Free Software Foundation.
00008 
00009     This library is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     Library General Public License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to
00016     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017     Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #ifndef __KGRID2D_H_
00021 #define __KGRID2D_H_
00022 
00023 #include <math.h>
00024 
00025 #include <QtCore/QPair>
00026 #include <QtCore/QVector>
00027 //Added by qt3to4:
00028 #include <QtCore/QTextStream>
00029 
00030 #include <kglobal.h>
00031 
00032 
00033 //-----------------------------------------------------------------------------
00034 namespace KGrid2D
00035 {
00039     typedef QPair<int, int> Coord;
00040 
00044     typedef QList<Coord> CoordList;
00045 }
00046 
00047 inline KGrid2D::Coord
00048 operator +(const KGrid2D::Coord &c1, const KGrid2D::Coord &c2) {
00049     return KGrid2D::Coord(c1.first + c2.first, c1.second + c2.second);
00050 }
00051 
00052 inline KGrid2D::Coord
00053 operator -(const KGrid2D::Coord &c1, const KGrid2D::Coord &c2) {
00054     return KGrid2D::Coord(c1.first - c2.first, c1.second - c2.second);
00055 }
00056 
00060 inline KGrid2D::Coord
00061 maximum(const KGrid2D::Coord &c1, const KGrid2D::Coord &c2) {
00062     return KGrid2D::Coord(qMax(c1.first, c2.first), qMax(c1.second, c2.second));
00063 }
00067 inline KGrid2D::Coord
00068 minimum(const KGrid2D::Coord &c1, const KGrid2D::Coord &c2) {
00069     return KGrid2D::Coord(qMin(c1.first, c2.first), qMin(c1.second, c2.second));
00070 }
00071 
00072 inline QTextStream &operator <<(QTextStream &s, const KGrid2D::Coord &c) {
00073     return s << '(' << c.second << "," << c.first << ')';
00074 }
00075 
00076 inline QTextStream &operator <<(QTextStream &s, const KGrid2D::CoordList &list)
00077 {
00078     for(KGrid2D::CoordList::const_iterator i=list.begin(); i!=list.end(); ++i)
00079         s << *i;
00080     return s;
00081 }
00082 
00083 //-----------------------------------------------------------------------------
00084 namespace KGrid2D
00085 {
00090 template <class Type>
00091 class Generic
00092 {
00093  public:
00097     Generic(uint width = 0, uint height = 0) {
00098         resize(width, height);
00099     }
00100 
00101     virtual ~Generic() {}
00102 
00106     void resize(uint width, uint height) {
00107         _width = width;
00108         _height = height;
00109         _vector.resize(width*height);
00110     }
00111 
00115     void fill(const Type &value) {
00116         for (int i=0; i<_vector.count(); i++) _vector[i] = value;
00117     }
00118 
00122     uint width() const  { return _width; }
00126     uint height() const { return _height; }
00130     uint size() const   { return _width*_height; }
00131 
00135     uint index(const Coord &c) const {
00136         return c.first + c.second*_width;
00137     }
00138 
00142     Coord coord(uint index) const {
00143         return Coord(index % _width, index / _width);
00144     }
00145 
00149     const Type &at(const Coord &c) const { return _vector[index(c)]; }
00153     Type &at(const Coord &c)             { return _vector[index(c)]; }
00157     const Type &operator [](const Coord &c) const { return _vector[index(c)]; }
00161     Type &operator [](const Coord &c)             { return _vector[index(c)]; }
00162 
00166     const Type &at(uint index) const          { return _vector[index]; }
00170     Type &at(uint index)                      { return _vector[index]; }
00174     const Type &operator [](uint index) const { return _vector[index]; }
00178     Type &operator [](uint index)             { return _vector[index]; }
00179 
00183     bool inside(const Coord &c) const {
00184         return ( c.first>=0 && c.first<(int)_width
00185                  && c.second>=0 && c.second<(int)_height );
00186     }
00187 
00191     void bound(Coord &c) const {
00192         c.first = qMax(qMin(c.first, (int)_width-1), 0);
00193         c.second = qMax(qMin(c.second, (int)_height-1), 0);
00194     }
00195 
00196  protected:
00197     uint               _width, _height;
00198     QVector<Type> _vector;
00199 };
00200 }
00201 
00202 template <class Type>
00203 QDataStream &operator <<(QDataStream &s, const KGrid2D::Generic<Type> &m) {
00204     s << (quint32)m.width() << (quint32)m.height();
00205     for (uint i=0; i<m.size(); i++) s << m[i];
00206     return s;
00207 }
00208 
00209 template <class Type>
00210 QDataStream &operator >>(QDataStream &s, KGrid2D::Generic<Type> &m) {
00211     quint32 w, h;
00212     s >> w >> h;
00213     m.resize(w, h);
00214     for (uint i=0; i<m.size(); i++) s >> m[i];
00215     return s;
00216 }
00217 
00218 
00219 namespace KGrid2D
00220 {
00221 
00222 //-----------------------------------------------------------------------------
00227 class SquareBase
00228 {
00229  public:
00233     enum Neighbour { Left=0, Right, Up, Down, LeftUp, LeftDown,
00234                      RightUp, RightDown, Nb_Neighbour };
00235 
00239     static double angle(Neighbour n) {
00240         switch (n) {
00241         case Left:      return M_PI;
00242         case Right:     return 0;
00243         case Up:        return M_PI_2;
00244         case Down:      return -M_PI_2;
00245         case LeftUp:    return 3.0*M_PI_4;
00246         case LeftDown:  return -3.0*M_PI_4;
00247         case RightUp:   return M_PI_4;
00248         case RightDown: return -M_PI_4;
00249         case Nb_Neighbour: Q_ASSERT(false);
00250         }
00251         return 0;
00252     }
00253 
00257     static Neighbour opposed(Neighbour n) {
00258         switch (n) {
00259         case Left:      return Right;
00260         case Right:     return Left;
00261         case Up:        return Down;
00262         case Down:      return Up;
00263         case LeftUp:    return RightDown;
00264         case LeftDown:  return RightUp;
00265         case RightUp:   return LeftDown;
00266         case RightDown: return LeftUp;
00267         case Nb_Neighbour: Q_ASSERT(false);
00268         }
00269         return Nb_Neighbour;
00270     }
00271 
00276     static bool isDirect(Neighbour n) { return n<LeftUp; }
00277 
00281     static Coord neighbour(const Coord &c, Neighbour n) {
00282         switch (n) {
00283         case Left:      return c + Coord(-1,  0);
00284         case Right:     return c + Coord( 1,  0);
00285         case Up:        return c + Coord( 0, -1);
00286         case Down:      return c + Coord( 0,  1);
00287         case LeftUp:    return c + Coord(-1, -1);
00288         case LeftDown:  return c + Coord(-1,  1);
00289         case RightUp:   return c + Coord( 1, -1);
00290         case RightDown: return c + Coord( 1,  1);
00291         case Nb_Neighbour: Q_ASSERT(false);
00292         }
00293         return c;
00294     }
00295 };
00296 
00301 template <class T>
00302 class Square : public Generic<T>, public SquareBase
00303 {
00304  public:
00308     Square(uint width = 0, uint height = 0)
00309         : Generic<T>(width, height) {}
00310 
00318     CoordList neighbours(const Coord &c, bool insideOnly = true,
00319                          bool directOnly = false) const {
00320         CoordList neighbours;
00321         for (int i=0; i<(directOnly ? LeftUp : Nb_Neighbour); i++) {
00322             Coord n = neighbour(c, (Neighbour)i);
00323             if ( insideOnly && !Generic<T>::inside(n) ) continue;
00324             neighbours.append(n);
00325         }
00326         return neighbours;
00327     }
00328 
00335     Coord toEdge(const Coord &c, Neighbour n) const {
00336         switch (n) {
00337         case Left:      return Coord(0, c.second);
00338         case Right:     return Coord(Generic<T>::width()-1, c.second);
00339         case Up:        return Coord(c.first, 0);
00340         case Down:      return Coord(c.first, Generic<T>::height()-1);
00341         case LeftUp:    return Coord(0, 0);
00342         case LeftDown:  return Coord(0, Generic<T>::height()-1);
00343         case RightUp:   return Coord(Generic<T>::width()-1, 0);
00344         case RightDown: return Coord(Generic<T>::width()-1, Generic<T>::height()-1);
00345         case Nb_Neighbour: Q_ASSERT(false);
00346         }
00347         return c;
00348     }
00349 };
00350 
00351 //-----------------------------------------------------------------------------
00361 class HexagonalBase
00362 {
00363  public:
00367     enum Neighbour { Left = 0, Right, LeftUp, LeftDown,
00368                      RightUp, RightDown, Nb_Neighbour };
00369 
00373     static double angle(Neighbour n) {
00374         switch (n) {
00375         case Left:      return M_PI;
00376         case Right:     return 0;
00377         case LeftUp:    return 2.0*M_PI/3;
00378         case LeftDown:  return -2.0*M_PI/3;
00379         case RightUp:   return M_PI/3;
00380         case RightDown: return -M_PI/3;
00381         case Nb_Neighbour: Q_ASSERT(false);
00382         }
00383         return 0;
00384     }
00385 
00389     static Neighbour opposed(Neighbour n) {
00390         switch (n) {
00391         case Left:      return Right;
00392         case Right:     return Left;
00393         case LeftUp:    return RightDown;
00394         case LeftDown:  return RightUp;
00395         case RightUp:   return LeftDown;
00396         case RightDown: return LeftUp;
00397         case Nb_Neighbour: Q_ASSERT(false);
00398         }
00399         return Nb_Neighbour;
00400     }
00401 
00405     static Coord neighbour(const Coord &c, Neighbour n) {
00406         bool oddRow = c.second%2;
00407         switch (n) {
00408         case Left:      return c + Coord(-1,  0);
00409         case Right:     return c + Coord( 1,  0);
00410         case LeftUp:    return c + (oddRow ? Coord( 0, -1) : Coord(-1, -1));
00411         case LeftDown:  return c + (oddRow ? Coord( 0,  1) : Coord(-1,  1));
00412         case RightUp:   return c + (oddRow ? Coord( 1, -1) : Coord( 0, -1));
00413         case RightDown: return c + (oddRow ? Coord( 1,  1) : Coord( 0,  1));
00414         case Nb_Neighbour: Q_ASSERT(false);
00415         }
00416         return c;
00417     }
00418 
00422     static uint distance(const Coord &c1, const Coord &c2) {
00423         return qAbs(c1.first - c2.first) + qAbs(c1.second - c2.second)
00424             + (c1.first==c2.first || c1.second==c2.second ? 0 : -1);
00425     }
00426 };
00427 
00437 template <class Type>
00438 class Hexagonal : public Generic<Type>, public HexagonalBase
00439 {
00440  public:
00444     Hexagonal(uint width = 0, uint height = 0)
00445         : Generic<Type>(width, height) {}
00446 
00453     CoordList neighbours(const Coord &c, bool insideOnly = true) const {
00454         CoordList neighbours;
00455         for (uint i=0; i<Nb_Neighbour; i++) {
00456             Coord n = neighbour(c, (Neighbour)i);
00457             if ( insideOnly && !Generic<Type>::inside(n) ) continue;
00458             neighbours.append(n);
00459         }
00460         return neighbours;
00461     }
00462 
00463 
00472     CoordList neighbours(const Coord &c, uint distance, bool all,
00473                         bool insideOnly = true) const {
00474         // brute force algorithm -- you're welcome to make it more efficient :)
00475         CoordList ring;
00476         if ( distance==0 ) return ring;
00477         ring = neighbours(c, insideOnly);
00478         if ( distance==1 ) return ring;
00479         CoordList center;
00480         center.append(c);
00481         for (uint i=1; i<distance; i++) {
00482             CoordList newRing;
00483             CoordList::const_iterator it;
00484             for (it=ring.begin(); it!=ring.end(); ++it) {
00485                 CoordList n = neighbours(*it, insideOnly);
00486                 CoordList::const_iterator it2;
00487                 for (it2=n.begin(); it2!=n.end(); ++it2)
00488                     if ( center.indexOf(*it2)==-1
00489                          && ring.indexOf(*it2)==-1
00490                          && newRing.indexOf(*it2)==-1 )
00491                         newRing.append(*it2);
00492                 center.append(*it);
00493             }
00494             ring = newRing;
00495         }
00496         if ( !all ) return ring;
00497         CoordList::const_iterator it;
00498         for (it=ring.begin(); it!=ring.end(); ++it)
00499             center.append(*it);
00500         center.removeAll(c);
00501         return center;
00502     }
00503 };
00504 
00505 } // namespace
00506 
00507 #endif

libkdegames

Skip menu "libkdegames"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • kblackbox
  • kgoldrunner
  • kmahjongg
  • ksquares
  • libkdegames
  •   highscore
  •   kgame
  •   kggzgames
  •   kggzmod
  •   kggznet
  • libkmahjongg
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal