Completed an AI implementation
[GoMoku3D.git] / src / core / GameMatrix.cpp
blob50bee2d7ec93ee485501548ab49f38a2c6f0ed90
1 /********************************************************************
3 * Copyright (C) 2008 Daniele Battaglia
5 * This file is part of GoMoku3D.
7 * GoMoku3D is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * GoMoku3D is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with GoMoku3D. If not, see <http://www.gnu.org/licenses/>.
20 *******************************************************************/
22 #include <QtGlobal>
23 #include "GameMatrix.h"
25 const int GameMatrix::EmptyPoint = -1;
27 GameMatrix *GameMatrix::_instance = 0;
29 GameMatrix::GameMatrix(int d1, int d2, int numPlayers)
31 _d1 = d1;
32 _d2 = d2;
34 for (int i = 0; i < numPlayers; i++) {
35 _lastRound.append(Point());
38 int matrixSize = (d1 * d2) * (d1 * d2) * (d1 * d2);
39 _matrix = new int[matrixSize];
40 for (int i = 0; i < matrixSize; i++) {
41 _matrix[i] = EmptyPoint;
44 _freeCounter = matrixSize;
47 GameMatrix::~GameMatrix()
49 _instance = 0;
50 delete _matrix;
53 GameMatrix *GameMatrix::create(int d1, int d2, int numPlayers)
55 if (_instance == 0) {
56 _instance = new GameMatrix(d1, d2, numPlayers);
58 return _instance;
61 void GameMatrix::destroy()
63 if (_instance != 0) {
64 delete _instance;
65 _instance = 0;
67 return;
70 GameMatrix *GameMatrix::instance()
72 return _instance;
75 bool GameMatrix::check(Point point)
77 return point.isValid() && instance()->elementAt(point) == EmptyPoint;
80 bool GameMatrix::add(Move move)
82 int pos = move.point().x() * (_d1 * _d2) * (_d1 * _d2) + move.point().y() * (_d1 * _d2) + move.point().z();
83 _matrix[pos] = move.playerId();
85 int start = qMax(0, move.point().x());
86 int i = 0;
87 bool valid = true;
89 while (valid && start <= move.point().x()) {
90 while (valid && i < _d1) {
91 int id = elementAt(start + i, move.point().y(), move.point().z());
92 if (id == move.playerId()) {
93 i++;
95 else {
96 if (id == -2) {
97 valid = false;
99 else {
100 start++;
101 i = 0;
105 if (i == _d1) {
106 return true;
110 start = qMax(0, move.point().y());
111 i = 0;
112 valid = true;
114 while (valid && start <= move.point().y()) {
115 while (valid && i < _d1) {
116 int id = elementAt(move.point().x(), start + i, move.point().z());
117 if (id == move.playerId()) {
118 i++;
120 else {
121 if (id == -2) {
122 valid = false;
124 else {
125 start++;
126 i = 0;
130 if (i == _d1) {
131 return true;
135 start = qMax(0, move.point().z());
136 i = 0;
137 valid = true;
139 while (valid && start <= move.point().z()) {
140 while (valid && i < _d1) {
141 int id = elementAt(move.point().x(), move.point().y(), start + i);
142 if (id == move.playerId()) {
143 i++;
145 else {
146 if (id == -2) {
147 valid = false;
149 else {
150 start++;
151 i = 0;
155 if (i == _d1) {
156 return true;
160 if (_d2 != 3) {
161 return false;
164 QSet<Point> set;
165 extractCC(move.point(), move.playerId(), set);
167 Point e;
168 int minX = _d1 * _d2;
169 int maxX = -1;
170 int minY = minX;
171 int maxY = maxX;
172 int minZ = minX;
173 int maxZ = maxX;
175 foreach (e, set) {
176 minX = qMin(minX, e.x());
177 minY = qMin(minY, e.y());
178 minZ = qMin(minZ, e.z());
179 maxX = qMax(maxX, e.x());
180 maxY = qMax(maxY, e.y());
181 maxZ = qMax(maxZ, e.z());
183 return (minX == 0 && maxX == _d1 * _d2 -1) || (minY == 0 && maxY == _d1 * _d2 -1) || (minZ == 0 && maxZ == _d1 * _d2 -1);
186 void GameMatrix::clear(Point point)
188 if (elementAt(point) != EmptyPoint) {
189 _freeCounter++;
190 int pos = point.x() * (_d1 * _d2) * (_d1 * _d2) + point.y() * (_d1 * _d2) + point.z();
191 _matrix[pos] = EmptyPoint;
193 return;
196 int GameMatrix::elementAt(int x, int y, int z) const
198 if (Point(x, y, z).isValid()) {
199 int pos = x * (_d1 * _d2) * (_d1 * _d2) + y * (_d1 * _d2) + z;
200 return _matrix[pos];
202 return -2;
205 int GameMatrix::elementAt(Point point) const
207 return elementAt(point.x(), point.y(), point.z());
210 bool GameMatrix::isFull() const
212 return _freeCounter == 0;
215 int GameMatrix::numberOfPlayers() const
217 return _lastRound.size();
220 void GameMatrix::setLastRound(QList<Point> round)
222 _lastRound = round;
223 return;
226 void GameMatrix::extractCC(Point p, int id, QSet<Point> &set)
228 set.insert(p);
230 QList<Point> adjacent;
231 adjacent.append(Point(p.x() - 1, p.y(), p.z()));
232 adjacent.append(Point(p.x() + 1, p.y(), p.z()));
233 adjacent.append(Point(p.x(), p.y() - 1, p.z()));
234 adjacent.append(Point(p.x(), p.y() + 1, p.z()));
235 adjacent.append(Point(p.x(), p.y(), p.z() - 1));
236 adjacent.append(Point(p.x(), p.y(), p.z() + 1));
238 Point e;
240 foreach (e, adjacent) {
241 if (id == elementAt(e) && set.find(e) == set.end()) {
242 extractCC(e, id, set);
245 return;
248 int GameMatrix::d1() const
250 return _d1;
253 int GameMatrix::d2() const
255 return _d2;