Skip to content

Commit 298edf9

Browse files
committed
Checks to see whether or not anyone has won the game. Generalizes to any size/dimension.
1 parent 3110edc commit 298edf9

1 file changed

Lines changed: 112 additions & 1 deletion

File tree

js/4dtictactoe.js

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ var TicTacToe4D = (function() {
1414
var plankThickness = 0.04; //how thick the barrier planks are
1515
var pieceColors = [0xFF0000, 0x0000FF];
1616
var D = 3; //number of dimensions
17-
var S = 3; //side length
17+
var S = 4; //side length
1818
var canvSel = '#canvas';
1919

2020
/*************
@@ -79,6 +79,13 @@ var TicTacToe4D = (function() {
7979
parseInt($s('#z').value),
8080
parseInt($s('#x').value)
8181
]); //axes are in this order for weird reasons...
82+
83+
var possWinner = thereIsALine();
84+
if (possWinner !== -1) {
85+
setTimeout(function() {
86+
alert('Player '+(possWinner+1)+' wins!');
87+
}, 10);
88+
}
8289
});
8390

8491
//initial rendering
@@ -95,6 +102,103 @@ var TicTacToe4D = (function() {
95102

96103
/********************
97104
* helper functions */
105+
function thereIsALine(dimsIn, dimsOut) {
106+
if (arguments.length === 0) {
107+
dimsIn = [];
108+
for (var di = 0; di < D; di++) dimsIn.push(di);
109+
dimsOut = {};
110+
}
111+
if (dimsIn.length === 1) { //then just check that dim
112+
var dc = [];
113+
dc[dimsIn[0]] = 0;
114+
for (var dim in dimsOut) {
115+
dc[dim] = dimsOut[dim];
116+
}
117+
var lineOwner = accessArr(gameState, dc);
118+
if (lineOwner === -1) return -1;
119+
else {
120+
for (var si = 1; si < S; si++) {
121+
dc[dimsIn[0]] = si;
122+
if (lineOwner !== accessArr(gameState, dc)) return -1;
123+
}
124+
return lineOwner;
125+
}
126+
} else {
127+
function getBinVectorsUpTo(n, bits, scale) {
128+
scale = scale || 0;
129+
var ret = [];
130+
for (var ai = 0; ai < n; ai++) {
131+
var bin = ai.toString(2);
132+
var vect = [];
133+
for (var bi = 0; bi < bits-bin.length; bi++) {
134+
vect.push(0);
135+
}
136+
for (var bi = 0; bi < bin.length; bi++) {
137+
vect.push(scale*parseInt(bin.charAt(bi)));
138+
}
139+
ret.push(vect);
140+
}
141+
return ret;
142+
}
143+
144+
//check the long diagonals of this space
145+
var corners = getBinVectorsUpTo(
146+
Math.pow(2, dimsIn.length-1), //# pairs of corners
147+
dimsIn.length, S-1
148+
);
149+
var cornerVels = [];
150+
for (var ci = 0; ci < corners.length; ci++) {
151+
var vel = [];
152+
for (var vi = 0; vi < corners[ci].length; vi++) {
153+
vel.push(1 - 2*corners[ci][vi]/(S-1));
154+
}
155+
cornerVels.push(vel);
156+
}
157+
var baseCoords = [];
158+
for (var dim in dimsOut) baseCoords[dim] = dimsOut[dim];
159+
for (var ci = 0; ci < corners.length; ci++) {
160+
var dc = baseCoords.slice(0); //starting cell
161+
for (var ii = 0; ii < dimsIn.length; ii++) {
162+
dc[dimsIn[ii]] = corners[ci][ii];
163+
}
164+
var lineOwner = accessArr(gameState, dc);
165+
if (lineOwner !== -1) {
166+
var everythingMatchedUp = true;
167+
for (var si = 1; si < S; si++) {
168+
for (var ii = 0; ii < dimsIn.length; ii++) {
169+
dc[dimsIn[ii]] += cornerVels[ci][ii];
170+
}
171+
if (lineOwner !== accessArr(gameState, dc)) {
172+
everythingMatchedUp = false;
173+
break;
174+
}
175+
}
176+
if (everythingMatchedUp) return lineOwner;
177+
}
178+
}
179+
180+
//remove a dimension and check the smaller dimensional space
181+
var foundALine = false;
182+
for (var ii = 0; ii < dimsIn.length; ii++) {
183+
var dmi = []; //dimsIn without ii
184+
for (var ai = 0; ai < dimsIn.length; ai++) {
185+
if (ai !== ii) dmi.push(dimsIn[ai]);
186+
}
187+
var dmo = {}; //dimsOut with ii
188+
for (var dim in dimsOut) {
189+
dmo[dim] = dimsOut[dim];
190+
}
191+
for (var si = 0; si < S; si++) {
192+
dmo[dimsIn[ii]] = si;
193+
foundALine = thereIsALine(dmi, dmo);
194+
if (foundALine !== -1) break;
195+
}
196+
if (foundALine !== -1) break;
197+
}
198+
return foundALine;
199+
}
200+
}
201+
98202
function makeMove(coords) {
99203
//spot not already taken
100204
if (
@@ -193,13 +297,20 @@ var TicTacToe4D = (function() {
193297
return Math.floor(low + Math.random()*(high-low));
194298
}
195299

300+
function accessArr(arr, loc, idx) {
301+
idx = idx || 0;
302+
if (idx === loc.length-1) return arr[loc[idx]];
303+
else return accessArr(arr[loc[idx]], loc, idx+1);
304+
}
305+
196306
function round(n, places) {
197307
var mult = Math.pow(10, places);
198308
return Math.round(mult*n)/mult;
199309
}
200310

201311
return {
202312
init: init4DTicTacToe,
313+
thereIsALine: thereIsALine,
203314
gameState: gameState
204315
};
205316
})();

0 commit comments

Comments
 (0)