Reputation: 2918
I have an an associative array which I have sorted in ascending order and now I want to make some decisions on those values. I can't understand how should I proceed.
Let me explain what I want to achieve:
Suppose: I have the following raw array:
Array
(
[0] => Array
(
[cell] => b2
[sign] => ✘
)
[1] => Array
(
[cell] => a1
[sign] => ◯
)
)
which then I sorted it as:
Array
(
[0] => Array
(
[cell] => a1
[sign] => ◯
)
[1] => Array
(
[cell] => b2
[sign] => ✘
)
)
Now I want to make decisions such as whether the values of cells a1 = b1 = c1
or a1 = b2 = c3
etc. Now how can I do that?
Upvotes: 2
Views: 142
Reputation: 410
Here is a more generalized implementation in Javascript. It is only tested on 2x2 and 3x3 game states, may need debugging for other game sizes:
// xxx
// oo-
// o--
alert("game a: " + WhoIsWinningGeneratePaths('xxxoo-o--'));
// x-x
// oo-
// o--
alert("game b: " + WhoIsWinningGeneratePaths('x-xoo-o--'));
// x-x
// ooo
// ---
alert("game c: " + WhoIsWinningGeneratePaths('x-xooo---'));
// x-
// oo
alert("game d: " + WhoIsWinningGeneratePaths('x-oo'));
// x-
// ox
alert("game e: " + WhoIsWinningGeneratePaths('x-ox'));
// x-
// o-
alert("game f: " + WhoIsWinningGeneratePaths('x-o-'));
function WhoIsWinningGeneratePaths(state) {
var n = Math.sqrt(state.length);
var rows = IsWin(state, GenPaths(n, 0, 1, n, n));
var cols = IsWin(state, GenPaths(n, 0, n, 1, n));
var diUp = IsWin(state, GenPaths(1, n-1, n-1, 0, n));
var diDn = IsWin(state, GenPaths(1, 0, n+1, 0, n));
if (rows !== '-') return rows;
if (cols !== '-') return cols;
if (diUp !== '-') return diUp;
return diDn;
}
function GenPaths(count, start, incrementA, incrementB, lengthToWin) {
var paths = [];
for (var i = 0; i < count; i++) {
var path = [];
for (var j = 0; j < lengthToWin; j++) {
path.push(start + i * incrementB + j * incrementA)
}
paths.push(path);
}
return paths;
}
function IsWin(state, paths) {
for (var i = 0; i < paths.length; i++) {
var currentPathResult = IsPathWin(state, paths[i]);
if (currentPathResult != '-')
return currentPathResult;
}
return '-';
}
function IsPathWin(state, path) {
var first = state[path[0]];
for (var j = 1; j < path.length; j++)
{
var compareToFirst = state[path[j]];
if (compareToFirst !== first)
return '-';
}
return first;
}
Upvotes: 1
Reputation: 410
I suggest referring to the positions of cells by a zero-based index. It makes it easy to use math tricks, like modulo or integer division to select rows or columns. Otherwise, you have to use a ton of offsets to avoid off-by-one errors.
IE, the board could be labeled:
0 1 2
3 4 5
6 7 8
The game state can be represented with a character array, with character '-' meaning empty, and x and o meaning x and o played there.
Here is a human game view, and the game stored in a string array:
x
o x o
o x
var state = "-x-oxoox-";
To check if a game has been won, lets make a function.
the function returns '-' if no one won, 'x' if x won, and 'o' if o won.
I am going to start you off with a implementation that hard codes every path to check. Then I show how to generate the paths to check.
function WhoIsWinningHardCode(state) {
var rows = IsWin(state, [[0,1,2],[3,4,5],[6,7,8]]);
var cols = IsWin(state, [[0,3,6],[1,4,7],[2,5,8]]);
var diagUp = IsWin(state, [[6,4,2]]);
var diagDown = IsWin(state, [[0,4,8]]);
if (rows !== '-') return rows;
if (cols !== '-') return cols;
if (diagUp !== '-') return diagUp;
return diagDown;
}
function WhoIsWinningGeneratePaths(state) {
var rows = IsWin(state, GenPaths(3, 0, 1, 3));
var cols = IsWin(state, GenPaths(3, 0, 3, 1));
var diagUp = IsWin(state, GenPaths(1, 2, 2, 0));
var diagDown = IsWin(state, GenPaths(1, 0, 4, 0));
if (rows !== '-') return rows;
if (cols !== '-') return cols;
if (diagUp !== '-') return diagUp;
return diagDown;
}
function GenPaths(count, start, incrementA, incrementB) {
var paths = [];
for (var i = 0; i < count; i++) {
var path = [];
for (var j = 0; j < 3; j++) {
path.push(start + i*incrementB + j*incrementA)
}
paths.push(path);
}
return paths;
}
function IsWin(state, paths) {
for (var i = 0; i < paths.length; i++) {
var path = paths[i];
var a = state[path[0]];
var b = state[path[1]];
var c = state[path[2]];
if (a !== '-')
if (a == b)
if (a == c)
return a;
}
return '-';
}
Upvotes: 1
Reputation: 2940
Guessing that your square is only 3x3, I would say the most simplest way would be to store the winning matches inside an array and just compare them by using array_intersect()
which combines two arrays and returns the duplicated values in an array. To get the number of duplicates, just wrap the count()
function and compare if player one or two's values have matched the $winArr
. Obviously there's still work to do by stopping duplicate values for your input array, Looping your foreach()
after each input etc... but at least your logic will be correct.
$winner; //Winner --> Used when game finished
$winArr = [
['c1','c2','c3'],
['b1','b2','b3'], // --> Vertical Win
['a1','a2','a3'],
['a1','b2','c3'],
['c1','b2','c3'], // --> Diagonal Win
['a1','b1','c1'],
['a2','b2','c2'], // --> Horizontal Win
['a3','b3','c3'],
];
$gameArr = [ // --> `Input Values Array = Dimension for P1 & P2 for ease
'playerOne' => ['a1', 'b1', 'c2', 'c1'],
'playerTwo' => ['a3', 'b3', 'a2'],
];
foreach ($winArr as $k=>$v) {
if (count(array_intersect($v, $gameArr['playerOne'])) === 3) {
$winner = 'Player One!';
break;
} elseif(count(array_intersect($v, $gameArr['playerTwo'])) === 3) {
$winner = 'Player Two!';
break;
}
}
if (isset($winner)) {
echo $winner;
}
Output:
Player One!
See: http://www.php.net/manual/en/function.array-intersect.php
Upvotes: 1