Checking for win on a wrap-around Connect 6 board

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
3
down vote

favorite












I have a method, that checks win conditions on a "Torus" board, which is a board without any borders. This means that if you place 4 diagonal stones on the top left, and 2 diagonal stones in the bottom right, if they are in the same diagonal and would connect if you ignored the border, which then would lead to a win. Basically it's a Connect 6 Game.



size() returns the size of the board which either is 18 or 20.



currentPlayer is a String like : "P1" or "P2".



r and c are the row and column where a move has just been made.



public boolean checkTorusWinner(int r, int c) 

int count = 0;
boolean hasWinner = false;
String currentPlayer = board[r][c];
int hSize = size();
int vSize = size();

/*
Checks Horizontally for a Win.
*/
for (int i = c; i < hSize; i++)
if (board[r][i] == currentPlayer)
count++;
else
count = 0;

if (i == size() - 1)
hSize = size() - 2;
for (int j = 0; j < hSize; j++)
if (board[r][j] == currentPlayer)
count++;
else
count = 0;

if (count == 6)

boardType = "none";
hasWinner = true;
break;



if (count == 6)
boardType = "none";
hasWinner = true;
break;


/*
Checks Vertically for a Win
*/
for (int i = r; i < vSize; i++)
if (board[i][c] == currentPlayer)
count++;
else
count = 0;

if (i == size() - 1)
i = -1;
vSize = size() - 2;

if (count == 6)

boardType = "none";
hasWinner = true;
break;



/*
Checks Diagonally from Top left to Bottom right
*/
if (c - r >= 0)
int startingC;
startingC = c - r;
int size = size();
for (int i = r, j = c; j < size; i++, j++)
if (board[i][j] == currentPlayer)
count++;
else
count = 0;

if (j == size() - 1)
j = startingC - 1;
i = -1;
size = size() - 2;


if (count == 6)
boardType = "none";
hasWinner = true;
break;


else
int size = size();
int startingR;
startingR = r - c;
for (int i = r, j = c; i < size; i++, j++)
if (board[i][j] == currentPlayer)
count++;
else
count = 0;

if (i == size() - 1)
j = -1;
i = startingR - 1;
size = size() - 2;



if (count == 6)
boardType = "none";
hasWinner = true;
break;





/*
Checks Diagonally from bottom left to top right;
*/
if (r + c <= 17)
int loop = 0;
int startingR;
startingR = r + c;
for (int i = r, j = c; i >= 0; i--, j++)
if (board[i][j] == currentPlayer)
count++;
else
count = 0;


if (i == 0 && loop == 0)
i = startingR + 1;
j = -1;
loop++;


if (count == 6)
boardType = "none";
hasWinner = true;
break;



else if (r + c > 17)
int loop = 0;
int startingC;
startingC = (r + c) - (size() - 1);
for (int i = r, j = c; i >= startingC; i--, j++)
if (board[i][j] == currentPlayer)
count++;
else
count = 0;

if (i == startingC && loop == 0)
i = size();
j = startingC - 1;
loop++;

if (count == 6)
boardType = "none";
hasWinner = true;
break;




return hasWinner;



Unfortunately this method's length doesn't meet the requirement for my university: it has to be a maximum of 80 lines. I don't know how I'm supposed to shorten this code so that it still works.







share|improve this question

















  • 1




    for the record... are you mandated to solve the problem in a single method?
    – Vogel612♦
    Mar 3 at 18:39










  • I think it is shorter to write a method that ignores which was the last move and just loops the entire board to find any winning combination, and if so, by which player.
    – JanErikGunnar
    Mar 3 at 20:00










  • This doesn't look like it returns the correct result. Have you checked it? In particular, what happens if the newest piece is in the middle of a horizontal sequence?
    – mdfst13
    Mar 3 at 23:28
















up vote
3
down vote

favorite












I have a method, that checks win conditions on a "Torus" board, which is a board without any borders. This means that if you place 4 diagonal stones on the top left, and 2 diagonal stones in the bottom right, if they are in the same diagonal and would connect if you ignored the border, which then would lead to a win. Basically it's a Connect 6 Game.



size() returns the size of the board which either is 18 or 20.



currentPlayer is a String like : "P1" or "P2".



r and c are the row and column where a move has just been made.



public boolean checkTorusWinner(int r, int c) 

int count = 0;
boolean hasWinner = false;
String currentPlayer = board[r][c];
int hSize = size();
int vSize = size();

/*
Checks Horizontally for a Win.
*/
for (int i = c; i < hSize; i++)
if (board[r][i] == currentPlayer)
count++;
else
count = 0;

if (i == size() - 1)
hSize = size() - 2;
for (int j = 0; j < hSize; j++)
if (board[r][j] == currentPlayer)
count++;
else
count = 0;

if (count == 6)

boardType = "none";
hasWinner = true;
break;



if (count == 6)
boardType = "none";
hasWinner = true;
break;


/*
Checks Vertically for a Win
*/
for (int i = r; i < vSize; i++)
if (board[i][c] == currentPlayer)
count++;
else
count = 0;

if (i == size() - 1)
i = -1;
vSize = size() - 2;

if (count == 6)

boardType = "none";
hasWinner = true;
break;



/*
Checks Diagonally from Top left to Bottom right
*/
if (c - r >= 0)
int startingC;
startingC = c - r;
int size = size();
for (int i = r, j = c; j < size; i++, j++)
if (board[i][j] == currentPlayer)
count++;
else
count = 0;

if (j == size() - 1)
j = startingC - 1;
i = -1;
size = size() - 2;


if (count == 6)
boardType = "none";
hasWinner = true;
break;


else
int size = size();
int startingR;
startingR = r - c;
for (int i = r, j = c; i < size; i++, j++)
if (board[i][j] == currentPlayer)
count++;
else
count = 0;

if (i == size() - 1)
j = -1;
i = startingR - 1;
size = size() - 2;



if (count == 6)
boardType = "none";
hasWinner = true;
break;





/*
Checks Diagonally from bottom left to top right;
*/
if (r + c <= 17)
int loop = 0;
int startingR;
startingR = r + c;
for (int i = r, j = c; i >= 0; i--, j++)
if (board[i][j] == currentPlayer)
count++;
else
count = 0;


if (i == 0 && loop == 0)
i = startingR + 1;
j = -1;
loop++;


if (count == 6)
boardType = "none";
hasWinner = true;
break;



else if (r + c > 17)
int loop = 0;
int startingC;
startingC = (r + c) - (size() - 1);
for (int i = r, j = c; i >= startingC; i--, j++)
if (board[i][j] == currentPlayer)
count++;
else
count = 0;

if (i == startingC && loop == 0)
i = size();
j = startingC - 1;
loop++;

if (count == 6)
boardType = "none";
hasWinner = true;
break;




