1

I'm writing some Java code to implement the Connect 4 game. A winner is declared when a player places four chips in a row, either horizontally, vertically or diagonally. Obviously I could write some for loops and check for a winner each time but would like some advice on doing it more elegantly. I was thinking about adding all winning combinations to some data structure and just checking the combinations the last move made is involved in but I'm not sure if that is possible or how to implement it. I am new to Java so any tips or advice on what data structure to use or how to implement would be much appreciated. Thanks

Edit: Ok, could someone please advise me on where to start to implement the guys answer here: algorithm to check a connect four field

Community
  • 1
  • 1
PhilipGough
  • 1,709
  • 1
  • 13
  • 18
  • 1
    Looping *is* elegant. – Darkhogg Nov 25 '13 at 19:12
  • I would like not to check the whole board each time though – PhilipGough Nov 25 '13 at 19:13
  • 1
    Why not? It's not like you were checking it 1000 times a second. – Darkhogg Nov 25 '13 at 19:14
  • 1
    Check out this: http://stackoverflow.com/q/7033165 – Ahmet Kakıcı Nov 25 '13 at 19:15
  • 1
    Yep thanks Ahmet I had looked at that and it is the answer that I was interested in trying to do, however I dont know where to start with it – PhilipGough Nov 25 '13 at 19:18
  • possible duplicate of [algorithm to check a connect four field](http://stackoverflow.com/questions/7033165/algorithm-to-check-a-connect-four-field) – Luc M Nov 25 '13 at 19:19
  • @Darkhogg imagine you want to implement some sort of AI which uses tree searches and has to check for a win in every node. You'll probably end up with much more than 1000 checks per second. When efficiency is more important than readability/simplicity, I would strongly recommend the bitboard variant mentioned above. – Gerrit-K Jul 22 '14 at 08:15

5 Answers5

5

No matter what, in order to check for victory condition, you'll need to do some sort of looping or recursion on the whole board. As long as your loop stops checking in any direction as soon as it stops being a winning condition (e.g. if you check left to right and after 2 iterations you find a different color) then it should be fine.

A way of optimizing this would be to only check for victory conditions when new moves are played, then you only need to check those around that move and not the whole board. If you need to check a complete board and not turn-by-turn then a further step would be to keep a list of moves played and do your checking from the first move forward, then you can stop as soon as the winning move was played.

Ross Drew
  • 8,163
  • 2
  • 41
  • 53
  • I am doing the same thing with loops and checks to terminate them if the piece streak is interrupted, but your optimization sounds rather interesting, how would it be implemented, especially if each player puts their pieces at opposite ends of the board? – Ungeheuer Jun 10 '15 at 22:28
  • Connect 4 is turn based, if player one is yellow and drops a token then you just check around that token for a win. Player 2 puts in his red, you check around that for a win. Simple. – Ross Drew Jun 11 '15 at 13:24
  • No need to loop across the board. Just check the last inserted coin :-) – Gianluca Ghettini Sep 13 '15 at 16:46
  • 1
    That's what the second paragraph says. – Ross Drew Sep 14 '15 at 08:04
5

