Question

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;
        }
Was it helpful?

Solution

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'

OTHER TIPS

Here is way to maintain the track of winner :-

  1. maintain 4 types of sets (horizontal,vertical,two diagonal).
  2. whenever a point on grid is colored check with corresponding neighbour in the same type eg. if grid point (x,y) is colored then for horizontal type we check (x,y+1) and (x,y-1).
  3. find union of two similar colored neighbour.
  4. If size of any set is equal to four then you have found the winner. You can check while updating neighbours of point currently colored.

Suggestions: Use Union-Find datastructure to achieve good time complexity (Note as your sets are small you can do without it as well).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top