return hasWinner;



Unfortunately this method's length doesn't meet the requirement for my university: it has to be a maximum of 80 lines. I don't know how I'm supposed to shorten this code so that it still works.







share|improve this question

















  • 1




    for the record... are you mandated to solve the problem in a single method?
    – Vogel612♦
    Mar 3 at 18:39










  • I think it is shorter to write a method that ignores which was the last move and just loops the entire board to find any winning combination, and if so, by which player.
    – JanErikGunnar
    Mar 3 at 20:00










  • This doesn't look like it returns the correct result. Have you checked it? In particular, what happens if the newest piece is in the middle of a horizontal sequence?
    – mdfst13
    Mar 3 at 23:28












up vote
3
down vote

favorite









up vote
3
down vote

favorite











I have a method, that checks win conditions on a "Torus" board, which is a board without any borders. This means that if you place 4 diagonal stones on the top left, and 2 diagonal stones in the bottom right, if they are in the same diagonal and would connect if you ignored the border, which then would lead to a win. Basically it's a Connect 6 Game.



size() returns the size of the board which either is 18 or 20.



currentPlayer is a String like : "P1" or "P2".



r and c are the row and column where a move has just been made.



public boolean checkTorusWinner(int r, int c) 

int count = 0;
boolean hasWinner = false;
String currentPlayer = board[r][c];
int hSize = size();
int vSize = size();

/*
Checks Horizontally for a Win.
*/
for (int i = c; i < hSize; i++)
if (board[r][i] == currentPlayer)
count++;
else
count = 0;

if (i == size() - 1)
hSize = size() - 2;
for (int j = 0; j < hSize; j++)
if (board[r][j] == currentPlayer)
count++;
else
count = 0;

if (count == 6)

boardType = "none";
hasWinner = true;
break;



if (count == 6)
boardType = "none";
hasWinner = true;
break;


/*
Checks Vertically for a Win
*/
for (int i = r; i < vSize; i++)
if (board[i][c] == currentPlayer)
count++;
else
count = 0;

if (i == size() - 1)
i = -1;
vSize = size() - 2;

if (count == 6)

boardType = "none";
hasWinner = true;
break;



/*
Checks Diagonally from Top left to Bottom right
*/
if (c - r >= 0)
int startingC;
startingC = c - r;
int size = size();
for (int i = r, j = c; j < size; i++, j++)
if (board[i][j] == currentPlayer)
count++;
else
count = 0;

if (j == size() - 1)
j = startingC - 1;
i = -1;
size = size() - 2;


if (count == 6)
boardType = "none";
hasWinner = true;
break;


else
int size = size();
int startingR;
startingR = r - c;
for (int i = r, j = c; i < size; i++, j++)
if (board[i][j] == currentPlayer)
count++;
else
count = 0;

if (i == size() - 1)
j = -1;
i = startingR - 1;
size = size() - 2;



if (count == 6)
boardType = "none";
hasWinner = true;
break;





/*
Checks Diagonally from bottom left to top right;
*/
if (r + c <= 17)
int loop = 0;
int startingR;
startingR = r + c;
for (int i = r, j = c; i >= 0; i--, j++)
if (board[i][j] == currentPlayer)
count++;
else
count = 0;


if (i == 0 && loop == 0)
i = startingR + 1;
j = -1;
loop++;


if (count == 6)
boardType = "none";
hasWinner = true;
break;



else if (r + c > 17)
int loop = 0;
int startingC;
startingC = (r + c) - (size() - 1);
for (int i = r, j = c; i >= startingC; i--, j++)
if (board[i][j] == currentPlayer)
count++;
else
count = 0;

if (i == startingC && loop == 0)
i = size();
j = startingC - 1;
loop++;

if (count == 6)
boardType = "none";
hasWinner = true;
break;




return hasWinner;



Unfortunately this method's length doesn't meet the requirement for my university: it has to be a maximum of 80 lines. I don't know how I'm supposed to shorten this code so that it still works.







share|improve this question













I have a method, that checks win conditions on a "Torus" board, which is a board without any borders. This means that if you place 4 diagonal stones on the top left, and 2 diagonal stones in the bottom right, if they are in the same diagonal and would connect if you ignored the border, which then would lead to a win. Basically it's a Connect 6 Game.



size() returns the size of the board which either is 18 or 20.



currentPlayer is a String like : "P1" or "P2".



r and c are the row and column where a move has just been made.



public boolean checkTorusWinner(int r, int c) 

int count = 0;
boolean hasWinner = false;
String currentPlayer = board[r][c];
int hSize = size();
int vSize = size();

/*
Checks Horizontally for a Win.
*/
for (int i = c; i < hSize; i++)
if (board[r][i] == currentPlayer)
count++;
else
count = 0;

if (i == size() - 1)
hSize = size() - 2;
for (int j = 0; j < hSize; j++)
if (board[r][j] == currentPlayer)
count++;
else
count = 0;

if (count == 6)

boardType = "none";
hasWinner = true;
break;



if (count == 6)
boardType = "none";
hasWinner = true;
break;


/*
Checks Vertically for a Win
*/
for (int i = r; i < vSize; i++)
if (board[i][c] == currentPlayer)
count++;
else
count = 0;

if (i == size() - 1)
i = -1;
vSize = size() - 2;

if (count == 6)

boardType = "none";
hasWinner = true;
break;



/*
Checks Diagonally from Top left to Bottom right
*/
if (c - r >= 0)
int startingC;
startingC = c - r;
int size = size();
for (int i = r, j = c; j < size; i++, j++)
if (board[i][j] == currentPlayer)
count++;
else
count = 0;

if (j == size() - 1)
j = startingC - 1;
i = -1;
size = size() - 2;


if (count == 6)
boardType = "none";
hasWinner = true;
break;


else
int size = size();
int startingR;
startingR = r - c;
for (int i = r, j = c; i < size; i++, j++)
if (board[i][j] == currentPlayer)
count++;
else
count = 0;

if (i == size() - 1)
j = -1;
i = startingR - 1;
size = size() - 2;



if (count == 6)
boardType = "none";
hasWinner = true;
break;





/*
Checks Diagonally from bottom left to top right;
*/
if (r + c <= 17)
int loop = 0;
int startingR;
startingR = r + c;
for (int i = r, j = c; i >= 0; i--, j++)
if (board[i][j] == currentPlayer)
count++;
else
count = 0;


if (i == 0 && loop == 0)
i = startingR + 1;
j = -1;
loop++;


if (count == 6)
boardType = "none";
hasWinner = true;
break;



else if (r + c > 17)
int loop = 0;
int startingC;
startingC = (r + c) - (size() - 1);
for (int i = r, j = c; i >= startingC; i--, j++)
if (board[i][j] == currentPlayer)
count++;
else
count = 0;

