I am programming a matrix game which is played by two player. The objective is to say whether player 1 can win the game return 1, if not return 0.
player can delete either the last row or the last column of the matrix, but only if the sum of the numbers in that row/column is even. example:
original matrix:
[1 2]
[2 2]
then we can subtract these matrices from this:
sum row, and this becomes:
[1 3] [0 0]
[2 4] [1 1]
sum col, and this becomes:
[1 2] [0 1]
[3 4] [0 1]
now we can play the game, and its clear that player 1 can remove from either the row or the column matrix. then player two can make a move, and finally we can see that player 1 cant win in this example.
here is my implementation for this program:
I only provide the method that is suppose to use the row and the column matrices and should return a 1 if player 1 wins and a 0 if player 1 ant win.
public static int play(int[][] rowM, int[][] colM){
int player = 1;
int[][] matrix = new int[rowM.length][colM[0].length];
for (int i = 0; i < rowM.length; i++) {
for (int j = 0; j < colM[0].length; j++) {
//if no possible move
if(rowM[i][j] == 0 && colM[i][j] == 0){
//if player 1 is playing, and losing
if(player % 2 == 1){
matrix[i][j] = 0;
player++;
}
//player 2 is losing
else{
matrix[i][j] = 1;
player++;
}
continue;
}
//if player 1 is playing
if(player % 2 == 1){
player++;
//the value in this position is even
if(rowM[i][j] == 1){
//if there is only 1 row left,
if(i == 0){
matrix[i][j] = 1;
}
else if(matrix[i-1][j] == 1){
matrix[i][j] = 1;
}
else{
matrix[i][j] = 0;
}
}
//the value in the col matrix this position is even
else if(colM[i][j] == 1){
//if there is only 1 column left,
if(j == 0){
//matrix[i][j] = 1;
matrix[i][j] = 1;
//player++;
}
else if (matrix[i][j-1] == 1){
matrix[i][j] = 1;
}
else{
matrix[i][j] = 0;
}
}
}
//player 2 is playing
else{
player++;
//the value in this position is even
if(rowM[i][j] == 1){
if(i == 0){
matrix[i][j] = 1;
}
else if(matrix[i-1][j] == 1){
matrix[i][j] = 0;
}
else{
matrix[i][j] = 1;
}
}
//the value in the col matrix this position is even
else if(colM[i][j] == 1){
if(j == 0){
matrix[i][j] = 1;
}
else if(matrix[i][j-1] == 1){
matrix[i][j] = 0;
}
else{
matrix[i][j] = 1;
}
}
}
}
}
return matrix[rowM.length-1][colM[0].length-1];
}
rowM and colM are matrices which have 1's and 0's inside, them, I didnt put my method that makes those matrices. this algorithm works with almost everything but I have found few examples that wont work with my implementation. I think some where in my code, specially one of the if statements must not be correct. I use debug to find it but I couldnt find out why it goes wrong.
here is an example that wot work with my code:
a matrix 2*1:
[2]
[1]
this gives me a 1, but its wrong it should be 0. Can some one help me to find my problem. this is my last option to see what am doing wrong. Please help
Related
currently working on a tic tac toe game in java, and I have a checkWin() method that works correctly for 3 out of the 4 possible winning conditions. The one I am having an issue with is the right diagonal.
Code:
public boolean checkWin(String player){
int row = 0; // Holder to count number of player spots in row
int d1 = 0; // Holder to count number of player spots in right diag.
int d2 = 0; // Holder to count number of player spots in left diag.
int[] column = new int[squares[0].length]; /* Holder to count number
of player spots in column */
for(int i = 0; i < size; i++){
row = 0;
for(int j = 0; j < size; j++){
if(null == squares[i][j]){
continue;
}
if(squares[i][j].getText().equals(player)){
row++; /* If spot at [i][j] equals player, increase row */
column[j]++; /* If spot at [i][j] equals player, increase
col */
if(i == j){ /* If spot at i is equal to j, increase left
diag */
d1++;
} else if ((size - 1) == i + j){ /* If spot at i + j
equals board size - 1, increase right diag. */
d2++;
}
}
}
if(row == size){
/*
if spots in row is equal to size (otherwise, if it fills
the row, return win
*/
return true;
}
}
if(size == d1 || size == d2){
/*
if spots in either diag is equal to size, return win
*/
return true;
}
for(int i = 0; i < column.length; i++){
if(column[i] == size){
/*
if column is full of the same player character, return win
*/
return true;
}
}
/*
otherwise, return false
*/
return false;
}
The problem part is:
else if ((size - 1) == i + j){ /* If spot at i + j
equals board size - 1, increase right diag. */
d2++;
}
Reason for setting it up this way, is how a 2D Array works, so for a 3x3 board:
[00][01][02]
[10][11][12]
[20][21][22]
And with i + j = size - 1, it would evaluate 2 + 0, 1 + 1, 0 + 2 all equal 2, which is size - 1 if size = 3, but when I run the program and perform the right diagonal move, it doesn't return a true value for win.
Any suggestions for how to fix this will be greatly appreciated.
else if ((size - 1) == i + j)
^ This is only evaluated if the if condition above it is false.
if(i == j)
When i == 1 and j == 1, then i == j is true, and thus (size - 1) == i + j is not evaluated.
TLDR: Get rid of your else.
I have to modify the below method:
private final static int NUM = 6;
public void fun(int[][] grid) {
for(int row = 0; row < NUM; row++) {
for(int col = 0; col < NUM; col++) {
if((grid[row][col] % 2) == 0) {
grid[row][col] = 0;
}
}
}
}
This method checks if it's a even number and if so it replaces its value with 0. Simple.
I now need to modify it so that it directs each cell to simultaneously replace its value with its number of diagonal neighbors that hold a value of 0.
I've thought about this for about an hour and tried many different solutions, most of which resulted in an out of bounds exception. I'm stumped and don't know how to accomplish this.
If the code is right, using the integers for the grid array below, it will reproduce the numbers shown in the bottom of the picture.
What is the problem, you just need to put if statements, like there can be maximum 4 possible neighbors so check that how many are equal to 0. But this is not enough you just need to add one more condition in each of the if statements. The condition would be that the neighbor you are trying to check is possible or not.
That is: Total 4 neighbors. If the coordinates of your main cell are x, y then:
1st Diagonal neighbor: x-1, y-1
2nd Diagonal neighbor: x-1, y+1
3rd Diagonal neighbor: x+1, y+1
4th Diagonal neighbor: x+1, y-1
These are all the 4 diagonal neighbors' coordinates but the last thing you need to check is whether they go out of bonds or not. For example for checking the 1st Diagonal neighbor I would do:
if((x-1)>0 && (y-1)>0){
//and then check here if that block is = `0`
}
and for other having say x+1 or y+1 you will need to check whether or not they are less than the NUM. Like if I want to check the 3rd Diagonal Neighbor:
if((x+1)<NUM && (y+1)<NUM){
//and then check here if that block is = `0`
}
Update: What do you mean by check here if that block is = 0?
If you want to check that is the diagonal neighboring blocks are equal to 0 or not then you will need to do it in a loop. Here is how:
public void fun(int[][] grid) {
for(int row = 0; row < NUM; row++) {
for(int col = 0; col < NUM; col++) {
if((grid[row][col] % 2) == 0) {
grid[row][col] = 0;
}
}
}
for(row = 0; row< NUM; row++){
for(int col = 0; col < NUM; col++) {
int count = 0;
// To check for the 1st Diagonal Neighbor
if((row-1)>0 && (col-1)>0){
if(grid[row-1][col-1]==0){
count++;
}
}
//Similarly for 2nd, 3rd and 4th Diagonal Neighbors
//and then
grid[row][col]=count;
}
}
}
Update 2:
For say the 3rd diagonal neighbor the code block would be like this:
if((row+1)<NUM && (col+1)<NUM){
if(grid[row+1][col+1]==0){
count++;
}
}
Answer
final private static int NUM = 6;
public void fun(int[][] grid) {
for(int row = 0; row < NUM; row++) {
for(int col = 0; col < NUM; col++) {
int counter = 0;
if((row - 1) > 0 && (col - 1) > 0) {
if(grid[row - 1][col - 1] == 0) {
counter++;
}
}
if((row - 1) > 0 && (col + 1) < NUM) {
if(grid[row - 1][col + 1] == 0) {
counter++;
}
}
if((row + 1) < NUM && (col - 1) > 0) {
if(grid[row + 1][col - 1] == 0) {
counter++;
}
}
if((row + 1) < NUM && (col + 1) < NUM) {
if(grid[row + 1][col + 1] == 0) {
counter++;
}
}
grid[row][col] = counter;
}
}
}
So im writing a java program which should find the shortest way from the entrance "2" to one of the numbers "3". It can only walk on " " positions. "1" is walls.
11111121
131 1
1 1 1111
1 1 13 1
1 1 11 1
1 1 1
1 1
11111111
My starting idea is to find the entrance in the 2d array. This could be done like this:
Point entrance = new Point(0,0);
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++){
if(map[i][j] == 2){
entrance.x =i;
entrance.y =j;
}
}
I could also find the two "3" and save them in points. but im not sure how to return the rute to the closest "3". I was considering like a joystick, where I save the what direction you go, like (UP, DOWN, LEFT, RIGHT).
Then return the full list of moves from the entrance to the closests 3.
Got any suggestion or ideas how I could implement this ?
What you have here is simply a non-cannonical representation of a graph. You have each cell being a vertex in the graph and you have an edge between two neighboring cells if and only if both of them are free.
Now that you look at the problem in this way, find the entrance like you do and than do a breadth first search to find the exit.
I would try and create a graph with nodes and edges. Nodes are the junctions in the maze, and edges are the paths between junctions and entrance or exit objects. Each edge object has a 'weight'. Once you calculate the network from the double array, you can use some easy algorithm to work out the shortest route.
You need to make a counter that will increment every time the current position is " " (walk-able)
Notation " " = 0 in the matrix:
Point entrance = new Point(0,0);
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++){
if(map[i][j] == 2){
entrance.x =i;
entrance.y =j;
}
}
Point firstexit = new Point(0,0);
int steps = 0;
int i = entrance.x;
int j = entrance.y;
int lasti = 0;
int lastj = 0;
while(true){
if(map[i][j] == 3){
firstexit.x =i;
firstexit.y =j;
break ;
}
if(map[i][j] == 0){
steps++;
}
// TO-DO : check if position exists
if(map[i][j+1] == 0 && (lasti != i && lastj != j)){
lastj = j;
j++;
}else if(map[i][j-1] == 0 && (lasti != i && lastj != j)){
lastj = j;
j--;
}else if(map[i+1][j] == 0 && (lasti != i && lastj != j)){
lasti = i;
i++;
}else if(map[i-1][j] == 0 && (lasti != i && lastj != j)){
lasti = i;
i--;
}
}
What I am doing is creating a command line "game" where there is a 3x3 grid (Array) where you can move a "1" through it by typing the direction (up, down, left, right).
For example:
0 0 0
0 1 0
0 0 0
I've made it so if the 1 is on the edge of the array it is not allowed to move out of the boundaries (read: resulting in an out of index error).
I'm completely lost as whenever I try to move right, I receiving the following:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
at Logic.setMove(Logic.java:87)
at Logic.getMove(Logic.java:10)
at GridGameMain.main(GridGameMain.java:13)
Here's my code:
public class GridGameMain {
static int[][] board = new int[3][3];
public static void main(String[] args){
board[(int) (Math.random() * 2.5)][(int) (Math.random() * 2.5)] = 1;
for (int i =0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
System.out.print(" " + board[j][i]);
}
System.out.println("");
}
Logic l = new Logic();
l.getMove();
}
}
import java.util.Scanner;
public class Logic extends GridGameMain{
void getMove(){ //takes user input then calls setMove
String direction; //string to hold the direction
Scanner user_input = new Scanner(System.in);
direction = user_input.next();
Logic l = new Logic();
l.setMove(direction);
}
void setMove(String direction){ //called when user presses enter upon typing a move
Logic l = new Logic();
if(direction.equals("up")){
if(board[0][0] == 1 || board[1][0] == 1 || board[2][0] == 1 ){
System.out.println("Invalid move!");
l.getMove();
}else{
for(int a = 0; a < 3; a++){
for(int b = 0; b < 3; b++){
if(board[a][b] == 1){
board[a][b-1] = 1;
board[a][b] = 0;
break;
}
}
}
l.printBoard();
System.out.println("you moved up");
l.getMove();
}
}
if(direction.equals("down")){
if(board[0][2] == 1 || board[1][2] == 1 || board[2][2] == 1 ){
System.out.println("Invalid move!");
l.getMove();
}else{
for(int a = 0; a < 3; a++){
for(int b = 0; b < 3; b++){
if(board[a][b] == 1){
board[a][b+1] = 1;
board[a][b] = 0;
break;
}
}
}
l.printBoard();
System.out.println("you moved down");
l.getMove();
}
}
if(direction.equals("left")){
if(board[0][0] == 1 || board[0][1] == 1 || board[0][2] == 1 ){
System.out.println("Invalid move!");
l.getMove();
}else{
for(int a = 0; a < 3; a++){
for(int b = 0; b < 3; b++){
if(board[a][b] == 1){
board[a-1][b] = 1;
board[a][b] = 0;
break;
}
}
}
l.printBoard();
System.out.println("you moved left");
l.getMove();
}
}
if(direction.equals("right")){
if(board[2][0] == 1 || board[2][1] == 1 || board[2][2] == 1 ){
System.out.println("Invalid move!");
l.getMove();
}else{
for(int a = 0; a < 3; a++){
for(int b = 0; b < 3; b++){
if(board[a][b] == 1){
board[a+1][b] = 1;
board[a][b] = 0;
break;
}
}
}
l.printBoard();
System.out.println("you moved right");
l.getMove();
}
}
}
void printBoard(){
for (int i =0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
System.out.print(" " + board[j][i]);
}
System.out.println("");
}
}
}
I'm just not sure why I can't move right when I can move up, down, and left just fine. Please tell me I'm not crazy!
I think the trouble is, you check to make sure the 1 is not on the far right, and then you start shifting things right. That means that, if your 1 was on the column 0, it's moved to column 2, then at the next and last iteration, it's moved to column 3.
Also, are you sure this doesn't happen when you go down?
This doesn't happen going down because, as #Keppil says, you break out of the "rows" (relevant) loop, while going right, you break out of the columns one, which is not what you wanted.
Also, you can use tags to break out of whatever loop you want. Here's how.
The problem is that you are moving the "1" from left to right, so since you break the first for, you don't break the second one, so it keep moving the "1", until it is put outside the array (ArrayIndexOutOfBoundsException).
An example to solve it:
boolean found = false;
for(int a = 0; a < 3; a++){
for(int b = 0; b < 3; b++){
if(board[a][b] == 1){
board[a+1][b] = 1;
board[a][b] = 0;
found = true;
break;
}
if(found){
break;
}
}
}
On your move right:
for(int a = 0; a < 3; a++){
for(int b = 0; b < 3; b++){
if(board[a][b] == 1){
board[a+1][b] = 1; // what if a is 2??
board[a][b] = 0;
break;
}
}
When a is 2, accessing board[a+1][b] is accessing board[3][b]. On a 3*3 board, that's beyond bounds.
Edit: the problem is due to the fact that after you move the 1, you continue the outer loop - but without the initial bounds check. So after the 1 is moved from the central column to the right one, you try to move it again. This only happens on a right move due to the why you loop.
There are two easy solutions:
Use some flag to make sure you break out of the outer loop as well, or better yet -
Change the bounds of the fors according to what you're actually going to check. If you're not going to move a 1 that is on column #2, you can have a loop between 0 and 1. No reason to go up to 2, if you're never going to make it move from that point. Same goes to all other moves - change the appropriate bounds from < 3 to < 2.
The break; inside your for-loops seems to interrupt only the inner for-loop. after breaking the for(int b = 0; b < 3; b++){ .. }, there is no reason for the outer loop to stop.
Your loop finds the 1 at [1][1] and shifts it to the right. then it breaks the inner loop. Nevertheless it calls the inner loop for a=2, where your 1 is now. He tries to shift again.. and fails with exception.
I believe you should be getting an error when you go to the right. The reason is because when you shift one to the right, you break and then you increment a, but you do not check that it went out of bounds again. Once the 'b' loop finishes and then increments 'a' then it will register it as having a value of 1 and move it once more to the right. This keeps going until it is out of bounds. An easy way to correct your code is to just reverse your loops so the outer loop is incrementing 'b' and the inner loop is incrementing 'a'.
What I have to do here is to count the number of adjacent white blocks (in 2's) on a square board which is made up of random black(0's) and white(1's) blocks. The white blocks have to be at i+1,j || i-1,j || i,j+1 || i,j-1. Technically diagonals are not counted. I have provided an example below:
[1 0 1]
[1 1 0]
[0 1 0]
Here count == 3 (0,0)(1,0) and (1,0)(1,1) and (1,1)(2,1)
Here is my code:
public int count = 0;
boolean count(int x, int y, int[][] mat)
{
if(x<0 || y<0)
return false;
if(mat[x][y] == 0)
return false;
for(int i = x; i<mat.length; i++)
{
for(int j = y; j<mat[0].length; j++)
{
if(mat[i][j] == 1)
{
mat[i][j] = 0;
if(count(i-1,j,mat))
count++;
if(count(i,j-1,mat))
count++;
if(count(i+1,j,mat))
count++;
if(count(i,j+1,mat))
count++;
}
}
}
return true;
}
Short explanation of what I am trying to do here: I am going about finding 1's on the board and when I find one I change it to a 0 and check its up,down,left,right for a 1. This goes on till I find no adjacent 1's. What is the thing I am missing here? I kind of have a feeling I am looping unnecessarily.
here's a solution without recursion
for(int i = 0; i < mat.length; i++) {
for(int j = 0; j < mat[i].length; j++) {
if(mat[i][j] == 1) {
if(i < mat.length - 1 && mat[i+1][j] == 1) {
count++;
}
if(j < mat[i].length - 1 && mat[i][j+1] == 1) {
count++;
}
}
}
I don't think recursion is the right answer as you should only being going one step deep (to find the adjacent value). Instead just loop through the elements looking to the right and down. Don't look up or left as twain mentioned so that you don't double count matches. Then is it simply:
for (i=0; i<max; i++)
for (j=0; j<max; j++)
if (array[i][j] == 1){
if (i<max-1 && array[i+1][j] == 1) count++;
if (j<max-1 && array[i][j+1] == 1) count++;
}