Other answers claim you can't check for a win without looping. Today I will play the Devil's advocate: you can do it (although you still shouldn't do it)! For a typical 7*6 Connnect Four board, there are only 69 possible winning positions per color, which can easily be coded in an afternoon or two, even if you're a slow typist.

This code supposes that you have a 7x6 2D array of characters called matrix, which contains one of the three values 'B', 'R', or ' ', corresponding to a black, red, or empty tile respectively. It either returns the character of the winner, or null if there is no winner yet.

char getWinner(){
    if (matrix[0][0] == 'B' and  matrix[1][0] == 'B' and  matrix[2][0] == 'B' and  matrix[3][0] == 'B'){return 'B';}
    if (matrix[0][0] == 'R' and  matrix[1][0] == 'R' and  matrix[2][0] == 'R' and  matrix[3][0] == 'R'){return 'R';}
    if (matrix[1][0] == 'B' and  matrix[2][0] == 'B' and  matrix[3][0] == 'B' and  matrix[4][0] == 'B'){return 'B';}
    if (matrix[1][0] == 'R' and  matrix[2][0] == 'R' and  matrix[3][0] == 'R' and  matrix[4][0] == 'R'){return 'R';}
    if (matrix[2][0] == 'B' and  matrix[3][0] == 'B' and  matrix[4][0] == 'B' and  matrix[5][0] == 'B'){return 'B';}
    if (matrix[2][0] == 'R' and  matrix[3][0] == 'R' and  matrix[4][0] == 'R' and  matrix[5][0] == 'R'){return 'R';}
    if (matrix[3][0] == 'B' and  matrix[4][0] == 'B' and  matrix[5][0] == 'B' and  matrix[6][0] == 'B'){return 'B';}
    if (matrix[3][0] == 'R' and  matrix[4][0] == 'R' and  matrix[5][0] == 'R' and  matrix[6][0] == 'R'){return 'R';}
    if (matrix[0][1] == 'B' and  matrix[1][1] == 'B' and  matrix[2][1] == 'B' and  matrix[3][1] == 'B'){return 'B';}
    if (matrix[0][1] == 'R' and  matrix[1][1] == 'R' and  matrix[2][1] == 'R' and  matrix[3][1] == 'R'){return 'R';}
    if (matrix[1][1] == 'B' and  matrix[2][1] == 'B' and  matrix[3][1] == 'B' and  matrix[4][1] == 'B'){return 'B';}
    if (matrix[1][1] == 'R' and  matrix[2][1] == 'R' and  matrix[3][1] == 'R' and  matrix[4][1] == 'R'){return 'R';}
    if (matrix[2][1] == 'B' and  matrix[3][1] == 'B' and  matrix[4][1] == 'B' and  matrix[5][1] == 'B'){return 'B';}
    if (matrix[2][1] == 'R' and  matrix[3][1] == 'R' and  matrix[4][1] == 'R' and  matrix[5][1] == 'R'){return 'R';}
    if (matrix[3][1] == 'B' and  matrix[4][1] == 'B' and  matrix[5][1] == 'B' and  matrix[6][1] == 'B'){return 'B';}
    if (matrix[3][1] == 'R' and  matrix[4][1] == 'R' and  matrix[5][1] == 'R' and  matrix[6][1] == 'R'){return 'R';}
    if (matrix[0][2] == 'B' and  matrix[1][2] == 'B' and  matrix[2][2] == 'B' and  matrix[3][2] == 'B'){return 'B';}
    if (matrix[0][2] == 'R' and  matrix[1][2] == 'R' and  matrix[2][2] == 'R' and  matrix[3][2] == 'R'){return 'R';}
    if (matrix[1][2] == 'B' and  matrix[2][2] == 'B' and  matrix[3][2] == 'B' and  matrix[4][2] == 'B'){return 'B';}
    if (matrix[1][2] == 'R' and  matrix[2][2] == 'R' and  matrix[3][2] == 'R' and  matrix[4][2] == 'R'){return 'R';}
    if (matrix[2][2] == 'B' and  matrix[3][2] == 'B' and  matrix[4][2] == 'B' and  matrix[5][2] == 'B'){return 'B';}
    if (matrix[2][2] == 'R' and  matrix[3][2] == 'R' and  matrix[4][2] == 'R' and  matrix[5][2] == 'R'){return 'R';}
    if (matrix[3][2] == 'B' and  matrix[4][2] == 'B' and  matrix[5][2] == 'B' and  matrix[6][2] == 'B'){return 'B';}
    if (matrix[3][2] == 'R' and  matrix[4][2] == 'R' and  matrix[5][2] == 'R' and  matrix[6][2] == 'R'){return 'R';}
    if (matrix[0][3] == 'B' and  matrix[1][3] == 'B' and  matrix[2][3] == 'B' and  matrix[3][3] == 'B'){return 'B';}
    if (matrix[0][3] == 'R' and  matrix[1][3] == 'R' and  matrix[2][3] == 'R' and  matrix[3][3] == 'R'){return 'R';}
    if (matrix[1][3] == 'B' and  matrix[2][3] == 'B' and  matrix[3][3] == 'B' and  matrix[4][3] == 'B'){return 'B';}
    if (matrix[1][3] == 'R' and  matrix[2][3] == 'R' and  matrix[3][3] == 'R' and  matrix[4][3] == 'R'){return 'R';}
    if (matrix[2][3] == 'B' and  matrix[3][3] == 'B' and  matrix[4][3] == 'B' and  matrix[5][3] == 'B'){return 'B';}
    if (matrix[2][3] == 'R' and  matrix[3][3] == 'R' and  matrix[4][3] == 'R' and  matrix[5][3] == 'R'){return 'R';}
    if (matrix[3][3] == 'B' and  matrix[4][3] == 'B' and  matrix[5][3] == 'B' and  matrix[6][3] == 'B'){return 'B';}
    if (matrix[3][3] == 'R' and  matrix[4][3] == 'R' and  matrix[5][3] == 'R' and  matrix[6][3] == 'R'){return 'R';}
    if (matrix[0][4] == 'B' and  matrix[1][4] == 'B' and  matrix[2][4] == 'B' and  matrix[3][4] == 'B'){return 'B';}
    if (matrix[0][4] == 'R' and  matrix[1][4] == 'R' and  matrix[2][4] == 'R' and  matrix[3][4] == 'R'){return 'R';}
    if (matrix[1][4] == 'B' and  matrix[2][4] == 'B' and  matrix[3][4] == 'B' and  matrix[4][4] == 'B'){return 'B';}
    if (matrix[1][4] == 'R' and  matrix[2][4] == 'R' and  matrix[3][4] == 'R' and  matrix[4][4] == 'R'){return 'R';}
    if (matrix[2][4] == 'B' and  matrix[3][4] == 'B' and  matrix[4][4] == 'B' and  matrix[5][4] == 'B'){return 'B';}
    if (matrix[2][4] == 'R' and  matrix[3][4] == 'R' and  matrix[4][4] == 'R' and  matrix[5][4] == 'R'){return 'R';}
    if (matrix[3][4] == 'B' and  matrix[4][4] == 'B' and  matrix[5][4] == 'B' and  matrix[6][4] == 'B'){return 'B';}
    if (matrix[3][4] == 'R' and  matrix[4][4] == 'R' and  matrix[5][4] == 'R' and  matrix[6][4] == 'R'){return 'R';}
    if (matrix[0][5] == 'B' and  matrix[1][5] == 'B' and  matrix[2][5] == 'B' and  matrix[3][5] == 'B'){return 'B';}
    if (matrix[0][5] == 'R' and  matrix[1][5] == 'R' and  matrix[2][5] == 'R' and  matrix[3][5] == 'R'){return 'R';}
    if (matrix[1][5] == 'B' and  matrix[2][5] == 'B' and  matrix[3][5] == 'B' and  matrix[4][5] == 'B'){return 'B';}
    if (matrix[1][5] == 'R' and  matrix[2][5] == 'R' and  matrix[3][5] == 'R' and  matrix[4][5] == 'R'){return 'R';}
    if (matrix[2][5] == 'B' and  matrix[3][5] == 'B' and  matrix[4][5] == 'B' and  matrix[5][5] == 'B'){return 'B';}
    if (matrix[2][5] == 'R' and  matrix[3][5] == 'R' and  matrix[4][5] == 'R' and  matrix[5][5] == 'R'){return 'R';}
    if (matrix[3][5] == 'B' and  matrix[4][5] == 'B' and  matrix[5][5] == 'B' and  matrix[6][5] == 'B'){return 'B';}
    if (matrix[3][5] == 'R' and  matrix[4][5] == 'R' and  matrix[5][5] == 'R' and  matrix[6][5] == 'R'){return 'R';}
    if (matrix[0][0] == 'B' and  matrix[0][1] == 'B' and  matrix[0][2] == 'B' and  matrix[0][3] == 'B'){return 'B';}
    if (matrix[0][0] == 'R' and  matrix[0][1] == 'R' and  matrix[0][2] == 'R' and  matrix[0][3] == 'R'){return 'R';}
    if (matrix[0][1] == 'B' and  matrix[0][2] == 'B' and  matrix[0][3] == 'B' and  matrix[0][4] == 'B'){return 'B';}
    if (matrix[0][1] == 'R' and  matrix[0][2] == 'R' and  matrix[0][3] == 'R' and  matrix[0][4] == 'R'){return 'R';}
    if (matrix[0][2] == 'B' and  matrix[0][3] == 'B' and  matrix[0][4] == 'B' and  matrix[0][5] == 'B'){return 'B';}
    if (matrix[0][2] == 'R' and  matrix[0][3] == 'R' and  matrix[0][4] == 'R' and  matrix[0][5] == 'R'){return 'R';}
    if (matrix[1][0] == 'B' and  matrix[1][1] == 'B' and  matrix[1][2] == 'B' and  matrix[1][3] == 'B'){return 'B';}
    if (matrix[1][0] == 'R' and  matrix[1][1] == 'R' and  matrix[1][2] == 'R' and  matrix[1][3] == 'R'){return 'R';}
    if (matrix[1][1] == 'B' and  matrix[1][2] == 'B' and  matrix[1][3] == 'B' and  matrix[1][4] == 'B'){return 'B';}
    if (matrix[1][1] == 'R' and  matrix[1][2] == 'R' and  matrix[1][3] == 'R' and  matrix[1][4] == 'R'){return 'R';}
    if (matrix[1][2] == 'B' and  matrix[1][3] == 'B' and  matrix[1][4] == 'B' and  matrix[1][5] == 'B'){return 'B';}
    if (matrix[1][2] == 'R' and  matrix[1][3] == 'R' and  matrix[1][4] == 'R' and  matrix[1][5] == 'R'){return 'R';}
    if (matrix[2][0] == 'B' and  matrix[2][1] == 'B' and  matrix[2][2] == 'B' and  matrix[2][3] == 'B'){return 'B';}
    if (matrix[2][0] == 'R' and  matrix[2][1] == 'R' and  matrix[2][2] == 'R' and  matrix[2][3] == 'R'){return 'R';}
    if (matrix[2][1] == 'B' and  matrix[2][2] == 'B' and  matrix[2][3] == 'B' and  matrix[2][4] == 'B'){return 'B';}
    if (matrix[2][1] == 'R' and  matrix[2][2] == 'R' and  matrix[2][3] == 'R' and  matrix[2][4] == 'R'){return 'R';}
    if (matrix[2][2] == 'B' and  matrix[2][3] == 'B' and  matrix[2][4] == 'B' and  matrix[2][5] == 'B'){return 'B';}
    if (matrix[2][2] == 'R' and  matrix[2][3] == 'R' and  matrix[2][4] == 'R' and  matrix[2][5] == 'R'){return 'R';}
    if (matrix[3][0] == 'B' and  matrix[3][1] == 'B' and  matrix[3][2] == 'B' and  matrix[3][3] == 'B'){return 'B';}
    if (matrix[3][0] == 'R' and  matrix[3][1] == 'R' and  matrix[3][2] == 'R' and  matrix[3][3] == 'R'){return 'R';}
    if (matrix[3][1] == 'B' and  matrix[3][2] == 'B' and  matrix[3][3] == 'B' and  matrix[3][4] == 'B'){return 'B';}
    if (matrix[3][1] == 'R' and  matrix[3][2] == 'R' and  matrix[3][3] == 'R' and  matrix[3][4] == 'R'){return 'R';}
    if (matrix[3][2] == 'B' and  matrix[3][3] == 'B' and  matrix[3][4] == 'B' and  matrix[3][5] == 'B'){return 'B';}
    if (matrix[3][2] == 'R' and  matrix[3][3] == 'R' and  matrix[3][4] == 'R' and  matrix[3][5] == 'R'){return 'R';}
    if (matrix[4][0] == 'B' and  matrix[4][1] == 'B' and  matrix[4][2] == 'B' and  matrix[4][3] == 'B'){return 'B';}
    if (matrix[4][0] == 'R' and  matrix[4][1] == 'R' and  matrix[4][2] == 'R' and  matrix[4][3] == 'R'){return 'R';}
    if (matrix[4][1] == 'B' and  matrix[4][2] == 'B' and  matrix[4][3] == 'B' and  matrix[4][4] == 'B'){return 'B';}
    if (matrix[4][1] == 'R' and  matrix[4][2] == 'R' and  matrix[4][3] == 'R' and  matrix[4][4] == 'R'){return 'R';}
    if (matrix[4][2] == 'B' and  matrix[4][3] == 'B' and  matrix[4][4] == 'B' and  matrix[4][5] == 'B'){return 'B';}
    if (matrix[4][2] == 'R' and  matrix[4][3] == 'R' and  matrix[4][4] == 'R' and  matrix[4][5] == 'R'){return 'R';}
    if (matrix[5][0] == 'B' and  matrix[5][1] == 'B' and  matrix[5][2] == 'B' and  matrix[5][3] == 'B'){return 'B';}
    if (matrix[5][0] == 'R' and  matrix[5][1] == 'R' and  matrix[5][2] == 'R' and  matrix[5][3] == 'R'){return 'R';}
    if (matrix[5][1] == 'B' and  matrix[5][2] == 'B' and  matrix[5][3] == 'B' and  matrix[5][4] == 'B'){return 'B';}
    if (matrix[5][1] == 'R' and  matrix[5][2] == 'R' and  matrix[5][3] == 'R' and  matrix[5][4] == 'R'){return 'R';}
    if (matrix[5][2] == 'B' and  matrix[5][3] == 'B' and  matrix[5][4] == 'B' and  matrix[5][5] == 'B'){return 'B';}
    if (matrix[5][2] == 'R' and  matrix[5][3] == 'R' and  matrix[5][4] == 'R' and  matrix[5][5] == 'R'){return 'R';}
    if (matrix[6][0] == 'B' and  matrix[6][1] == 'B' and  matrix[6][2] == 'B' and  matrix[6][3] == 'B'){return 'B';}
    if (matrix[6][0] == 'R' and  matrix[6][1] == 'R' and  matrix[6][2] == 'R' and  matrix[6][3] == 'R'){return 'R';}
    if (matrix[6][1] == 'B' and  matrix[6][2] == 'B' and  matrix[6][3] == 'B' and  matrix[6][4] == 'B'){return 'B';}
    if (matrix[6][1] == 'R' and  matrix[6][2] == 'R' and  matrix[6][3] == 'R' and  matrix[6][4] == 'R'){return 'R';}
    if (matrix[6][2] == 'B' and  matrix[6][3] == 'B' and  matrix[6][4] == 'B' and  matrix[6][5] == 'B'){return 'B';}
    if (matrix[6][2] == 'R' and  matrix[6][3] == 'R' and  matrix[6][4] == 'R' and  matrix[6][5] == 'R'){return 'R';}
    if (matrix[0][3] == 'B' and  matrix[1][2] == 'B' and  matrix[2][1] == 'B' and  matrix[3][0] == 'B'){return 'B';}
    if (matrix[0][3] == 'R' and  matrix[1][2] == 'R' and  matrix[2][1] == 'R' and  matrix[3][0] == 'R'){return 'R';}
    if (matrix[3][3] == 'B' and  matrix[2][2] == 'B' and  matrix[1][1] == 'B' and  matrix[0][0] == 'B'){return 'B';}
    if (matrix[3][3] == 'R' and  matrix[2][2] == 'R' and  matrix[1][1] == 'R' and  matrix[0][0] == 'R'){return 'R';}
    if (matrix[0][4] == 'B' and  matrix[1][3] == 'B' and  matrix[2][2] == 'B' and  matrix[3][1] == 'B'){return 'B';}
    if (matrix[0][4] == 'R' and  matrix[1][3] == 'R' and  matrix[2][2] == 'R' and  matrix[3][1] == 'R'){return 'R';}
    if (matrix[3][4] == 'B' and  matrix[2][3] == 'B' and  matrix[1][2] == 'B' and  matrix[0][1] == 'B'){return 'B';}
    if (matrix[3][4] == 'R' and  matrix[2][3] == 'R' and  matrix[1][2] == 'R' and  matrix[0][1] == 'R'){return 'R';}
    if (matrix[0][5] == 'B' and  matrix[1][4] == 'B' and  matrix[2][3] == 'B' and  matrix[3][2] == 'B'){return 'B';}
    if (matrix[0][5] == 'R' and  matrix[1][4] == 'R' and  matrix[2][3] == 'R' and  matrix[3][2] == 'R'){return 'R';}
    if (matrix[3][5] == 'B' and  matrix[2][4] == 'B' and  matrix[1][3] == 'B' and  matrix[0][2] == 'B'){return 'B';}
    if (matrix[3][5] == 'R' and  matrix[2][4] == 'R' and  matrix[1][3] == 'R' and  matrix[0][2] == 'R'){return 'R';}
    if (matrix[1][3] == 'B' and  matrix[2][2] == 'B' and  matrix[3][1] == 'B' and  matrix[4][0] == 'B'){return 'B';}
    if (matrix[1][3] == 'R' and  matrix[2][2] == 'R' and  matrix[3][1] == 'R' and  matrix[4][0] == 'R'){return 'R';}
    if (matrix[4][3] == 'B' and  matrix[3][2] == 'B' and  matrix[2][1] == 'B' and  matrix[1][0] == 'B'){return 'B';}
    if (matrix[4][3] == 'R' and  matrix[3][2] == 'R' and  matrix[2][1] == 'R' and  matrix[1][0] == 'R'){return 'R';}
    if (matrix[1][4] == 'B' and  matrix[2][3] == 'B' and  matrix[3][2] == 'B' and  matrix[4][1] == 'B'){return 'B';}
    if (matrix[1][4] == 'R' and  matrix[2][3] == 'R' and  matrix[3][2] == 'R' and  matrix[4][1] == 'R'){return 'R';}
    if (matrix[4][4] == 'B' and  matrix[3][3] == 'B' and  matrix[2][2] == 'B' and  matrix[1][1] == 'B'){return 'B';}
    if (matrix[4][4] == 'R' and  matrix[3][3] == 'R' and  matrix[2][2] == 'R' and  matrix[1][1] == 'R'){return 'R';}
    if (matrix[1][5] == 'B' and  matrix[2][4] == 'B' and  matrix[3][3] == 'B' and  matrix[4][2] == 'B'){return 'B';}
    if (matrix[1][5] == 'R' and  matrix[2][4] == 'R' and  matrix[3][3] == 'R' and  matrix[4][2] == 'R'){return 'R';}
    if (matrix[4][5] == 'B' and  matrix[3][4] == 'B' and  matrix[2][3] == 'B' and  matrix[1][2] == 'B'){return 'B';}
    if (matrix[4][5] == 'R' and  matrix[3][4] == 'R' and  matrix[2][3] == 'R' and  matrix[1][2] == 'R'){return 'R';}
    if (matrix[2][3] == 'B' and  matrix[3][2] == 'B' and  matrix[4][1] == 'B' and  matrix[5][0] == 'B'){return 'B';}
    if (matrix[2][3] == 'R' and  matrix[3][2] == 'R' and  matrix[4][1] == 'R' and  matrix[5][0] == 'R'){return 'R';}
    if (matrix[5][3] == 'B' and  matrix[4][2] == 'B' and  matrix[3][1] == 'B' and  matrix[2][0] == 'B'){return 'B';}
    if (matrix[5][3] == 'R' and  matrix[4][2] == 'R' and  matrix[3][1] == 'R' and  matrix[2][0] == 'R'){return 'R';}
    if (matrix[2][4] == 'B' and  matrix[3][3] == 'B' and  matrix[4][2] == 'B' and  matrix[5][1] == 'B'){return 'B';}
    if (matrix[2][4] == 'R' and  matrix[3][3] == 'R' and  matrix[4][2] == 'R' and  matrix[5][1] == 'R'){return 'R';}
    if (matrix[5][4] == 'B' and  matrix[4][3] == 'B' and  matrix[3][2] == 'B' and  matrix[2][1] == 'B'){return 'B';}
    if (matrix[5][4] == 'R' and  matrix[4][3] == 'R' and  matrix[3][2] == 'R' and  matrix[2][1] == 'R'){return 'R';}
    if (matrix[2][5] == 'B' and  matrix[3][4] == 'B' and  matrix[4][3] == 'B' and  matrix[5][2] == 'B'){return 'B';}
    if (matrix[2][5] == 'R' and  matrix[3][4] == 'R' and  matrix[4][3] == 'R' and  matrix[5][2] == 'R'){return 'R';}
    if (matrix[5][5] == 'B' and  matrix[4][4] == 'B' and  matrix[3][3] == 'B' and  matrix[2][2] == 'B'){return 'B';}
    if (matrix[5][5] == 'R' and  matrix[4][4] == 'R' and  matrix[3][3] == 'R' and  matrix[2][2] == 'R'){return 'R';}
    if (matrix[3][3] == 'B' and  matrix[4][2] == 'B' and  matrix[5][1] == 'B' and  matrix[6][0] == 'B'){return 'B';}
    if (matrix[3][3] == 'R' and  matrix[4][2] == 'R' and  matrix[5][1] == 'R' and  matrix[6][0] == 'R'){return 'R';}
    if (matrix[6][3] == 'B' and  matrix[5][2] == 'B' and  matrix[4][1] == 'B' and  matrix[3][0] == 'B'){return 'B';}
    if (matrix[6][3] == 'R' and  matrix[5][2] == 'R' and  matrix[4][1] == 'R' and  matrix[3][0] == 'R'){return 'R';}
    if (matrix[3][4] == 'B' and  matrix[4][3] == 'B' and  matrix[5][2] == 'B' and  matrix[6][1] == 'B'){return 'B';}
    if (matrix[3][4] == 'R' and  matrix[4][3] == 'R' and  matrix[5][2] == 'R' and  matrix[6][1] == 'R'){return 'R';}
    if (matrix[6][4] == 'B' and  matrix[5][3] == 'B' and  matrix[4][2] == 'B' and  matrix[3][1] == 'B'){return 'B';}
    if (matrix[6][4] == 'R' and  matrix[5][3] == 'R' and  matrix[4][2] == 'R' and  matrix[3][1] == 'R'){return 'R';}
    if (matrix[3][5] == 'B' and  matrix[4][4] == 'B' and  matrix[5][3] == 'B' and  matrix[6][2] == 'B'){return 'B';}
    if (matrix[3][5] == 'R' and  matrix[4][4] == 'R' and  matrix[5][3] == 'R' and  matrix[6][2] == 'R'){return 'R';}
    if (matrix[6][5] == 'B' and  matrix[5][4] == 'B' and  matrix[4][3] == 'B' and  matrix[3][2] == 'B'){return 'B';}
    if (matrix[6][5] == 'R' and  matrix[5][4] == 'R' and  matrix[4][3] == 'R' and  matrix[3][2] == 'R'){return 'R';}
    return null;
}
Kevin
  • 74,910
  • 12
  • 133
  • 166
  • 6
    I retract my statement, it CAN be done. Nobody likes a smart a** :P – Ross Drew Nov 25 '13 at 20:00
  • 1
    Yes, I suppose that you could enumerate all possible winning combinations. But then again, isn't a conditional block with 69 possible conditions really a *looping* of conditions? Sure, you have them all as separate conditions. Another alternative would be to put them in a list of conditions to evaluate, then loop through that list (more elegant). In essence though, I think the idea is the same. And of course as your specs change you could generate a new list of winning combinations - but to do that, you would **cough** need a loop **cough**. :) +1 in any case :P – Chris Cirefice Nov 25 '13 at 20:01
  • What I had intended or meant by my question was if I could store the winning combos in a data structure such as a hash table or something. And look up the key of the location when a chip was placed in it. I was not trying to avoid doing any loops even if thats what it sounded like i meant – PhilipGough Nov 25 '13 at 20:11
  • hey.. you need to check only the column where the last coin was inserted! not the whole grid! – Gianluca Ghettini Dec 02 '15 at 13:33
2

I'm going to assume you have your board as a char[][] or int[][] (matrix), where you might have:

if (char[][]) -> 'B' for black, 'R' for red

or

if (int[][]) -> 1 for black, 0 for red

In my mind it would only make sense to have a 2-d array (matrix) for this kind of problem. Anyway, the algorithm to check the winner not just should, but must loop over the board, as others have said. The reason for this is because it is the most elegant solution to this type of problem.

You should basically do the following:

A nested for loop: one to iterate rows, one to iterate columns.

for (int i = 0; i < matrix.length; i ++) {
  for (int j = 0; j < matrix.length; j ++) {
    // Check for stuff in here
  }
}

You can check vertical, horizontal and diagonal through something like the following:

vertical (down):

if (colorOfPieceFound) {
  // check j-1 (move down one row, same column);
  // check j-2, etc.
}

horizontal (left):

if (colorOfPieceFound) {
  // check i-1 (move left one column, same row);
  // check i-2, etc.
}

diagonal (up-left):

if (colorOfPieceFound) {
  // check [i-1][j+1] (move down one row, same column);
  // repeat with +/- 2
}

Basically you have 8 directions you need to check when you find a piece. You do this for each element of the matrix (i.e. checkAllDirections(matrix[i][j])) or starting at the place where the piece was 'dropped'.

Chris Cirefice
  • 5,475
  • 7
  • 45
  • 75
  • Yeah thats what I have, a 2d array containing a state which is red or black. Just thought there might be a better way to go about it. Thanks – PhilipGough Nov 25 '13 at 19:37
  • 1
    Well, I mean since you're using Java you could build your own matrix *iterator*, which would kind of 'functionalize' that process. But I've done similar "winner checking" algorithms for different games, and if the board is anything like a matrix, it's best just to do a nested `for` loop. And like I said in my answer, and as others have said, you could make it '*smarter*' by having it only check for a winner after a move was made, at that particular location (this would make the most sense). Otherwise you could just check the entire board every round. Either one works! – Chris Cirefice Nov 25 '13 at 19:40
  • actually it would make more sense, and I did this, to make 0 an empty space as that is the default `int[][]` value and have red = 1, black = 2. I created `RoundButtons`, literally round buttons, that when clicked on change color and made a 2D array of those. My code is pretty much the same as what you have, except my code always starts at the bottom left corner, checks all directions for that piece @ [5][0] then moves one column over etc. but Im having problems. When I run my code by hand, it works, but something is messed up – Ungeheuer Jun 10 '15 at 22:33
1

With a small search space it is totally okay to use nested loops for checking victory conditions in a connect four game.

If you store winning configurations you have to compare your playing field with them - most likely via nested loops or hashes. (Direct comparison or matrix multiplication, doesn't matter)

I would advice using nested loops and using different methods for checking for horizontal, vertical and diagonal winning conditions. Yes there are possibilities to make it more efficient - mostly for bigger boards - but it is really not worth the hassle for a 4x4 board as the speed improvement is marginal if even existent (it could be even slower) and the code gets more complicated.

There is some optimization you can find for example here. But as you see, the code gets non-intuitive.

TheMorph
  • 572
  • 2
  • 10
1

I did this recently while building a NodeJS version of Connect4. After every move, you check for a winner. The way I did it was to have 3 methods, checkForWinnerHorizontal(), checkForWinnerVertical(), and checkForWinnerDiagonal().

Each method would concatenate all the characters in a row(or column or diagonal) and then check the concatenated string for either 4 R's or 4 B's.

  • Horizontal was easy. Just join the characters in the row.
  • Vertical was a little harder because you need to get columns. You can build it by hardcoding each column or pivot the array and then use the Horizontal method.
  • Diagonal was the hardest. You need to get all the forward diagonals and backward diagonals. You also must check for out of bounds conditions (depending on you algorithm). I just built a getDiagonal(start, direction) method to return each diagonal.

In the end, you just check each of the concatenated strings to see if there are 4 of the same character in it.

L_7337
  • 2,650
  • 28
  • 42