if (i == startingC && loop == 0)
i = size();
j = startingC - 1;
loop++;

if (count == 6)
boardType = "none";
hasWinner = true;
break;




return hasWinner;



Unfortunately this method's length doesn't meet the requirement for my university: it has to be a maximum of 80 lines. I don't know how I'm supposed to shorten this code so that it still works.









share|improve this question












share|improve this question




share|improve this question








edited Mar 3 at 23:09









mdfst13

16.8k42055




16.8k42055









asked Mar 3 at 14:32









Gilles Chen

163




163







  • 1




    for the record... are you mandated to solve the problem in a single method?
    – Vogel612♦
    Mar 3 at 18:39










  • I think it is shorter to write a method that ignores which was the last move and just loops the entire board to find any winning combination, and if so, by which player.
    – JanErikGunnar
    Mar 3 at 20:00










  • This doesn't look like it returns the correct result. Have you checked it? In particular, what happens if the newest piece is in the middle of a horizontal sequence?
    – mdfst13
    Mar 3 at 23:28












  • 1




    for the record... are you mandated to solve the problem in a single method?
    – Vogel612♦
    Mar 3 at 18:39










  • I think it is shorter to write a method that ignores which was the last move and just loops the entire board to find any winning combination, and if so, by which player.
    – JanErikGunnar
    Mar 3 at 20:00










  • This doesn't look like it returns the correct result. Have you checked it? In particular, what happens if the newest piece is in the middle of a horizontal sequence?
    – mdfst13
    Mar 3 at 23:28







1




1




for the record... are you mandated to solve the problem in a single method?
– Vogel612♦
Mar 3 at 18:39




for the record... are you mandated to solve the problem in a single method?
– Vogel612♦
Mar 3 at 18:39












I think it is shorter to write a method that ignores which was the last move and just loops the entire board to find any winning combination, and if so, by which player.
– JanErikGunnar
Mar 3 at 20:00




I think it is shorter to write a method that ignores which was the last move and just loops the entire board to find any winning combination, and if so, by which player.
– JanErikGunnar
Mar 3 at 20:00












This doesn't look like it returns the correct result. Have you checked it? In particular, what happens if the newest piece is in the middle of a horizontal sequence?
– mdfst13
Mar 3 at 23:28




This doesn't look like it returns the correct result. Have you checked it? In particular, what happens if the newest piece is in the middle of a horizontal sequence?
– mdfst13
Mar 3 at 23:28










2 Answers
2






active

oldest

votes

















up vote
2
down vote













Thanks for sharing your code.




Your code is a procedural approach to the problem.



There is nothing wrong with procedural approaches in general, but Java is an object oriented (OO) programming language and if you want to become a good Java programmer then you should start solving problems in an OO way.



But OOP doesn't mean to "split up" code into random classes.



The ultimate goal of OOP is to reduce code duplication, improve readability and support reuse as well as extending the code.



Doing OOP means that you follow certain principles which are (among others):



  • information hiding / encapsulation

  • single responsibility

  • separation of concerns

  • KISS (Keep it simple (and) stupid.)

  • DRY (Don't repeat yourself.)

  • "Tell! Don't ask."

  • Law of demeter ("Don't talk to strangers!")

How might that help to improve your code?



From an OO point of view you have the current position and you have to check if that position is part of a line of at least 5 other (excluding itself) equal elements.



The first implication is that you only have to look at the current positions neighbors and that there is no need to scan the whole board.



The easieast way is to go in each direction and count the consecutive neighbors belonging to the current player. Afterwards you add the opposit directions and check the sum.



I use a trick to safely calculate an index in "wrap around" arrays:



(arrayLength + currentIndex + differece) % arrayLength 


where % is the modulo operator.



Here is how I would implement that:



 class FiledPosition
final int r, c;
FiledPosition(int r, int c)
this.r=r;
this.c=c;


interface NeighborCalculator
FiledPosition getFor(FiledPosition current);
}

enum Direction NORTH,NORTH_EAST,EAST,SOUTH_EAST,SOUTH,SOUTH_WEST,WEST,NORTH_WEST


the code above may live in separate classes. What follows must be in your solution class



 private final Direction opposits = new Direction
NORTH,SOUTH,
NORTH_EAST,SOUTH_WEST,
NORTH_WEST,SOUTH_EAST,
EAST,WEST


private final int WIN_COUNT_EXCLUDUNG_CURRENT = 5;
Map<Direction, NeighborCalculator> neigborSelector = new HashMap<>();

public boolean checkTorusWinner(int r, int c)

neigborSelector.put(NORTH, new NeighborCalculator() // pre java8 anonymous inner class
public FiledPosition getFor(FiledPosition currentPoint )
return new Point((vSize+currentPoint.r-1)%vSize, currentPoint.c));

);
neigborSelector.put(NORTH_EAST,currentPoint -> new Point((vSize+currentPoint.r-1)%vSize, (hSize+currentPoint.c+1)%hSize)); // java8 lambda
neigborSelector.put(EAST,currentPoint -> new Point(currentPoint.r, (hSize+currentPoint.c+1)%hSize));
neigborSelector.put(SOUTH_EAST,currentPoint -> new Point((vSize+currentPoint.r+1)%vSize, (hSize+currentPoint.c+1)%hSize));
// similar for all directions, should be in the classes constructor.

Map<Direction, Counter> lineSectionCounts = new HashMap<>();
String currentPlayer = board[r][c];
int hSize = size();
int vSize = size();

// count consecutive same in each direction without current
for(Direction direction : Direction.values())
int consecutiveSame = 0;
FiledPosition neigborPosition = neigborSelector.get(direction).getFor(new FiledPosition(r,c));
while(currentPlayer.equals(board[neigborPosition.r][neigborPosition.c]))
consecutiveSame++;
neigborPosition = neigborSelector.get(direction).getFor(neigborPosition);

lineSectionCounts.put(consecutiveSame); // auto boxed


// sum up opposit directions
for(Direction opposit : opposits)
if(WIN_COUNT_EXCLUDUNG_CURRENT < lineSectionCounts.get(oposit[0]) + lineSectionCounts.get(oposit[1])) // auto unbox
return true; // current Player won.

return false; // no winner yet



This complete code has 57 lines (24 without the configuration). There are 4 lines missing to completly configure neigborSelector map (if you use jav8 lambdas).



This code uses basic Java concepts like classes, interfaces and enums you should already have heared of.






