I am trying to make a connect 4 program in java and I am stuck on the winner check. I know that I could make a very long list of if and else if's but I think loops would work better. I'm open to any other way of solving this problem but on what I've been looking at makes it seem the best. I have an idea of what to do with the rows and columns but I don't even know where to start with the diagonals. This is what I have so far:
edit:
int p1counter = 0;
int p2counter = 0;
int r = 1;//x
int c = 1;//y
for(r = 1; r <= 6; r++)
{
while(c <= 7)
{
if(grid[r][c].equals("_"))
{
c++;
p1counter = 0; p2counter = 0;
}
else if(grid[r][c].equals("1"))//player 1 counter
{
c++;
p1counter++;
}
else if(grid[r][c].equals("2"))//player 2 counter
{
c++;
p2counter++;
}
}
if(p1counter >= 4)
{
JOptionPane.showMessageDialog(null, "Player 1 is the winner!");
done = true;
}
else if(p2counter >= 4)
{
JOptionPane.showMessageDialog(null, "Player 2 is the winner!");
done = true;
}
return done;
}
In similar situations I have done the following:
Create an array of strings; as many strings as there are rows+columns+diagonals
Traverse the grid in the four possible directions (this does not include every possible diagonal since diagonals must be at least 4 long) and enter a corresponding character in the string: for example 0 (empty), 1, 2
Search the string array for 1111
and 2222
.
By first organizing the data, the comparison can be done with a built in function. Much faster and cleaner.
Here is how it might be done (this is the "slow and careful way"):
class c4check {
public static void main(String[] args) {
char grid[][] = {{'e','e','e','e','a','b','a'},
{'e','a','b','a','b','b','a'},
{'e','b','a','a','b','b','a'},
{'e','a','b','b','a','b','b'},
{'e','b','a','b','b','a','a'},
{'e','a','b','a','b','b','a'}};
int ii, jj, ri, ci, di;
String checkGrid[] = new String[25];
// copy rows:
for(ri = 0; ri < 6; ri++) {
String temp = "";
for(ci = 0; ci < 7; ci++) {
temp += grid[ri][ci];
}
checkGrid[ri] = temp;
}
// copy columns:
for(ci = 0; ci < 7; ci++) {
String temp = "";
for(ri = 0; ri < 6; ri++) {
temp += grid[ri][ci];
}
checkGrid[ci + 6] = temp;
}
// copy first diagonals:
for(di = 0; di < 6; di++) {
String temp = "";
for(ri = 0; ri < 6; ri++) {
ci = di - 2;
ri = 0;
while(ci < 0) {
ri++;
ci++;
}
for(; ri < 6; ri++, ci++) {
if( ci > 6 ) continue;
temp += grid[ri][ci];
}
}
checkGrid[di+13] = temp;
}
// diagonals in the other direction:
for(di = 0; di < 6; di++) {
String temp = "";
for(ri = 0; ri < 6; ri++) {
ci = 8 - di;
ri = 0;
while(ci > 6) {
ri++;
ci--;
}
for(; ri < 6; ri++, ci--) {
if( ci < 0 ) continue;
temp += grid[ri][ci];
}
}
checkGrid[di+19] = temp;
}
for(ii = 0; ii < 25; ii++) {
System.out.println("Checking '" + checkGrid[ii] + "'");
if (checkGrid[ii].contains("aaaa")) System.out.println("Player A wins!");
if (checkGrid[ii].contains("bbbb")) System.out.println("Player B wins!");
}
}
}
Obviously, instead of copying temp
to an array element, and then checking at the end, you could check for "aaaa"
or "bbbb"
each time, and return from the function as soon as you found a match.
Output of this particular code (which has more than one "winning" combination, so it's not a "real" situation - but it allowed me to check that all the diagonals were visited correctly):
Checking 'eeeeaba'
Checking 'eababba'
Checking 'ebaabba'
Checking 'eabbabb'
Checking 'ebabbaa'
Checking 'eababba'
Checking 'eeeeee'
Checking 'eababa'
Checking 'ebabab'
Checking 'eaabba'
Checking 'abbabb'
Checking 'bbbbab'
Player B wins!
Checking 'aaabaa'
Checking 'eaaa'
Checking 'ebbbb'
Player B wins!
Checking 'eaabbb'
Checking 'ebaaaa'
Player A wins!
Checking 'eabba'
Checking 'ebbb'
Checking 'abba'
Checking 'ababb'
Checking 'abbbaa'
Checking 'bbabbe'
Checking 'aaaae'
Player A wins!
Checking 'ebbe'