I am creating a simple Connect Four program in Kotlin using a 2D array to print the board. Everything works fine except for my horizontal win-checker function. Because of the logic I am using, I get (index out of bounds) errors when trying to put your piece on the first column, because it is trying to check the next column in the array, but there is none. Is there a better way to handle checking for a winner? This is my function:
fun checkWinsHorizontal() {
for(row in 0 until gameBoard.size) {
for(col in 0 until gameBoard.size){
// if this spot is taken up by an "X", and the horizontally adjacent spaces are the same, declare winner
if (gameBoard[row][col] == "X" && (gameBoard[row][col] == gameBoard[row][col - 1] && gameBoard[row][col] == gameBoard[row][col - 2] && gameBoard[row][col] == gameBoard[row][col - 3]) ){
printBoard()
println("YOU WIN")
winner = true
return
}
// same thing as above but for a "computer" opponent
else if (gameBoard[row][col] == "O" && gameBoard[row][col] == gameBoard[row][col - 1] && gameBoard[row][col] == gameBoard[row][col - 2] && gameBoard[row][col] == gameBoard[row][col - 3]){
printBoard()
println("COMPUTER WINS")
winner = true
return
}
}
}
}
The comments above explain why you're getting the index out of bounds (you have hard coded values like gameBoard[row][col - 1] but col might be 0). I suggest a few fixes:
First, there's no need to check every cell on the board after each move. The only way a player can win is if the piece they just placed completes a row, column, or diagonal. So I suggest you check only potential wins involving that cell.
To do that for a row you could have something like:
fun completesRow(row: Int, col: Int) : Boolean {
var count: Int = 1
val symbol = gameBoard[row][col]
// First move left - now we check that the symbols (X or O) match
// AND that we're within bounds.
var curCol = col - 1
while (curCol >= 0 && gameBoard[row][curCol] == symbol) {
++count
if (count == 4) {
return true
}
--curCol
}
// same thing to the right; numColumns is assumed to be the number of
// columns in the board.
curCol = col + 1
while (curCol < numColumns && gameBoard[row][curCol] == symbol) {
++count
if (count == 4) {
return true
}
++curCol
}
// if you got here there weren't 4 in a row
return false
}
Note: the above is untested - I doubt it even compiles, but hopefully it's instructive.
You can also further generalize this if you want. Instead of having different functions that move left/right, up/down, and diagonally you could create Iterator instances for those movements and then have a single function that takes 2 iterators (one moving left and one right for example) and it can do the checks using that. That way you can use the same exact method to check a horizontal, vertical, or diagonal win.
I'm tinkering around with a cellular automaton and my movement detection function is acting really strangely. I'm 80% sure it's my implementation but I have no idea where the issue is. Could someone take a look and enlighten me since I've spent the better part of 7H trying to get it to work and it won't:
private int[] cellularSearch(short xPos, short yPos)
{
// the center position is our current position; the others are potentially free positions
byte[][] positions = new byte[][]{{0,0,0},{0,1,0},{0,0,0}};
int[] result = new int[2];
byte strike=0;
int dice0=0, dice1=0;
while(strike<9)
{
dice0 = r.nextInt(3)-1;
result[0] = xPos + dice0;
if((result[0] >= 0)
&& (result[0] < img.getWidth()))
{
dice1 = r.nextInt(3)-1;
result[1] = yPos + dice1;
if((result[1] >= 0)
&& (result[1] < img.getHeight()))
{
if((positions[dice1+1][dice0+1] != 1)) // if this isn't our own cell and wasn't tried before
{
if(img.getRGB(result[0], result[1]) == Color.white.getRGB()) // if the new cell is free
{
return result;
}
}
positions[dice1+1][dice0+1]=1; // we need to use +1 to create a correlation between the linkage in the matrix and the actual positions around our cell
strike++;
}
}
}
}
The code works and it correctly identifies when a pixel is white and returns the position for it. My problem is the distribution of the results. Given that I'm using Random both for the row and the column, I was expecting a near equal distribution over all possible locations, but what happens is that this code seems to prefer the cell right above the coordinates being fed in (it hits it ~3x as much as the other ones) and the one right below the coordinates (it hits it ~2x as much as the others).
When I start my program and all my pixels slowly move towards the top of the window on EVERY run (vs true randomness with my old lengthy code which was 3x as long), so there's gotta be an error in there somewhere. Could someone please lend a hand?
Thank you in advance!
EDIT: Thank you everyone for the effort! Sorry for the non-compiling code but I extracted the main purpose of the function while cutting out a ton of commented code (my other approaches to implementing this function). Locally the code has the return statement and it runs. I'll slowly go through all your answers in the next few hours (gonna have dinner soon).
EDIT2: I tried what #DodgyCodeException and #tevemadar suggested and made a list with all the 8 positions, then shuffle them each time I enter the function, and then iterate through them, trying each one in part. Still the position exactly above and below the current cell are selected most. I'm baffled. This is my old super-spaghetti code that I've written for this function and it worked perfectly with no errors, equal distribution, and (oddly enough) it's the most efficient implementation that I've tried out of everything mentioned here. After I'm done with lunch and filing some paperwork I'll thoroughly study it (it's been ~ 2 years since I wrote it) to see why it works so well. If anyone still has ideas, I'm fully open.
boolean allRan=false;
int lastDice=0, anteLastDice=0, dice = r.nextInt(3)+1;
//the initial dice usage is for selecting the row on which we'll operate:
//dice = 1 or 3 -> we operate above or under our current cell; dice = 2 -> we operate on the same row
while(!allRan)
{
if((dice==1) || (dice==3))
{
int i= r.nextInt(3);
if(((xPos-1+i) < img.getWidth())
&& ((xPos-1+i) >= 0))
{
if(((yPos-1) >= 0)
&& (img.getRGB(xPos-1+i, yPos-1) == Color.white.getRGB())
&& (dice==1))
{
result[0] = xPos-1+i;
result[1] = yPos-1;
above++;
endTime = (int) System.currentTimeMillis();
section4Runtime += (double) (endTime - startTime) / 1000;
return result;
}
else if(((yPos+1) < img.getHeight())
&& (img.getRGB(xPos-1+i, yPos+1) == Color.white.getRGB())
&& (dice==3))
{
result[0] = xPos-1+i;
result[1] = yPos+1;
below++;
endTime = (int) System.currentTimeMillis();
section4Runtime += (double) (endTime - startTime) / 1000;
return result;
}
}
// if this section is reached, it means that: the initial dice roll didn't find a free cell, or the position was out of bounds, or the dice rolled 2
// in this section we do a dice reroll (while remembering and avoiding our previous values) so that we cover all dice rolls
if(dice==1)
{
if(lastDice==0)
{
lastDice=dice;
dice += r.nextInt(2)+1; // we incrmeent randomly towards 2 or 3.
}
else
{
if(lastDice==2)
{
if(anteLastDice==0)
{
anteLastDice= lastDice;
lastDice=dice;
dice=3;
}
else
{
allRan=true;
}
}
else if(lastDice==3)
{
if(anteLastDice==0)
{
anteLastDice= lastDice;
lastDice=dice;
dice=2;
}
else
{
allRan=true;
}
}
}
}
else // dice is 3
{
if(lastDice==0)
{
lastDice=dice;
dice -= r.nextInt(2)+1; // we decrement randomly towards 2 or 1.
}
else
{
if(lastDice==2)
{
if(anteLastDice==0)
{
anteLastDice= lastDice;
lastDice=dice;
dice=1;
}
else
{
allRan=true;
}
}
else if(lastDice==1)
{
if(anteLastDice==0)
{
anteLastDice= lastDice;
lastDice=dice;
dice=2;
}
else
{
allRan=true;
}
}
}
}
}
if(dice==2)
{
int i=0;
i += r.nextInt(2)==0?-1:1;
if(((xPos+i) < img.getWidth())
&& ((xPos+i) >= 0)
&& (img.getRGB(xPos+i, yPos) == Color.white.getRGB()))
{
result[0] = xPos+i;
result[1] = yPos;
leveled++;
endTime = (int) System.currentTimeMillis();
section4Runtime += (double) (endTime - startTime) / 1000;
return result;
}
// same as above: a dice reroll (with constrictions)
if(lastDice==0)
{
lastDice=dice;
dice+= r.nextInt(2)==0?-1:1; // randomly chose if you decrement by 1 or increment by 1
}
else
{
if(lastDice==1)
{
if(anteLastDice==0)
{
anteLastDice= lastDice;
lastDice=dice;
dice =3;
}
else
{
allRan=true;
}
}
else if(lastDice==3)
{
if(anteLastDice==0)
{
anteLastDice= lastDice;
lastDice=dice;
dice =1;
}
else
{
allRan=true;
}
}
}
}
}
return result;
After much thought, I eventually figured it out. All the ideas that we all had were violating a fundamental "rule" of the first implementation that I was using: the first implementation was trying a random position on one of the 3 lines, then moving on to the next lines (without coming back to try the other positions on that line). Example: if the algo selected the line above, it would randomly try the top-left corner to see if it's free; if it wasn't then it would try the same line as the current cell and the line below (again, just with 1 of their possible positions) without coming back. All our ideas were iterating through all possibilities around the cell, which meant that it was inevitable to have the top and bottom line have more hits than the middle (since top and bottom have 3 possible points each while middle has only 2). Also, when there were holes in the field, the cells most likely to fill it up were the ones that were moving diagonally (which in the end is up or down) or those directly moving up or down, since those moving sideways only had the options left/ right. The only mystery that will remain unsolved is why (using our proposed implementations) the model would generally use the point exactly above our current cell. I have no idea why it loves going straight up most of the time with that implementation. Nevertheless, the new algorithm (which reflects the old one, but is much lighter) is:
boolean[] lines = new boolean[]{false, false, false};
byte checks =0;
while(checks < 3) // just 3 tries in total
{
dice = r.nextInt(3);
if(lines[dice]== false)
{
lines[dice] = true; // just 1 try per line
// calculated here since we reuse dice below
result[1] = yPos - 1 + dice; // will be above if dice==0; will be below if dice==2; same line if dice==1
if((dice == 0) || (dice == 2)) // top/bottom line
{dice = r.nextInt(3)-1;}
else if(dice == 1) // middle line
{dice = r.nextInt(2)==0?-1:1;} // we exclude the middle point since that's our current position
result[0] = xPos + dice; // logic is calculated above and just applied here
checks++;
}
if((result[0] >= 0)
&& (result[0] < img.getWidth())
&& (result[1] >= 0)
&& (result[1] < img.getHeight()))
{
if (img.getRGB(result[0], result[1]) == Color.white.getRGB()) // if the new cell is free
{
return result;
}
}
}
result[0] = -1; // in case we get here, reset the value so it's not used
This brings the code down from 167 lines to 33 lines (and makes it MUCH more readable). I have no idea who to select as the best solution. Please suggest if you have any ideas.
First, I have to admit I can't see what your algorithm is supposed to be doing -- it's not clear to me why you roll the each die when you do, other times using the existing value.
For a clear, easy to follow algorithm, I'd suggest scoping your dice variables inside the loop, rolling both at the same time, and making them final so that you know that each iteration has exactly one two-die roll:
while(strike < 9) {
final int roll1 = r.nextInt(3) - 1;
final int roll2 = r.nextInt(3) - 1;
strike += handleRoll(roll1,roll2);
}
You can prove the distribution to yourself by writing a simple counter for your handleRoll(), before later substituting your real code.
int[] counts = int[6];
void handleRoll(int roll1, int roll2) {
counts[1 + roll1] ++;
counts[4 + roll2] ++;
return 1;
}
(Increase the required strike count to get large enough samples to reason about)
Make sure you use the same instance of Random throughout the program -- don't keep making new ones.
(You could tidy this up a bit by creating a Coordinate class and a factory that creates random ones)
I simplified your code like this:
made a series of extract-method refactorings to tidy away detail
changed your rolls to use the range 0 to 2 instead of -1 to +1 -- since you use them in two places, and in one of those you add one again!
used x and y and only create result when needed
used final for the rolls and the resulting x and y, scoping them to the inside of the loop
turned nested ifs into an && logic
changed some odd type choices. The positions grid seems made for boolean. There's seldom any value in using short in Java.
So:
private int[] cellularSearch(int xPos, int yPos) {
boolean[][] positions =
new boolean[][] { { false, false, false },
{ false, true, false },
{ false, false, false } };
int strike = 0;
while (strike < 9) {
final int dice0 = r.nextInt(3);
final int dice1 = r.nextInt(3);
final int x = xPos + dice0 - 1;
final int y = yPos + dice1 - 1;
if (isInXrange(x) && isInYRange(y)) {
if (!alreadyTried(positions, dice1, dice0) && isWhite(x, y)) {
return new int[] { x, y };
}
markAsTried(positions, dice1, dice0);
strike++;
}
}
return null; // or whatever you intend to happen here
}
private boolean isInXrange(int x) {
return (x >= 0) && (x < img.getWidth());
}
private boolean isInYRange(int y) {
return (y >= 0) && (y < img.getHeight());
}
private boolean alreadyTried(boolean[][] positions, final int dice1, final int dice0) {
return positions[dice1 + 1][dice0 + 1];
}
private static void markAsTried(boolean[][] positions, int dice1, int dice0) {
positions[dice1][dice0] = true;
}
private boolean isWhite(final int x, final int y) {
return img.getRGB(x, y) == Color.white.getRGB();
}
I think this is equivalent to your code, with one exception -- yours doesn't roll the second die if the first roll takes you outside the width of the image. You could re-add this as a performance improvement later if you like.
But it exposes some issues. It looks as if the intent is to try every cell (you have a 3x3 grid, and you've chosen 9 "strikes") - but it doesn't increment strike when x,y is outside the image. It does increment strike when the position has been tried before. So you can exit the loop having not tried every cell.
I don't see a specific way that this causes the weighting you've described --
but it looks like the sort of thing that could lead to unexpected results.
(Anyway - since the code you've given doesn't compile, you didn't observe it with the code you've given us)
If the intention is to check every cell, it might be better to shuffle a list of cells to try, then test them in order:
List<Coords> coordsToTry = new ArrayList<>();
for(int x=0; x<2; x++) {
for(int y=0; y<2; y++) {
coordsToTry.add(new Coords( x, y));
}
}
Collections.shuffle(coordsToTry);
for(Coords coords : coordsToTry) {
if(isWhite(coords)) {
return coords;
}
}
return null; // or whatever is meant to happen when nothing found
The distribution of java.util.Random is not that uneven. You can confirm with the following code:
public static void main(String[] args) throws Exception {
final int N = 3;
Random r = new Random();
int[] counts = new int[N];
for (int i = 0; i <= 100_000; i++) {
counts[r.nextInt(N)]++;
}
System.out.println(Arrays.toString(counts));
}
UPDATE:
As you've said, the above code produces fairly evenly distributed values. However, add the following line at the beginning of the loop:
if (i % 6 == 0)
r = new Random(0);
And then you get [16667, 33334, 50000]. One value occurs twice as frequently, and another 3 times as frequently, as the first. This sets the random number generator to a newly created one with a constant seed. It simulates your code, in which you say you create a new Random() on entry to your function (albeit without a seed argument) and then your function calls nextInt() six times - this if (i % 6 == 0) statement ensures a new RNG is also created every 6 iterations.
Check your code and make sure you are only ever creating a RNG once in your whole program.
java.util.Random is a pseudorandom number generator (definition on wikipedia) and needs to be seeded.
From the docs:
If two instances of Random are created with the same seed, and the same sequence of method calls is made for each, they will generate and return identical sequences of numbers. In order to guarantee this property, particular algorithms are specified for the class Random.
If you want to be sure to get good random numbers, use SecureRandom, which is guaranteed to produce non-deterministic output
Since you are interested in the combined distribution of the two 'dices', on top of #DodgyCodeException's suggestion, you can check statistics like
public static void main(String[] args) {
Random r=new Random();
int stat[]=new int[9];
for(int i=0;i<9000;i++)
stat[r.nextInt(3)+r.nextInt(3)*3]++;
for (int i : stat)
System.out.println(i);
}
However it is pretty even too.
There is a minor difference between generating random numbers from a power-of-two-range and otherwise, so if you really want to do some magic, you can use the fact that you are actually picking a position out of 8 possibilities (since the middle one is ruled out at the beginning).
Something like
final int xhelper[]=new int[]{-1, 0, 1,-1, 1,-1, 0, 1};
final int yhelper[]=new int[]{-1,-1,-1, 0, 0, 1, 1, 1};
...
int dir=r.nextInt(8);
int dice0=xhelper[dir];
int dice1=yhelper[dir];
But in fact I do not think it makes a difference.
I am trying to design a Tic-Tac-Toe game in Java. I must point out that I am a complete beginner in Java. So I am trying to generate all possible combinations of the game, then store it in a file. We know that there are 255168 possible combinations. Anyway here is my code:
import java.io.*;
import java.util.Random;
import java.util.Arrays;
public class generator2 {
public static void main(String[] args) {
Random r=new Random();
String s;
String store[] = new String[255168];
int count=0;
int i=0;
int a[][]=new int[3][3];
int wf;
int flag=0;
char b;
while(count<255168)
{
s="";
b='X';
flag=0;
for(int[] row : a)Arrays.fill(row, 0);
wf=0;
i=0;
while(wf==0)
{
int r1=r.nextInt(3)+0;
int r2=r.nextInt(3)+0;
if(a[r1][r2]==0)
{
i++;
if(flag==0) {a[r1][r2]=1;flag=1;}
else {a[r1][r2]=2;flag=0;}
if(a[0][0]==1 && a[0][1]==1 && a[0][2]==1 || a[1][0]==1 && a[1][1]==1 && a[1][2]==1 || a[2][0]==1 && a[2][1]==1 && a[2][2]==1 || a[0][0]==1 && a[1][0]==1 && a[2][0]==1 || a[0][1]==1 && a[1][1]==1 && a[2][1]==1 || a[0][2]==1 && a[1][2]==1 && a[2][2]==1 || a[0][0]==1 && a[1][1]==1 && a[2][2]==1 || a[0][2]==1 && a[1][1]==1 && a[2][0]==1)
{
b='W';
wf=1;
break;
}
else if(a[0][0]==2 && a[0][1]==2 && a[0][2]==2 || a[1][0]==2 && a[1][1]==2 && a[1][2]==2 || a[2][0]==2 && a[2][1]==2 && a[2][2]==2 || a[0][0]==2 && a[1][0]==2 && a[2][0]==2 || a[0][1]==2 && a[1][1]==2 && a[2][1]==2 || a[0][2]==2 && a[1][2]==2 && a[2][2]==2 || a[0][0]==2 && a[1][1]==2 && a[2][2]==2 || a[0][2]==2 && a[1][1]==2 && a[2][0]==2)
{
b='L';
wf=1;
break;
}
else if(i==9)
{
b='T';
wf=1;
break;
}
}
}
s+=b;
for(i=0;i<3;i++)
for(int j=0;j<3;j++)
s+=String.valueOf(a[i][j]);
if(repeat(s,store,count)) {store[count]=s;count++;s="";System.out.println(count);}
else {continue;}
}
// for(i=0;i<958;i++)
// {
// System.out.println(store[i]);
// }
}
public static boolean repeat(String s,String[] a,int count){
int flag=0;
for(int i=0;i<count;i++)
{
if(a[i].equals(s)) {flag=1;break;}
}
if(flag==1)return false;
else return true;
}
}
Format of stored string:
First Character: W-Player1 Win.. L-Player2 Win.. T-Tie
next 9 characters represent board layout:
211012012 represents
2 1 1
0 1 2
0 1 2
Note that 0 is for position still not filled by any player. As we can see Player1 wins in above game so the string is stored is W211012012.
Theoretically this method should generate all possible unique combinations(255168), but it is not. It generates 958 combinations and then the program is just stuck.
Actually I think you should be happy to know that 958 is the correct answer for the number of legal endgame states.
https://archive.ics.uci.edu/ml/machine-learning-databases/tic-tac-toe/tic-tac-toe.names
255168 is correct when you keep track of the order of each player's moves -- not just the final end state. You are computing the valid final end game states.
Take your example of W211012012. There are 108 ways to accomplish W211012012 when considering the order of each player's moves. Player 1's top right move can't be last and other 3 moves can be in any order for 3*3!. Player 2's three moves can be in any order for 3!. 108=3*3!*3!.
If instead you want to calculate all 255168 combinations when the order of the moves matters consider representing your state strings differently. Maybe [WLT](1,row,col)(2,row,col)(1,row,col)... or any other way that would encode the order of the moves.
You are simulating all possible games by having 2 players play randomly and keeping track of unique games. That's one way to do it, and a good exercise, but not particularly efficient. You could also use a searching algorithm like DFS https://en.m.wikipedia.org/wiki/Depth-first_search to explore the search space.
I am creating a boardgame which has two different coloured pieces, black and red.
If a player surrounds the opponents pieces with his own, either horizontally or vertically, the pieces are removed. Here are some pictures to demonstrate this:
My board is a simple 2d integer array, with values of 0, 1 or 2 depending on whether the space is empty, has a red piece or a black piece.
This is the code I have come up with so far, however I am getting issues with out of bounds errors and it also does not account for capturing more than one piece.
static final int EMPTY = 0, BLACK = 1, RED = 2, ROW = 9, COLUMN = 9;
board = new int[ROW][COLUMN];
public void captureRedPieces() {
for(int i = 0; i < ROW; i++) {
for(int j = 0; j < COLUMN; j++) {
if(i <= ROW - 2) {
if(board[i][j] == 1 && board[i + 1][j] == 2 && board[i + 2][j] == 1) {
board[i + 1][j] = EMPTY;
}
}
if(i <= COLUMN - 2) {
if(board[i][j] == 1 && board[i][j + 1] == 2 && board[i][j + 2] == 1) {
board[i][j + 1] = EMPTY;
}
}
}
}
}
Could anyone help me come up with a better solution for capturing pieces?
You are testing whether i <= ROW - 2, but then you are using i+2 as an index for your check. This means that if i is 7, which is equal to ROW - 2 and passes your if test, then i+2 will be 9, which is out of bounds because the array only goes 0 to 8.
So you should correct this to i < ROW - 2 rather than <=.
Also, you have this code:
if(i <= COLUMN - 2) {
if(board[i][j] == 1 && board[i][j + 1] == 2 && board[i][j + 2] == 1) {
board[i][j + 1] = EMPTY;
}
}
This should be a condition on j, not on i - and it has to be fixed in the same way I told you about i - < instead of <=.
Note: since your rules state that a "surrounding" state is a capture only after the surrounding color makes a move, perhaps you should change your approach: you should only check the position where black made a move, to match with positions around it. Of course, you'll still have to make sure you don't go out of bounds. Your current approach might mark places that are "surrounded" since previous moves, and that would be wrong per the rules.
So your method should be declared like so:
public void captureRedPieces(int blackMoveRow, int blackMoveCol )
Probably you have to replace i <= COLUMN - 2 with j <= COLUMN - 2. Seems that capturing occurs after the new move. If you know the exact position of the new piece, then no need to iterate over the whole board. You just need to check nearby pieces in the same row and in the same column where the new piece was placed.
this is more of a logic question than syntax but I'm sure you guys have better ways to do it than me anyway. So I have some pieces (JLabels) on a board (11x11 Grid of JPanels on a JPanel) all in a frame. I'm trying to highlight the "possible moves" for these pieces (I.E. how many panels they can cross in a move) very similar to in many online chessgames. I have the logic that checks if movement follows the rules, and it works perfect, I just can't seem to figure out how to find all of those legal moves at once and use them.
This is the code that I use to check if movement is legal:
public void movePieces(MouseEvent me)
{
MouseEvent e = me;
if (turnCount%2 == 1 && pieceCheck[(e.getY()/yInc)][(e.getX()/xInc)])
{
if (playerOne && (logic[(e.getY()/yInc)][(e.getX()/xInc)] == 0 || logic[(e.getY()/yInc)][(e.getX()/xInc)] == 2 || logic[(e.getY()/yInc)][(e.getX()/xInc)] == 4))
{
otherCount = logic[(e.getY()/yInc)][(e.getX()/xInc)];
tempX = e.getX();
tempY = e.getY();
paintPossible(tempX, tempY);
turnCount++;
}
if (!playerOne && (logic[(e.getY()/yInc)][(e.getX()/xInc)] == 1 || logic[(e.getY()/yInc)][(e.getX()/xInc)] == 3 || logic[(e.getY()/yInc)][(e.getX()/xInc)] == 5))
{
otherCount = logic[(e.getY()/yInc)][(e.getX()/xInc)];
tempX = e.getX();
tempY = e.getY();
turnCount++;
}
}
else if ((turnCount%2 == 0 && logic[(e.getY()/yInc)][(e.getX()/xInc)] == -1 && !pieceCheck[(e.getY()/yInc)][(e.getX()/xInc)]) && (Math.abs(tempX - e.getX()) <= xInc && (Math.abs(tempY - e.getY()) <= yInc) || ((Math.abs(tempX - e.getX()) <= 2*xInc) && (Math.abs(tempY - e.getY()) < yInc/4)) || ((Math.abs(tempX - e.getX()) < xInc/4) && (Math.abs(tempY - e.getY()) <= 2*yInc))))
{
panels[(e.getY()/yInc)][(e.getX()/xInc)].add(pieces[otherCount]);
logic[(e.getY()/yInc)][(e.getX()/xInc)] = otherCount;
pieceCheck[(e.getY()/yInc)][(e.getX()/xInc)] = true;
pieceCheck[tempY/yInc][tempX/xInc] = false;
panels[tempY/yInc][tempX/xInc].setBackground(veryDarkGray);
panels[tempY/yInc][tempX/xInc].setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
playerOne = !playerOne;
turnCount++;
}
....
}
Basically the first if-statement and what's inside is for when you first click a piece, and then if it's your turn then it will set that piece as the next in line to put down, and grab the X-Y coordinates of where it is.
The else-if then activates the next time you click due to the rotation of my turnCount, and makes sure there's no piece where you're clicking and that the space is within a certain# of pixels to where your piece is before you move.
I need to take that same checking of validity in where you can move, and apply it in a separate method that will loop through the 2d array of JPanels that is my board and color the valid moves. The method would be called where "paintPossible(tempX, tempY)" is, and in the same spot in the "if" below.