share|improve this answer























  • This solution has 8 repetitions of code where the only difference is the -1, 0, +1. Additionally, since SOUTH is basically "NEGATIVE NORTH", defining SOUTH is effectively duplication of NORTH. I think it would be more DRY to have the four "real" directions (horizontal, vertical, diagonal forward, diagonal backward) as small objects only containing the "x-delta" and "y-delta" (1,0, 0,1, 1,1, 1,-1). Then the code (or a method on the direction class) can just negate both values to get the opposite direction where needed.
    – JanErikGunnar
    Mar 5 at 12:46










  • Additionally, WIN_COUNT_EXCLUDUNG_CURRENT is very specific, a WIN_COUNT (and taking -1 if "current" needs to be excluded) would be far more reusable and readable.
    – JanErikGunnar
    Mar 5 at 12:46










  • @JanErikGunnar "WIN_COUNT_EXCLUDUNG_CURRENT is very specific, a WIN_COUNT (and taking -1 if "current" needs to be excluded) would be far more reusable and readable" WIN_COUNT_EXCLUDUNG_CURRENT is an implementation detail but in OOP we reuse behavior, not code.
    – Timothy Truckle
    Mar 5 at 12:56






  • 1




    Fair enough, although I disagree :)
    – JanErikGunnar
    Mar 5 at 13:10






  • 1




    It's a big world with room for more than one way to look at it... ;o)
    – Timothy Truckle
    Mar 5 at 13:11


















up vote
0
down vote













Some tips:



  • obviously, break into smaller methods if allowed


  • There are many magic numbers and strings. 17? 6? "none"? Put them in variables or constants to make the code more readable and easier to adjust.


  • you are changing hSize value within a loop where hSize is the bound of the loop. This is very error prone!


  • hasWinner = true; break; can be replaced by return true;


  • modulo operator is fantastic for "looping" arrays. Example:
    length = 18;
    position = 17;
    array[(position) % length] == array[(position+1) % length]
    This will compare position 17 with position 0.


  • code can probably be simplified and more generic by taking less regard to the position of the last move.


  • the method sets board type to "none". I assume this resets the board. This makes the name of the method (checkTorusWinner) missleading


  • pseudo code for very easy approach



For each x:
For each y:
Set xwin = ywin = diagFwdWin = diagBackwdWin = true.
For each n = 1... winLength-1:
If board [x] [y] != board [(x+n) % boardwidth] [y] then
Xwin =false
End if
// Same if, but instead, y+n % boardheight, Ywin
// same if, but both x+n AND y+n, diagbackwdWin
// same if, but both x+n and y MINUS n, diagfwdWin
End for
If Xwin or ywin or diagFwdWin or diagBackwdWin == true then
Return true
End if
End for
End for
Return false


For better performance, x and y in outer loop can be limited to position of last added +/- winLength






