• Skip to content
  • Skip to link menu
KDE 4.2 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 {
00092 template <class Type>
00093 class Generic
00094 {
00095  public:
00099     Generic(uint width = 0, uint height = 0) {
00100         resize(width, height);
00101     }
00102 
00103     virtual ~Generic() {}
00104 
00108     void resize(uint width, uint height) {
00109         _width = width;
00110         _height = height;
00111         _vector.resize(width*height);
00112     }
00113 
00117     void fill(const Type &value) {
00118         for (int i=0; i<_vector.count(); i++) _vector[i] = value;
00119     }
00120 
00124     uint width() const  { return _width; }
00128     uint height() const { return _height; }
00132     uint size() const   { return _width*_height; }
00133 
00137     uint index(const Coord &c) const {
00138         return c.first + c.second*_width;
00139     }
00140 
00144     Coord coord(uint index) const {
00145         return Coord(index % _width, index / _width);
00146     }
00147 
00151     const Type &at(const Coord &c) const { return _vector[index(c)]; }
00155     Type &at(const Coord &c)             { return _vector[index(c)]; }
00159     const Type &operator [](const Coord &c) const { return _vector[index(c)]; }
00163     Type &operator [](const Coord &c)             { return _vector[index(c)]; }
00164 
00168     const Type &at(uint index) const          { return _vector[index]; }
00172     Type &at(uint index)                      { return _vector[index]; }
00176     const Type &operator [](uint index) const { return _vector[index]; }
00180     Type &operator [](uint index)             { return _vector[index]; }
00181 
00185     bool inside(const Coord &c) const {
00186         return ( c.first>=0 && c.first<(int)_width
00187                  && c.second>=0 && c.second<(int)_height );
00188     }
00189 
00193     void bound(Coord &c) const {
00194         c.first = qMax(qMin(c.first, (int)_width-1), 0);
00195         c.second = qMax(qMin(c.second, (int)_height-1), 0);
00196     }
00197 
00198  protected:
00199     uint               _width, _height;
00200     QVector<Type> _vector;
00201 };
00202 }
00203 
00204 template <class Type>
00205 QDataStream &operator <<(QDataStream &s, const KGrid2D::Generic<Type> &m) {
00206     s << (quint32)m.width() << (quint32)m.height();
00207     for (uint i=0; i<m.size(); i++) s << m[i];
00208     return s;
00209 }
00210 
00211 template <class Type>
00212 QDataStream &operator >>(QDataStream &s, KGrid2D::Generic<Type> &m) {
00213     quint32 w, h;
00214     s >> w >> h;
00215     m.resize(w, h);
00216     for (uint i=0; i<m.size(); i++) s >> m[i];
00217     return s;
00218 }
00219 
00220 
00221 namespace KGrid2D
00222 {
00223 
00224 //-----------------------------------------------------------------------------
00231 class SquareBase
00232 {
00233  public:
00237     enum Neighbour { Left=0, Right, Up, Down, LeftUp, LeftDown,
00238                      RightUp, RightDown, Nb_Neighbour };
00239 
00243     static double angle(Neighbour n) {
00244         switch (n) {
00245         case Left:      return M_PI;
00246         case Right:     return 0;
00247         case Up:        return M_PI_2;
00248         case Down:      return -M_PI_2;
00249         case LeftUp:    return 3.0*M_PI_4;
00250         case LeftDown:  return -3.0*M_PI_4;
00251         case RightUp:   return M_PI_4;
00252         case RightDown: return -M_PI_4;
00253         case Nb_Neighbour: Q_ASSERT(false);
00254         }
00255         return 0;
00256     }
00257 
00261     static Neighbour opposed(Neighbour n) {
00262         switch (n) {
00263         case Left:      return Right;
00264         case Right:     return Left;
00265         case Up:        return Down;
00266         case Down:      return Up;
00267         case LeftUp:    return RightDown;
00268         case LeftDown:  return RightUp;
00269         case RightUp:   return LeftDown;
00270         case RightDown: return LeftUp;
00271         case Nb_Neighbour: Q_ASSERT(false);
00272         }
00273         return Nb_Neighbour;
00274     }
00275 
00280     static bool isDirect(Neighbour n) { return n<LeftUp; }
00281 
00285     static Coord neighbour(const Coord &c, Neighbour n) {
00286         switch (n) {
00287         case Left:      return c + Coord(-1,  0);
00288         case Right:     return c + Coord( 1,  0);
00289         case Up:        return c + Coord( 0, -1);
00290         case Down:      return c + Coord( 0,  1);
00291         case LeftUp:    return c + Coord(-1, -1);
00292         case LeftDown:  return c + Coord(-1,  1);
00293         case RightUp:   return c + Coord( 1, -1);
00294         case RightDown: return c + Coord( 1,  1);
00295         case Nb_Neighbour: Q_ASSERT(false);
00296         }
00297         return c;
00298     }
00299 };
00300 
00307 template <class T>
00308 class Square : public Generic<T>, public SquareBase
00309 {
00310  public:
00314     Square(uint width = 0, uint height = 0)
00315         : Generic<T>(width, height) {}
00316 
00324     CoordList neighbours(const Coord &c, bool insideOnly = true,
00325                          bool directOnly = false) const {
00326         CoordList neighbours;
00327         for (int i=0; i<(directOnly ? LeftUp : Nb_Neighbour); i++) {
00328             Coord n = neighbour(c, (Neighbour)i);
00329             if ( insideOnly && !Generic<T>::inside(n) ) continue;
00330             neighbours.append(n);
00331         }
00332         return neighbours;
00333     }
00334 
00341     Coord toEdge(const Coord &c, Neighbour n) const {
00342         switch (n) {
00343         case Left:      return Coord(0, c.second);
00344         case Right:     return Coord(Generic<T>::width()-1, c.second);
00345         case Up:        return Coord(c.first, 0);
00346         case Down:      return Coord(c.first, Generic<T>::height()-1);
00347         case LeftUp:    return Coord(0, 0);
00348         case LeftDown:  return Coord(0, Generic<T>::height()-1);
00349         case RightUp:   return Coord(Generic<T>::width()-1, 0);
00350         case RightDown: return Coord(Generic<T>::width()-1, Generic<T>::height()-1);
00351         case Nb_Neighbour: Q_ASSERT(false);
00352         }
00353         return c;
00354     }
00355 };
00356 
00357 //-----------------------------------------------------------------------------
00369 class HexagonalBase
00370 {
00371  public:
00375     enum Neighbour { Left = 0, Right, LeftUp, LeftDown,
00376                      RightUp, RightDown, Nb_Neighbour };
00377 
00381     static double angle(Neighbour n) {
00382         switch (n) {
00383         case Left:      return M_PI;
00384         case Right:     return 0;
00385         case LeftUp:    return 2.0*M_PI/3;
00386         case LeftDown:  return -2.0*M_PI/3;
00387         case RightUp:   return M_PI/3;
00388         case RightDown: return -M_PI/3;
00389         case Nb_Neighbour: Q_ASSERT(false);
00390         }
00391         return 0;
00392     }
00393 
00397     static Neighbour opposed(Neighbour n) {
00398         switch (n) {
00399         case Left:      return Right;
00400         case Right:     return Left;
00401         case LeftUp:    return RightDown;
00402         case LeftDown:  return RightUp;
00403         case RightUp:   return LeftDown;
00404         case RightDown: return LeftUp;
00405         case Nb_Neighbour: Q_ASSERT(false);
00406         }
00407         return Nb_Neighbour;
00408     }
00409 
00413     static Coord neighbour(const Coord &c, Neighbour n) {
00414         bool oddRow = c.second%2;
00415         switch (n) {
00416         case Left:      return c + Coord(-1,  0);
00417         case Right:     return c + Coord( 1,  0);
00418         case LeftUp:    return c + (oddRow ? Coord( 0, -1) : Coord(-1, -1));
00419         case LeftDown:  return c + (oddRow ? Coord( 0,  1) : Coord(-1,  1));
00420         case RightUp:   return c + (oddRow ? Coord( 1, -1) : Coord( 0, -1));
00421         case RightDown: return c + (oddRow ? Coord( 1,  1) : Coord( 0,  1));
00422         case Nb_Neighbour: Q_ASSERT(false);
00423         }
00424         return c;
00425     }
00426 
00430     static uint distance(const Coord &c1, const Coord &c2) {
00431         return qAbs(c1.first - c2.first) + qAbs(c1.second - c2.second)
00432             + (c1.first==c2.first || c1.second==c2.second ? 0 : -1);
00433     }
00434 };
00435 
00447 template <class Type>
00448 class Hexagonal : public Generic<Type>, public HexagonalBase
00449 {
00450  public:
00454     Hexagonal(uint width = 0, uint height = 0)
00455         : Generic<Type>(width, height) {}
00456 
00463     CoordList neighbours(const Coord &c, bool insideOnly = true) const {
00464         CoordList neighbours;
00465         for (uint i=0; i<Nb_Neighbour; i++) {
00466             Coord n = neighbour(c, (Neighbour)i);
00467             if ( insideOnly && !Generic<Type>::inside(n) ) continue;
00468             neighbours.append(n);
00469         }
00470         return neighbours;
00471     }
00472 
00473 
00482     CoordList neighbours(const Coord &c, uint distance, bool all,
00483                         bool insideOnly = true) const {
00484         // brute force algorithm -- you're welcome to make it more efficient :)
00485         CoordList ring;
00486         if ( distance==0 ) return ring;
00487         ring = neighbours(c, insideOnly);
00488         if ( distance==1 ) return ring;
00489         CoordList center;
00490         center.append(c);
00491         for (uint i=1; i<distance; i++) {
00492             CoordList newRing;
00493             CoordList::const_iterator it;
00494             for (it=ring.begin(); it!=ring.end(); ++it) {
00495                 CoordList n = neighbours(*it, insideOnly);
00496                 CoordList::const_iterator it2;
00497                 for (it2=n.begin(); it2!=n.end(); ++it2)
00498                     if ( center.indexOf(*it2)==-1
00499                          && ring.indexOf(*it2)==-1
00500                          && newRing.indexOf(*it2)==-1 )
00501                         newRing.append(*it2);
00502                 center.append(*it);
00503             }
00504             ring = newRing;
00505         }
00506         if ( !all ) return ring;
00507         CoordList::const_iterator it;
00508         for (it=ring.begin(); it!=ring.end(); ++it)
00509             center.append(*it);
00510         center.removeAll(c);
00511         return center;
00512     }
00513 };
00514 
00515 } // namespace
00516 
00517 #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