I am doing a basic Snake Game in Java Processing. It is supposed to turn clockwise whne the user presses L or D, and when the user presses the A or J key the snake should turn counter-clockwise. The keys should not directly control the snake's direction. They should control how the snake turns.
DEMO
Look at DEMO Question 2
QUESTION
image
My Code
final int ROWS=20, COLS=15; //The number of rows and columns of squares
final int SQ_SIZE=40; //The size of each square in pixels
final int[] X_DIRECTIONS = {0, -1, 0, 1}; //X change for down, left, up, right
final int[] Y_DIRECTIONS = {1, 0, -1, 0}; //Y change for down, left, up, right
int startingLength = 5, currentLength = 0, snakeSpeed = 30, currentDirection = 0;
int [] x = new int[ROWS*COLS];
int [] y = new int[ROWS*COLS];
void setup(){
background(#ff9900);
size(600,800); //MUST be COLS*SQ_SIZE, ROWS*SQ_SIZE
resetSnake();
}
void draw(){
if(frameCount % snakeSpeed == 0){
background(#ff9900);
drawCircles(x, y, currentLength, #32CD32);
moveSnake(X_DIRECTIONS[currentDirection], Y_DIRECTIONS[currentDirection]);
//moveSnake(X_DIRECTIONS[currentDirection], 0);
}
}
void resetSnake(){
currentLength = startingLength;
fillArray(y, currentLength, ROWS/2, -1);
fillArray(x, currentLength, COLS/2, 0);
drawCircles(x, y, currentLength, #32CD32);
}
void moveSnake(int addX, int addY){
if(addX != 0){
fillArray(x, currentLength, x[0] + addX, addX);
}
fillArray(y, currentLength, y[0] + addY, -addY);
}
void keyPressed(){
int newDir = keyCode == DOWN ? 0:(keyCode == UP ? 2:(keyCode == RIGHT ? 3:(keyCode == LEFT ? 1:-1)));
if(newDir != -1) currentDirection = newDir;
}
void drawCircles(int[]x, int[]y, int n, int colour){
//Draw circles here
for(int i = 0; i < n; i++){
fill(colour);
circle(x[i]*SQ_SIZE, y[i]*SQ_SIZE, SQ_SIZE);
}
}
void fillArray(int[] a, int n, int start, int delta){
int index = 0;
if(delta > 0){
for(int i = start; i < start + n; i+=delta){
a[index++] = i;
}
}else if(delta < 0){
for(int i = start; i > start-n; i+=delta){
a[index++] = i;
}
}else{
for(int i = 0; i < n; i++){
a[index++] = start;
}
}
}
Since you have the directions in an array, you can "rotate" through them like this:
void keyPressed(){
if (keyCode == 76 //the code for 'l'
|| keyCode == 68) { //the code for 'd'
currentDirection++;
if(currentDirection > 3) { //make sure currentDirection is not bigger than the array length
currentDirection = 0;
}
}
if (keyCode == 65 //the code for 'a'
|| keyCode == 74) { //the code for 'j'
currentDirection--;
if (currentDirection < 0) { //make sure currentDirection is not smaller than 0
currentDirection = 3;
}
}
}
Related
I have a question about my homework in scratching my head-on.
So I need to build a program that counts the number of areas of true value (near to each other) in the 2D array.
{0,1,0,0}
{1,0,0,1}
{1,1,0,1}
{1,0,0,1}
So the program needs to return 3 because there 3 places with trues.
If there are no true then to return 0.
The program needs to recursive and without loops.
Thanks in advance to the ones that will help me solve this one. I didn't even have any idea how to start it.
Ok, you do a dfs to record the cells you went and you can have a boolean[][] to record the cells you went. Then you just loop through the grid to see where you have not gone. If you did not go there yet, go there and also perform a dfs on nearby cells, but anyway, a code would be more clear.
public static int[][] grid;
public static boolean[][] went;
public static int r, c;
public static void dfs(int x, int y) {
if (x < 0 || x >= r || y < 0 || y >= c) {//out of the grid
return;
}
if (went[x][y]) {//I went here
return;
}
went[x][y] = true;
if (grid[x][y] == 0) {//It's false here so don't go
return;
}
dfs(x - 1, y);
dfs(x + 1, y);
dfs(x, y - 1);
dfs(x, y + 1);
}
public static void main(String[] args) throws IOException {
BufferedReader input =
new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(input.readLine());
//input reading
r = Integer.parseInt(st.nextToken());
c = Integer.parseInt(st.nextToken());
grid = new int[r][c];
went = new boolean[r][c];
for (int i = 0; i < r; i++) {
st = new StringTokenizer(input.readLine());
for (int j = 0; j < c; j++) {
grid[i][j] = Integer.parseInt(st.nextToken());
}
}
//end of input reading
int cnt = 0;//number of areas
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
// If I have not went have and the value
// must be true so I would perform a dfs
// (since I only care about the value of 1s)
if (!went[i][j] && grid[i][j] == 1) {
cnt++;//add to our counter
dfs(i, j);//have not went here
}
}
}
System.out.println(cnt);
}
This solution uses the only recursion. No loops.
public static void main(String... args) {
System.out.println(countTrueAreas(new int[][] {
{ 0, 1, 0, 0 },
{ 1, 0, 0, 1 },
{ 1, 1, 0, 1 },
{ 1, 0, 0, 1 } })); // 3
}
public static int countTrueAreas(int[][] grid) {
return countTrueAreas(grid, 0, 0, 10) - 10;
}
private static int countTrueAreas(int[][] grid, int row, int col, int num) {
if (row == grid.length)
return num;
if (col == grid[row].length) {
if (++row == grid.length)
return num;
col = 0;
}
if (grid[row][col] == 1)
dfs(grid, row, col, num++);
return countTrueAreas(grid, row, col + 1, num);
}
private static void dfs(int[][] grid, int row, int col, int num) {
if (row < 0 || row >= grid.length)
return;
if (col < 0 || col >= grid[row].length)
return;
if (grid[row][col] != 1)
return;
grid[row][col] = num;
dfs(grid, row, col - 1, num);
dfs(grid, row, col + 1, num);
dfs(grid, row - 1, col, num);
dfs(grid, row + 1, col, num);
}
The problem is:
Given exact k steps, how many ways to move a point from start point to destination? Point can move for eight directions(horizontally, vertically, diagonally, anti-diagonally).
I solved the problem through DP, but it works only for square board, not for rectangle board. I mean if dim[0]!=dim[1] in the code, it will run into an error result.
Here I can provide test case:
Test case 1
dim = {5,6},start = {0,2},end = {2,2},steps = 4;
result is 50(expected: 105)
Test case 2
dim = {5,5},int[] start = {0,2},end = {2,2},steps = 4;
result is 105(expected: 105)
Here is the code:
private static int[][] dir = {{0,1},{1,0},{1,1},{1,-1},{0,-1},{-1,0},{-1,-1},{-1,1}};
//DP
/*
#param dim, a tuple (width, height) of the dimensions of the board
#param start, a tuple (x, y) of the king's starting coordinate
#param target, a tuple (x, y) of the king's destination
*/
public static int countPaths2(int[] dim, int[] start, int[] des, int steps){
if(dim[0] == 0 || dim[1] == 0) return 0;
int[][][] dp = new int[dim[0]*dim[1]][dim[1]*dim[0]][steps+1];
for(int step = 0; step<=steps;step++){
for(int i = 0; i< dim[0]*dim[1];i++){
for(int j = 0; j< dim[0]*dim[1];j++){
if(step == 0 && i == j){
dp[i][j][step] = 1;
}
if(step >= 1){
for(int k =0; k< dir.length;k++){
int row = i / dim[0];
int col = i % dim[1];
if(row + dir[k][0] >= 0 && row + dir[k][0]< dim[0] && col + dir[k][1]>=0 && col + dir[k][1]< dim[1]){
int adj = (row + dir[k][0])*dim[0] + col + dir[k][1];
dp[i][j][step] += dp[adj][j][step-1];
}
}
}
}
}
}
int startPos = start[0]*dim[0] + start[1];
int targetPos = des[0]*dim[0] + des[1];
return dp[startPos][targetPos][steps];
}
public static void main(String[] args){
int[] dim = {5,5}; // can just use to square;
int[] start = {0,2};
int[] end = {2,2};
int steps = 7;
System.out.println(countPaths2(dim, start,end, steps));
}
How could I make it work for any kind of board?
The culprit is:
int row = i / dim[0];
int col = i % dim[1]; // <- this should have been dim[0]
in the div/mod pattern you are supposed to divide and modulo by the same number...
I have a two-dimensional array filled with random letters. I have words to find in that array.
I have written a toString method that uses:
startX : The start X position of the String to be found
startY : The start Y position of the String to be found
endX : The end X position of the String to be found
endY : The end Y position of the String to be found
The code that I provide works horizontally and vertically but does not work for diagonals. How can I print words which are placed in the array diagonally?
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
if (startX == endX) {
if (startY < endY) {
for (int i = startY; i <= endY; i++)
sb.append(i).append("x").append(startY).append(" ");
} else {
for (int i = endY; i <= startY; i++)
sb.append(i).append("x").append(startY).append(" ");
}
}
if (startY == endY) {
if (startX < endX) {
for (int i = startX; i <= endX; i++)
sb.append(i).append("x").append(startY).append(" ");
} else
for (int i = endX; i <= startX; i++)
sb.append(i).append("x").append(startY).append(" ");
}
if (startX > endX && startY > endY) {
int i = startX;
int j = startY;
while (i >= endX)
sb.append(i--).append("x").append(j--).append(" ");
} else if (startX > endX && startY < endY) {
int i = startX;
int j = startY;
while (i >= endX)
sb.append(i--).append("x").append(j++).append(" ");
} else if (startX < endX && startY > endY) {
int i = startX;
int j = startY;
while (i >= endX)
sb.append(i++).append("x").append(j--).append(" ");
} else if (startX < endX && startY < endY) {
int i = startX;
int j = startY;
while (i >= endX)
sb.append(i++).append("x").append(j++).append(" ");
}
return sb.toString();
}
I assume that what you are looking for is a way to find a word in a letter puzzle.
In such a case, I suggest you to store the puzzle on a 2D array and the word to find in a String. Then you need to check all the positions of the array that have the same character than the begining character of the String you are looking for (in the code I provide: findWord). Once you find a match, you need to check the rest of the characters of the string (in the code I provide: checkDirections). If the rest of the characters match then you have found the string, otherwise you need to check for the other directions or for the next appearance of the first letter of the string.
Next I provide the code:
package letterPuzzle;
import java.util.Random;
public class LetterPuzzle {
private static final String ALPHABET = "abcdefghijklmnopqrstuvwxyz";
private static final int[] DIRECTIONS_X = new int[] { 0, 0, 1, -1, 1, 1, -1, -1 };
private static final int[] DIRECTIONS_Y = new int[] { 1, -1, 0, 0, 1, -1, 1, -1 };
private static int N;
private static char[][] puzzle;
private static void initializePuzzle() {
Random r = new Random();
puzzle = new char[N][N];
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
puzzle[i][j] = ALPHABET.charAt(r.nextInt(ALPHABET.length()));
}
}
// Add the JAVA word in a location
if (N < 6) {
System.out.println("[ERRRO] Example needs N >= 6");
System.exit(1);
}
puzzle[2][3] = 'j';
puzzle[3][3] = 'a';
puzzle[4][3] = 'v';
puzzle[5][3] = 'a';
}
private static void printPuzzle() {
System.out.println("[DEBUG] Puzzle");
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
System.out.print(puzzle[i][j] + " ");
}
System.out.println("");
}
System.out.println("[DEBUG] End Puzzle");
}
private static boolean findWord(String word) {
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
// We check all the matrix but only try to match the word if the first letter matches
if (puzzle[i][j] == word.charAt(0)) {
if (checkDirections(i, j, word)) {
return true;
}
}
}
}
return false;
}
private static boolean checkDirections(int initX, int initY, String word) {
System.out.println("Searching " + word + " from (" + initX + ", " + initY + ")");
// Checks the different directions from (initX, initY) position
for (int dirIndex = 0; dirIndex < DIRECTIONS_X.length; ++dirIndex) {
System.out.println(" - Searching direction " + dirIndex);
boolean wordMatches = true;
// Checks all the characters in an specific direction
for (int charIndex = 0; charIndex < word.length() && wordMatches; ++charIndex) {
int x = initX + DIRECTIONS_X[dirIndex] * charIndex;
int y = initY + DIRECTIONS_Y[dirIndex] * charIndex;
System.out.println(" -- Checking position (" + x + ", " + y + ")");
if (x < 0 || y < 0 || x >= N || y >= N || puzzle[x][y] != word.charAt(charIndex)) {
System.out.println(" -- Not match");
wordMatches = false;
} else {
System.out.println(" -- Partial match");
}
}
// If the word matches we stop, otherwise we check other directions
if (wordMatches) {
return true;
}
}
return false;
}
public static void main(String[] args) {
// Check args
if (args.length != 2) {
System.err.println("[ERROR] Invalid usage");
System.err.println("[ERROR] main <puzzleSize> <wordToSearch>");
}
// Get args
N = Integer.valueOf(args[0]);
String word = args[1];
// Initialize puzzle (randomly)
initializePuzzle();
printPuzzle();
// Search word
boolean isPresent = findWord(word);
if (isPresent) {
System.out.println("Word found");
} else {
System.out.println("Word NOT found");
}
}
}
Notice that:
The puzzle matrix is randomly initialized and I hardcoded the word 'java' on the 2,3 -> 5,3 positions (this is just for the example but you should initialize the puzzle from the command line or from a file).
The ALPHABET variable is used only for the random generation.
The directions are stored on two 1D arrays to make the 8 directions programatically but you can unroll for the sake of clarity.
It is probably not best efficient code in terms of performance since you will double check lots of positions if the first character of the string appears several times. However it is still a feasible and easy solution.
If :
each word of yours is in a particular row and doesn't overflows to next row and
all words are consecutive
then you can do something like this:
#Override
public String toString()
{
StringBuilder string = new StringBuilder();
for(int c = startY; c<=endY; c++) {
string.append(startX).append("x").append(c).append(", ");
}
return string.toString();
}
trying to create a Conways Game of life, but apparently the shapes are not like they have to be. Perhaps someone can help me find the issue.
For example the glider :
- X - - - -
- - X X - -
- X X - - -
- - - - - -
becomes this
- - X X - -
- X - - - -
X X X - - -
- X X X - -
but should be like this :
- - X - - -
- - - X - -
- X X X - -
- - - - - -
And my code looks like this
public Frame(int x, int y) {
setWidth(x);
setHeight(y);
if (x<1)
frame = null;
else if (y<1)
frame = null;
else {
frame = new String [x][y];
for (int i=0; i<frame.length; i++) {
for (int j=0; j<frame[i].length; j++) {
frame [i][j] = DEAD;
}
}
} // else
} // construktor
public Integer getNeighbourCount(int x, int y) {
Frame cell = new Frame(getHeight(), getWidth());
int counter = 0;
if(frame[x][y].equals(ALIVE))
{
counter = counter - 1;
}
for(int i=x-1; i<=x+1;i++){
if(i<frame.length && i>0){
for(int j=y-1; j<=y+1;j++){
if(j<frame[i].length && j>0){
if (frame[i][j]==ALIVE) {
counter++;
}
}
}
}
}
return counter;
}
public Frame nextFrame() {
// Returns next frame
Frame cell = new Frame(getWidth(), getHeight());
//cell.frame = new String[getWidth()][getHeight()];
for(int i = 0; i < frame.length; i++){
for(int j =0; j <frame[i].length;j++){
int n = getNeighbourCount(i,j);
if(cell.frame[i][j]==null) {
cell.frame[i][j] = DEAD;
}
if (isAlive(i, j) && n < 2 || n > 3) {
cell.frame[i][j] = DEAD;
}
if (isAlive(i, j) && n == 3 || n == 2){
cell.frame[i][j] = ALIVE;
}
if(!isAlive(i, j) && n == 3) {
cell.frame[i][j] = ALIVE;
}
if(isAlive(i, j) && n > 3){
cell.frame[i][j] = DEAD;
}
frame[i][j] = cell.frame[i][j];
}
}
cell.toString();
return cell;
}
`
Full code http://pastebin.com/LMwz724H
Here's a solution that works - using an enum for each cell and getting the i/j and x/y stuff right (I think). It certainly generates the correct first iteration:
static class GameOfLife {
final int w;
final int h;
State[][] frame;
enum State {
Dead, Alive;
}
public GameOfLife(int w, int h) {
this.w = w;
this.h = h;
frame = new State[h][w];
}
public void alive(int x, int y) {
frame[y][x] = State.Alive;
}
public void tick() {
frame = nextGeneration();
}
private int surroundingPopulation(int x, int y) {
int pop = 0;
for (int i = y - 1; i <= y + 1; i++) {
for (int j = x - 1; j <= x + 1; j++) {
// On frame - vertically.
if ((i >= 0 && i < h)
// On frame horizontally.
&& (j >= 0 && j < w)
// Alive
&& (frame[i][j] == State.Alive)
// Not the center.
&& (i != y || j != x)) {
pop += 1;
}
}
}
return pop;
}
private State[][] nextGeneration() {
State[][] next = new State[h][w];
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int pop = surroundingPopulation(x, y);
// Any live cell
if (frame[y][x] == State.Alive) {
if (pop < 2) {
// ... with fewer than two live neighbours dies, as if caused by under-population.
next[y][x] = State.Dead;
} else if (pop > 3) {
// ... with more than three live neighbours dies, as if by overcrowding.
next[y][x] = State.Dead;
} else {
// ... with two or three live neighbours lives on to the next generation.
next[y][x] = State.Alive;
}
} else {
// Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
if (pop == 3) {
next[y][x] = State.Alive;
}
}
}
}
return next;
}
#Override
public String toString() {
StringBuilder s = new StringBuilder();
for (State[] row : frame) {
for (State c : row) {
s.append(c == State.Alive ? "X" : " ");
}
s.append("\r\n");
}
return s.toString();
}
}
public void test() {
GameOfLife g = new GameOfLife(6, 6);
g.alive(1, 0);
g.alive(2, 1);
g.alive(3, 1);
g.alive(1, 2);
g.alive(2, 2);
System.out.println("Before:\r\n" + g);
g.tick();
System.out.println("After:\r\n" + g);
}
I believe the problem is that you are copying the new value as you iterate through the loop. This means neighbours are using the value from the next tick rather than the current one.
You can fix this by waiting until you calculated all new values in your new frame: cell.frame and then iterate through the frame again and copy from cell.frame to frame.
An alternative (better in my view) is to have away of cloning a frame during construction. Then you could change your nextFrame method to create a clone of frame and use the clone to set the new values in frame.
You are changing the DEAD and ALIVE frames while you iterate through the grid. You need to store the coordinates which should die or become alive and perform that afterwards.
Store the coordinates in two ArrayLists (dead, alive). The first and second position is the x and y axis, and change those coordinates according to whether they should become alive or not.
Here's a snippet from a simple test I wrote a while back. As others have mentioned, don't change values on an active board while still reading them. Instead, clone the board and make changes to the copy while reading the current board.
Another problem I bumped into a few times was iterating over y, then x for each y, but referring to x,y when accessing a point. It feels back to front :)
// Rules:
// 1) Any live cell with fewer than two live neighbours dies, as if caused by under-population.
// 2) Any live cell with two or three live neighbours lives on to the next generation.
// 3) Any live cell with more than three live neighbours dies, as if by overcrowding.
// 4) Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
void mutateGrid() {
// Copy existing grid into the next generation's grid
boolean[][] mutatedGrid = new boolean[gridXWidth][gridYHeight];
for (int i = 0; i < gridXWidth; i++) {
System.arraycopy(grid[i], 0, mutatedGrid[i], 0, gridYHeight);
}
// Start mutation rules
for (int y = 0; y < gridYHeight; y++) {
for (int x = 0; x < gridXWidth; x++) {
int liveNeighbours = countLiveNeighbours(x,y);
if (liveNeighbours < 2 || liveNeighbours > 3) {
mutatedGrid[x][y] = false;
}
else if (liveNeighbours == 3) {
mutatedGrid[x][y] = true;
}
}
}
grid = mutatedGrid;
}
int countLiveNeighbours(int x, int y) {
int count = 0;
for (int j = y-1; j <= y+1; j++) {
for (int i = x-1; i <= x+1; i++) {
if (i < 0 || j < 0 || i >= gridXWidth || j >= gridYHeight){
continue;
}
if (grid[i][j]) {
count++;
}
}
}
count -= grid[x][y]?1:0; // remove self from count
return count;
}
This question already has answers here:
How do I do a deep copy of a 2d array in Java?
(7 answers)
Closed 8 years ago.
So I am trying to make an algorithm for finding full paths in NxN grid. For example in 1x1 grid there is 1 possible path, in 2x2 grid there is 1, in 3x3 there is 2 and in 4x4 there is 8. The idea is to find scenarios where we can fill every spot of the grid by moving.
I have made a recursive function for the job and here is the code:
public static int getRoutesHelp(int[][] table, int x, int y)
{
if(x > table.length-1 || x < 0 || y < 0 || y > table.length-1)
return 0;
if(table[x][y] == 1)
return 0;
table[x][y] = 1;
if(isDeadEnd(table, x, y))
{
if(isTableFull(table))
return 1;
}
else
{
int a = getRoutesHelp(table, x-1, y);
int d = getRoutesHelp(table, x, y+1);
int b = getRoutesHelp(table, x+1, y);
int c = getRoutesHelp(table, x, y-1);
return a+b+c+d;
}
return 0;
}
public static int getRoutes(int size)
{
int[][] table = new int[size][size];
// init table
for(int i = 0; i < size; i++)
{
for(int a = 0; a < size; a++)
{
table[i][a] = 0;
}
}
return getRoutesHelp(table, 0 ,0);
}
So basically I start from 0.0 and start moving to all possible directions and by repeating this I get the amount of successful routes. The problem is that after the assignment of int d the original table is somehow filled with 1 but it should be empty as far as I understand because java passes a copy of the table right? I've been fighting with this for like 4 hours and can't really find the problem so any help is appreciated. Empty slots in table are marked with 0 and filled slots with 1.
EDIT: I managed to fix the issue I had with the copying and now my other problem is that with 5x5 grid my algorithm returns 52 routes and it should be 86. So it works with 4x4 grid okay, but once I move further it breaks.
Added the isDeadEnd function here
public static boolean isDeadEnd(int[][] table, int x, int y)
{
int toCheck[] = new int[4];
toCheck[0] = x-1; // left
toCheck[1] = y-1; // top
toCheck[2] = x+1; // right
toCheck[3] = y+1; // bottom
int valuesOfDirections[] = new int[4]; // left, top, right, bottom
for(int i = 0; i < 4; i++)
{
int tarkastettava = toCheck[i];
if(tarkastettava > table.length-1 || tarkastettava < 0)
{
valuesOfDirections[i] = 1;
}
else
{
if(i == 0 || i == 2)
{
valuesOfDirections[i] = table[tarkastettava][y];
}
else
{
valuesOfDirections[i] = table[x][tarkastettava];
}
}
}
for(int i = 0; i < 4; i++)
{
if(valuesOfDirections[i] == 0)
{
return false;
}
}
return true;
}
Come to think of it, you probably can do a simple backtrack here:
table[x][y] = 1;
if(isDeadEnd(table, x, y)) {
if(isTableFull(table))
return 1;
}
table[x][y] = 0;
}
And later:
int res = a + b + c + d;
if (res == 0) {
// backtrack here too
table[x][y] = 0;
}
return res;