share|improve this answer























    Your Answer




    StackExchange.ifUsing("editor", function ()
    return StackExchange.using("mathjaxEditing", function ()
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    );
    );
    , "mathjax-editing");

    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "196"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );








     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f188729%2fchecking-for-win-on-a-wrap-around-connect-6-board%23new-answer', 'question_page');

    );

    Post as a guest






























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    2
    down vote













    Thanks for sharing your code.




    Your code is a procedural approach to the problem.



    There is nothing wrong with procedural approaches in general, but Java is an object oriented (OO) programming language and if you want to become a good Java programmer then you should start solving problems in an OO way.



    But OOP doesn't mean to "split up" code into random classes.



    The ultimate goal of OOP is to reduce code duplication, improve readability and support reuse as well as extending the code.



    Doing OOP means that you follow certain principles which are (among others):



    • information hiding / encapsulation

    • single responsibility

    • separation of concerns

    • KISS (Keep it simple (and) stupid.)

    • DRY (Don't repeat yourself.)

    • "Tell! Don't ask."

    • Law of demeter ("Don't talk to strangers!")

    How might that help to improve your code?



    From an OO point of view you have the current position and you have to check if that position is part of a line of at least 5 other (excluding itself) equal elements.



    The first implication is that you only have to look at the current positions neighbors and that there is no need to scan the whole board.



    The easieast way is to go in each direction and count the consecutive neighbors belonging to the current player. Afterwards you add the opposit directions and check the sum.



    I use a trick to safely calculate an index in "wrap around" arrays:



    (arrayLength + currentIndex + differece) % arrayLength 


    where % is the modulo operator.



    Here is how I would implement that:



     class FiledPosition
    final int r, c;
    FiledPosition(int r, int c)
    this.r=r;
    this.c=c;


    interface NeighborCalculator
    FiledPosition getFor(FiledPosition current);
    }

    enum Direction NORTH,NORTH_EAST,EAST,SOUTH_EAST,SOUTH,SOUTH_WEST,WEST,NORTH_WEST


    the code above may live in separate classes. What follows must be in your solution class



     private final Direction opposits = new Direction
    NORTH,SOUTH,
    NORTH_EAST,SOUTH_WEST,
    NORTH_WEST,SOUTH_EAST,
    EAST,WEST


    private final int WIN_COUNT_EXCLUDUNG_CURRENT = 5;
    Map<Direction, NeighborCalculator> neigborSelector = new HashMap<>();

    public boolean checkTorusWinner(int r, int c)

    neigborSelector.put(NORTH, new NeighborCalculator() // pre java8 anonymous inner class
    public FiledPosition getFor(FiledPosition currentPoint )
    return new Point((vSize+currentPoint.r-1)%vSize, currentPoint.c));

    );
    neigborSelector.put(NORTH_EAST,currentPoint -> new Point((vSize+currentPoint.r-1)%vSize, (hSize+currentPoint.c+1)%hSize)); // java8 lambda
    neigborSelector.put(EAST,currentPoint -> new Point(currentPoint.r, (hSize+currentPoint.c+1)%hSize));
    neigborSelector.put(SOUTH_EAST,currentPoint -> new Point((vSize+currentPoint.r+1)%vSize, (hSize+currentPoint.c+1)%hSize));
    // similar for all directions, should be in the classes constructor.

    Map<Direction, Counter> lineSectionCounts = new HashMap<>();
    String currentPlayer = board[r][c];
    int hSize = size();
    int vSize = size();

    // count consecutive same in each direction without current
    for(Direction direction : Direction.values())
    int consecutiveSame = 0;
    FiledPosition neigborPosition = neigborSelector.get(direction).getFor(new FiledPosition(r,c));
    while(currentPlayer.equals(board[neigborPosition.r][neigborPosition.c]))
    consecutiveSame++;
    neigborPosition = neigborSelector.get(direction).getFor(neigborPosition);

    lineSectionCounts.put(consecutiveSame); // auto boxed


    // sum up opposit directions
    for(Direction opposit : opposits)
    if(WIN_COUNT_EXCLUDUNG_CURRENT < lineSectionCounts.get(oposit[0]) + lineSectionCounts.get(oposit[1])) // auto unbox
    return true; // current Player won.

    return false; // no winner yet



    This complete code has 57 lines (24 without the configuration). There are 4 lines missing to completly configure neigborSelector map (if you use jav8 lambdas).



    This code uses basic Java concepts like classes, interfaces and enums you should already have heared of.






    share|improve this answer























    • This solution has 8 repetitions of code where the only difference is the -1, 0, +1. Additionally, since SOUTH is basically "NEGATIVE NORTH", defining SOUTH is effectively duplication of NORTH. I think it would be more DRY to have the four "real" directions (horizontal, vertical, diagonal forward, diagonal backward) as small objects only containing the "x-delta" and "y-delta" (1,0, 0,1, 1,1, 1,-1). Then the code (or a method on the direction class) can just negate both values to get the opposite direction where needed.
      – JanErikGunnar
      Mar 5 at 12:46










    • Additionally, WIN_COUNT_EXCLUDUNG_CURRENT is very specific, a WIN_COUNT (and taking -1 if "current" needs to be excluded) would be far more reusable and readable.
      – JanErikGunnar
      Mar 5 at 12:46










    • @JanErikGunnar "WIN_COUNT_EXCLUDUNG_CURRENT is very specific, a WIN_COUNT (and taking -1 if "current" needs to be excluded) would be far more reusable and readable" WIN_COUNT_EXCLUDUNG_CURRENT is an implementation detail but in OOP we reuse behavior, not code.
      – Timothy Truckle
      Mar 5 at 12:56






    • 1




      Fair enough, although I disagree :)
      – JanErikGunnar
      Mar 5 at 13:10






    • 1




      It's a big world with room for more than one way to look at it... ;o)
      – Timothy Truckle
      Mar 5 at 13:11















    up vote
    2
    down vote













    Thanks for sharing your code.




    Your code is a procedural approach to the problem.



    There is nothing wrong with procedural approaches in general, but Java is an object oriented (OO) programming language and if you want to become a good Java programmer then you should start solving problems in an OO way.



    But OOP doesn't mean to "split up" code into random classes.



    The ultimate goal of OOP is to reduce code duplication, improve readability and support reuse as well as extending the code.



    Doing OOP means that you follow certain principles which are (among others):



    • information hiding / encapsulation

    • single responsibility

    • separation of concerns

    • KISS (Keep it simple (and) stupid.)

    • DRY (Don't repeat yourself.)

    • "Tell! Don't ask."

    • Law of demeter ("Don't talk to strangers!")

    How might that help to improve your code?



    From an OO point of view you have the current position and you have to check if that position is part of a line of at least 5 other (excluding itself) equal elements.



    The first implication is that you only have to look at the current positions neighbors and that there is no need to scan the whole board.



    The easieast way is to go in each direction and count the consecutive neighbors belonging to the current player. Afterwards you add the opposit directions and check the sum.



    I use a trick to safely calculate an index in "wrap around" arrays:



    (arrayLength + currentIndex + differece) % arrayLength 


    where % is the modulo operator.



    Here is how I would implement that:



     class FiledPosition
    final int r, c;
    FiledPosition(int r, int c)
    this.r=r;
    this.c=c;


    interface NeighborCalculator
    FiledPosition getFor(FiledPosition current);
    }

    enum Direction NORTH,NORTH_EAST,EAST,SOUTH_EAST,SOUTH,SOUTH_WEST,WEST,NORTH_WEST


    the code above may live in separate classes. What follows must be in your solution class



     private final Direction opposits = new Direction
    NORTH,SOUTH,
    NORTH_EAST,SOUTH_WEST,
    NORTH_WEST,SOUTH_EAST,
    EAST,WEST


    private final int WIN_COUNT_EXCLUDUNG_CURRENT = 5;
    Map<Direction, NeighborCalculator> neigborSelector = new HashMap<>();

    public boolean checkTorusWinner(int r, int c)

    neigborSelector.put(NORTH, new NeighborCalculator() // pre java8 anonymous inner class
    public FiledPosition getFor(FiledPosition currentPoint )
    return new Point((vSize+currentPoint.r-1)%vSize, currentPoint.c));

    );
    neigborSelector.put(NORTH_EAST,currentPoint -> new Point((vSize+currentPoint.r-1)%vSize, (hSize+currentPoint.c+1)%hSize)); // java8 lambda
    neigborSelector.put(EAST,currentPoint -> new Point(currentPoint.r, (hSize+currentPoint.c+1)%hSize));
    neigborSelector.put(SOUTH_EAST,currentPoint -> new Point((vSize+currentPoint.r+1)%vSize, (hSize+currentPoint.c+1)%hSize));
    // similar for all directions, should be in the classes constructor.

    Map<Direction, Counter> lineSectionCounts = new HashMap<>();
    String currentPlayer = board[r][c];
    int hSize = size();
    int vSize = size();

    // count consecutive same in each direction without current
    for(Direction direction : Direction.values())
    int consecutiveSame = 0;
    FiledPosition neigborPosition = neigborSelector.get(direction).getFor(new FiledPosition(r,c));
    while(currentPlayer.equals(board[neigborPosition.r][neigborPosition.c]))
    consecutiveSame++;
    neigborPosition = neigborSelector.get(direction).getFor(neigborPosition);

    lineSectionCounts.put(consecutiveSame); // auto boxed


    // sum up opposit directions
    for(Direction opposit : opposits)
    if(WIN_COUNT_EXCLUDUNG_CURRENT < lineSectionCounts.get(oposit[0]) + lineSectionCounts.get(oposit[1])) // auto unbox
    return true; // current Player won.

    return false; // no winner yet



    This complete code has 57 lines (24 without the configuration). There are 4 lines missing to completly configure neigborSelector map (if you use jav8 lambdas).



    This code uses basic Java concepts like classes, interfaces and enums you should already have heared of.






    share|improve this answer























    • This solution has 8 repetitions of code where the only difference is the -1, 0, +1. Additionally, since SOUTH is basically "NEGATIVE NORTH", defining SOUTH is effectively duplication of NORTH. I think it would be more DRY to have the four "real" directions (horizontal, vertical, diagonal forward, diagonal backward) as small objects only containing the "x-delta" and "y-delta" (1,0, 0,1, 1,1, 1,-1). Then the code (or a method on the direction class) can just negate both values to get the opposite direction where needed.
      – JanErikGunnar
      Mar 5 at 12:46










    • Additionally, WIN_COUNT_EXCLUDUNG_CURRENT is very specific, a WIN_COUNT (and taking -1 if "current" needs to be excluded) would be far more reusable and readable.
      – JanErikGunnar
      Mar 5 at 12:46










    • @JanErikGunnar "WIN_COUNT_EXCLUDUNG_CURRENT is very specific, a WIN_COUNT (and taking -1 if "current" needs to be excluded) would be far more reusable and readable" WIN_COUNT_EXCLUDUNG_CURRENT is an implementation detail but in OOP we reuse behavior, not code.
      – Timothy Truckle
      Mar 5 at 12:56






    • 1




      Fair enough, although I disagree :)
      – JanErikGunnar
      Mar 5 at 13:10






    • 1




      It's a big world with room for more than one way to look at it... ;o)
      – Timothy Truckle
      Mar 5 at 13:11













    up vote
    2
    down vote










    up vote
    2
    down vote









    Thanks for sharing your code.




    Your code is a procedural approach to the problem.



    There is nothing wrong with procedural approaches in general, but Java is an object oriented (OO) programming language and if you want to become a good Java programmer then you should start solving problems in an OO way.



    But OOP doesn't mean to "split up" code into random classes.



    The ultimate goal of OOP is to reduce code duplication, improve readability and support reuse as well as extending the code.



    Doing OOP means that you follow certain principles which are (among others):



    • information hiding / encapsulation

    • single responsibility

    • separation of concerns

    • KISS (Keep it simple (and) stupid.)

    • DRY (Don't repeat yourself.)

    • "Tell! Don't ask."

    • Law of demeter ("Don't talk to strangers!")

    How might that help to improve your code?



    From an OO point of view you have the current position and you have to check if that position is part of a line of at least 5 other (excluding itself) equal elements.



    The first implication is that you only have to look at the current positions neighbors and that there is no need to scan the whole board.



    The easieast way is to go in each direction and count the consecutive neighbors belonging to the current player. Afterwards you add the opposit directions and check the sum.



    I use a trick to safely calculate an index in "wrap around" arrays:



    (arrayLength + currentIndex + differece) % arrayLength 


    where % is the modulo operator.



    Here is how I would implement that:



     class FiledPosition
    final int r, c;
    FiledPosition(int r, int c)
    this.r=r;
    this.c=c;


    interface NeighborCalculator
    FiledPosition getFor(FiledPosition current);
    }

    enum Direction NORTH,NORTH_EAST,EAST,SOUTH_EAST,SOUTH,SOUTH_WEST,WEST,NORTH_WEST


    the code above may live in separate classes. What follows must be in your solution class



     private final Direction opposits = new Direction
    NORTH,SOUTH,
    NORTH_EAST,SOUTH_WEST,
    NORTH_WEST,SOUTH_EAST,
    EAST,WEST


    private final int WIN_COUNT_EXCLUDUNG_CURRENT = 5;
    Map<Direction, NeighborCalculator> neigborSelector = new HashMap<>();

    public boolean checkTorusWinner(int r, int c)

    neigborSelector.put(NORTH, new NeighborCalculator() // pre java8 anonymous inner class
    public FiledPosition getFor(FiledPosition currentPoint )
    return new Point((vSize+currentPoint.r-1)%vSize, currentPoint.c));

    );
    neigborSelector.put(NORTH_EAST,currentPoint -> new Point((vSize+currentPoint.r-1)%vSize, (hSize+currentPoint.c+1)%hSize)); // java8 lambda
    neigborSelector.put(EAST,currentPoint -> new Point(currentPoint.r, (hSize+currentPoint.c+1)%hSize));
    neigborSelector.put(SOUTH_EAST,currentPoint -> new Point((vSize+currentPoint.r+1)%vSize, (hSize+currentPoint.c+1)%hSize));
    // similar for all directions, should be in the classes constructor.

    Map<Direction, Counter> lineSectionCounts = new HashMap<>();
    String currentPlayer = board[r][c];
    int hSize = size();
    int vSize = size();

    // count consecutive same in each direction without current
    for(Direction direction : Direction.values())
    int consecutiveSame = 0;
    FiledPosition neigborPosition = neigborSelector.get(direction).getFor(new FiledPosition(r,c));
    while(currentPlayer.equals(board[neigborPosition.r][neigborPosition.c]))
    consecutiveSame++;
    neigborPosition = neigborSelector.get(direction).getFor(neigborPosition);

    lineSectionCounts.put(consecutiveSame); // auto boxed


    // sum up opposit directions
    for(Direction opposit : opposits)
    if(WIN_COUNT_EXCLUDUNG_CURRENT < lineSectionCounts.get(oposit[0]) + lineSectionCounts.get(oposit[1])) // auto unbox
    return true; // current Player won.

    return false; // no winner yet



    This complete code has 57 lines (24 without the configuration). There are 4 lines missing to completly configure neigborSelector map (if you use jav8 lambdas).



    This code uses basic Java concepts like classes, interfaces and enums you should already have heared of.






    share|improve this answer















    Thanks for sharing your code.




    Your code is a procedural approach to the problem.



    There is nothing wrong with procedural approaches in general, but Java is an object oriented (OO) programming language and if you want to become a good Java programmer then you should start solving problems in an OO way.



    But OOP doesn't mean to "split up" code into random classes.



    The ultimate goal of OOP is to reduce code duplication, improve readability and support reuse as well as extending the code.



    Doing OOP means that you follow certain principles which are (among others):



    • information hiding / encapsulation

    • single responsibility

    • separation of concerns

    • KISS (Keep it simple (and) stupid.)

    • DRY (Don't repeat yourself.)

    • "Tell! Don't ask."

    • Law of demeter ("Don't talk to strangers!")

    How might that help to improve your code?



    From an OO point of view you have the current position and you have to check if that position is part of a line of at least 5 other (excluding itself) equal elements.



    The first implication is that you only have to look at the current positions neighbors and that there is no need to scan the whole board.



    The easieast way is to go in each direction and count the consecutive neighbors belonging to the current player. Afterwards you add the opposit directions and check the sum.



    I use a trick to safely calculate an index in "wrap around" arrays:



    (arrayLength + currentIndex + differece) % arrayLength 


    where % is the modulo operator.



    Here is how I would implement that:



     class FiledPosition
    final int r, c;
    FiledPosition(int r, int c)
    this.r=r;
    this.c=c;


    interface NeighborCalculator
    FiledPosition getFor(FiledPosition current);
    }

    enum Direction NORTH,NORTH_EAST,EAST,SOUTH_EAST,SOUTH,SOUTH_WEST,WEST,NORTH_WEST


    the code above may live in separate classes. What follows must be in your solution class



     private final Direction opposits = new Direction
    NORTH,SOUTH,
    NORTH_EAST,SOUTH_WEST,
    NORTH_WEST,SOUTH_EAST,
    EAST,WEST


    private final int WIN_COUNT_EXCLUDUNG_CURRENT = 5;
    Map<Direction, NeighborCalculator> neigborSelector = new HashMap<>();

    public boolean checkTorusWinner(int r, int c)

    neigborSelector.put(NORTH, new NeighborCalculator() // pre java8 anonymous inner class
    public FiledPosition getFor(FiledPosition currentPoint )
    return new Point((vSize+currentPoint.r-1)%vSize, currentPoint.c));

    );
    neigborSelector.put(NORTH_EAST,currentPoint -> new Point((vSize+currentPoint.r-1)%vSize, (hSize+currentPoint.c+1)%hSize)); // java8 lambda
    neigborSelector.put(EAST,currentPoint -> new Point(currentPoint.r, (hSize+currentPoint.c+1)%hSize));
    neigborSelector.put(SOUTH_EAST,currentPoint -> new Point((vSize+currentPoint.r+1)%vSize, (hSize+currentPoint.c+1)%hSize));
    // similar for all directions, should be in the classes constructor.

    Map<Direction, Counter> lineSectionCounts = new HashMap<>();
    String currentPlayer = board[r][c];
    int hSize = size();
    int vSize = size();

    // count consecutive same in each direction without current
    for(Direction direction : Direction.values())
    int consecutiveSame = 0;
    FiledPosition neigborPosition = neigborSelector.get(direction).getFor(new FiledPosition(r,c));
    while(currentPlayer.equals(board[neigborPosition.r][neigborPosition.c]))
    consecutiveSame++;
    neigborPosition = neigborSelector.get(direction).getFor(neigborPosition);

    lineSectionCounts.put(consecutiveSame); // auto boxed


    // sum up opposit directions
    for(Direction opposit : opposits)
    if(WIN_COUNT_EXCLUDUNG_CURRENT < lineSectionCounts.get(oposit[0]) + lineSectionCounts.get(oposit[1])) // auto unbox
    return true; // current Player won.

    return false; // no winner yet



    This complete code has 57 lines (24 without the configuration). There are 4 lines missing to completly configure neigborSelector map (if you use jav8 lambdas).



    This code uses basic Java concepts like classes, interfaces and enums you should already have heared of.







    share|improve this answer















    share|improve this answer



    share|improve this answer








    edited Mar 5 at 8:44


























    answered Mar 5 at 8:01









    Timothy Truckle

    4,673316




    4,673316











    • This solution has 8 repetitions of code where the only difference is the -1, 0, +1. Additionally, since SOUTH is basically "NEGATIVE NORTH", defining SOUTH is effectively duplication of NORTH. I think it would be more DRY to have the four "real" directions (horizontal, vertical, diagonal forward, diagonal backward) as small objects only containing the "x-delta" and "y-delta" (1,0, 0,1, 1,1, 1,-1). Then the code (or a method on the direction class) can just negate both values to get the opposite direction where needed.
      – JanErikGunnar
      Mar 5 at 12:46










    • Additionally, WIN_COUNT_EXCLUDUNG_CURRENT is very specific, a WIN_COUNT (and taking -1 if "current" needs to be excluded) would be far more reusable and readable.
      – JanErikGunnar
      Mar 5 at 12:46










    • @JanErikGunnar "WIN_COUNT_EXCLUDUNG_CURRENT is very specific, a WIN_COUNT (and taking -1 if "current" needs to be excluded) would be far more reusable and readable" WIN_COUNT_EXCLUDUNG_CURRENT is an implementation detail but in OOP we reuse behavior, not code.
      – Timothy Truckle
      Mar 5 at 12:56






    • 1




      Fair enough, although I disagree :)
      – JanErikGunnar
      Mar 5 at 13:10






    • 1




      It's a big world with room for more than one way to look at it... ;o)
      – Timothy Truckle
      Mar 5 at 13:11

















    • This solution has 8 repetitions of code where the only difference is the -1, 0, +1. Additionally, since SOUTH is basically "NEGATIVE NORTH", defining SOUTH is effectively duplication of NORTH. I think it would be more DRY to have the four "real" directions (horizontal, vertical, diagonal forward, diagonal backward) as small objects only containing the "x-delta" and "y-delta" (1,0, 0,1, 1,1, 1,-1). Then the code (or a method on the direction class) can just negate both values to get the opposite direction where needed.
      – JanErikGunnar
      Mar 5 at 12:46










    • Additionally, WIN_COUNT_EXCLUDUNG_CURRENT is very specific, a WIN_COUNT (and taking -1 if "current" needs to be excluded) would be far more reusable and readable.
      – JanErikGunnar
      Mar 5 at 12:46










    • @JanErikGunnar "WIN_COUNT_EXCLUDUNG_CURRENT is very specific, a WIN_COUNT (and taking -1 if "current" needs to be excluded) would be far more reusable and readable" WIN_COUNT_EXCLUDUNG_CURRENT is an implementation detail but in OOP we reuse behavior, not code.
      – Timothy Truckle
      Mar 5 at 12:56






    • 1




      Fair enough, although I disagree :)
      – JanErikGunnar
      Mar 5 at 13:10






    • 1




      It's a big world with room for more than one way to look at it... ;o)
      – Timothy Truckle
      Mar 5 at 13:11
















    This solution has 8 repetitions of code where the only difference is the -1, 0, +1. Additionally, since SOUTH is basically "NEGATIVE NORTH", defining SOUTH is effectively duplication of NORTH. I think it would be more DRY to have the four "real" directions (horizontal, vertical, diagonal forward, diagonal backward) as small objects only containing the "x-delta" and "y-delta" (1,0, 0,1, 1,1, 1,-1). Then the code (or a method on the direction class) can just negate both values to get the opposite direction where needed.
    – JanErikGunnar
    Mar 5 at 12:46




    This solution has 8 repetitions of code where the only difference is the -1, 0, +1. Additionally, since SOUTH is basically "NEGATIVE NORTH", defining SOUTH is effectively duplication of NORTH. I think it would be more DRY to have the four "real" directions (horizontal, vertical, diagonal forward, diagonal backward) as small objects only containing the "x-delta" and "y-delta" (1,0, 0,1, 1,1, 1,-1). Then the code (or a method on the direction class) can just negate both values to get the opposite direction where needed.
    – JanErikGunnar
    Mar 5 at 12:46












    Additionally, WIN_COUNT_EXCLUDUNG_CURRENT is very specific, a WIN_COUNT (and taking -1 if "current" needs to be excluded) would be far more reusable and readable.
    – JanErikGunnar
    Mar 5 at 12:46




    Additionally, WIN_COUNT_EXCLUDUNG_CURRENT is very specific, a WIN_COUNT (and taking -1 if "current" needs to be excluded) would be far more reusable and readable.
    – JanErikGunnar
    Mar 5 at 12:46












    @JanErikGunnar "WIN_COUNT_EXCLUDUNG_CURRENT is very specific, a WIN_COUNT (and taking -1 if "current" needs to be excluded) would be far more reusable and readable" WIN_COUNT_EXCLUDUNG_CURRENT is an implementation detail but in OOP we reuse behavior, not code.
    – Timothy Truckle
    Mar 5 at 12:56




    @JanErikGunnar "WIN_COUNT_EXCLUDUNG_CURRENT is very specific, a WIN_COUNT (and taking -1 if "current" needs to be excluded) would be far more reusable and readable" WIN_COUNT_EXCLUDUNG_CURRENT is an implementation detail but in OOP we reuse behavior, not code.
    – Timothy Truckle
    Mar 5 at 12:56




    1




    1




    Fair enough, although I disagree :)
    – JanErikGunnar
    Mar 5 at 13:10




    Fair enough, although I disagree :)
    – JanErikGunnar
    Mar 5 at 13:10




    1




    1




    It's a big world with room for more than one way to look at it... ;o)
    – Timothy Truckle
    Mar 5 at 13:11





    It's a big world with room for more than one way to look at it... ;o)
    – Timothy Truckle
    Mar 5 at 13:11













    up vote
    0
    down vote













    Some tips:



    • obviously, break into smaller methods if allowed


    • There are many magic numbers and strings. 17? 6? "none"? Put them in variables or constants to make the code more readable and easier to adjust.


    • you are changing hSize value within a loop where hSize is the bound of the loop. This is very error prone!


    • hasWinner = true; break; can be replaced by return true;


    • modulo operator is fantastic for "looping" arrays. Example:
      length = 18;
      position = 17;
      array[(position) % length] == array[(position+1) % length]
      This will compare position 17 with position 0.


    • code can probably be simplified and more generic by taking less regard to the position of the last move.


    • the method sets board type to "none". I assume this resets the board. This makes the name of the method (checkTorusWinner) missleading


    • pseudo code for very easy approach



    For each x:
    For each y:
    Set xwin = ywin = diagFwdWin = diagBackwdWin = true.
    For each n = 1... winLength-1:
    If board [x] [y] != board [(x+n) % boardwidth] [y] then
    Xwin =false
    End if
    // Same if, but instead, y+n % boardheight, Ywin
    // same if, but both x+n AND y+n, diagbackwdWin
    // same if, but both x+n and y MINUS n, diagfwdWin
    End for
    If Xwin or ywin or diagFwdWin or diagBackwdWin == true then
    Return true
    End if
    End for
    End for
    Return false


    For better performance, x and y in outer loop can be limited to position of last added +/- winLength






    share|improve this answer



























      up vote
      0
      down vote













      Some tips:



      • obviously, break into smaller methods if allowed


      • There are many magic numbers and strings. 17? 6? "none"? Put them in variables or constants to make the code more readable and easier to adjust.


      • you are changing hSize value within a loop where hSize is the bound of the loop. This is very error prone!


      • hasWinner = true; break; can be replaced by return true;


      • modulo operator is fantastic for "looping" arrays. Example:
        length = 18;
        position = 17;
        array[(position) % length] == array[(position+1) % length]
        This will compare position 17 with position 0.


      • code can probably be simplified and more generic by taking less regard to the position of the last move.


      • the method sets board type to "none". I assume this resets the board. This makes the name of the method (checkTorusWinner) missleading


      • pseudo code for very easy approach



      For each x:
      For each y:
      Set xwin = ywin = diagFwdWin = diagBackwdWin = true.
      For each n = 1... winLength-1:
      If board [x] [y] != board [(x+n) % boardwidth] [y] then
      Xwin =false
      End if
      // Same if, but instead, y+n % boardheight, Ywin
      // same if, but both x+n AND y+n, diagbackwdWin
      // same if, but both x+n and y MINUS n, diagfwdWin
      End for
      If Xwin or ywin or diagFwdWin or diagBackwdWin == true then
      Return true
      End if
      End for
      End for
      Return false


      For better performance, x and y in outer loop can be limited to position of last added +/- winLength






      share|improve this answer

























        up vote
        0
        down vote










        up vote
        0
        down vote









        Some tips:



        • obviously, break into smaller methods if allowed


        • There are many magic numbers and strings. 17? 6? "none"? Put them in variables or constants to make the code more readable and easier to adjust.


        • you are changing hSize value within a loop where hSize is the bound of the loop. This is very error prone!


        • hasWinner = true; break; can be replaced by return true;


        • modulo operator is fantastic for "looping" arrays. Example:
          length = 18;
          position = 17;
          array[(position) % length] == array[(position+1) % length]
          This will compare position 17 with position 0.


        • code can probably be simplified and more generic by taking less regard to the position of the last move.


        • the method sets board type to "none". I assume this resets the board. This makes the name of the method (checkTorusWinner) missleading


        • pseudo code for very easy approach



        For each x:
        For each y:
        Set xwin = ywin = diagFwdWin = diagBackwdWin = true.
        For each n = 1... winLength-1:
        If board [x] [y] != board [(x+n) % boardwidth] [y] then
        Xwin =false
        End if
        // Same if, but instead, y+n % boardheight, Ywin
        // same if, but both x+n AND y+n, diagbackwdWin
        // same if, but both x+n and y MINUS n, diagfwdWin
        End for
        If Xwin or ywin or diagFwdWin or diagBackwdWin == true then
        Return true
        End if
        End for
        End for
        Return false


        For better performance, x and y in outer loop can be limited to position of last added +/- winLength






        share|improve this answer















        Some tips:



        • obviously, break into smaller methods if allowed


        • There are many magic numbers and strings. 17? 6? "none"? Put them in variables or constants to make the code more readable and easier to adjust.


        • you are changing hSize value within a loop where hSize is the bound of the loop. This is very error prone!


        • hasWinner = true; break; can be replaced by return true;


        • modulo operator is fantastic for "looping" arrays. Example:
          length = 18;
          position = 17;
          array[(position) % length] == array[(position+1) % length]
          This will compare position 17 with position 0.


        • code can probably be simplified and more generic by taking less regard to the position of the last move.


        • the method sets board type to "none". I assume this resets the board. This makes the name of the method (checkTorusWinner) missleading


        • pseudo code for very easy approach



        For each x:
        For each y:
        Set xwin = ywin = diagFwdWin = diagBackwdWin = true.
        For each n = 1... winLength-1:
        If board [x] [y] != board [(x+n) % boardwidth] [y] then
        Xwin =false
        End if
        // Same if, but instead, y+n % boardheight, Ywin
        // same if, but both x+n AND y+n, diagbackwdWin
        // same if, but both x+n and y MINUS n, diagfwdWin
        End for
        If Xwin or ywin or diagFwdWin or diagBackwdWin == true then
        Return true
        End if
        End for
        End for
        Return false


        For better performance, x and y in outer loop can be limited to position of last added +/- winLength







        share|improve this answer















        share|improve this answer



        share|improve this answer








        edited Mar 4 at 10:12


























        answered Mar 4 at 3:10









        JanErikGunnar

        23616




        23616






















             

            draft saved


            draft discarded


























             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f188729%2fchecking-for-win-on-a-wrap-around-connect-6-board%23new-answer', 'question_page');

            );

            Post as a guest