inserting an x in between a predrawn base - java

I want to initialize an x between the first | | and move it as users input left, right, down, up. I think I just mostly need help with putting the x there in the first place. Can probably figure out the rest based on the answer.
public class dimensions {
public static void main(String[] args) {
System.out.println("Select the size of the world widthxheight: ");
Scanner sc = new Scanner(System. in );
String input = sc.nextLine();
String[] parts = input.split("x");
String part1 = parts[0];
String part2 = parts[1];
int sx = 1;
int sy = 0;
int width = Integer.parseInt(part1);
int height = Integer.parseInt(part2);
for (int h = height - 1; h >= 0; h--) {
for (int w = width - 1; w >= 0; w--) {
if (w == width - 1) {
System.out.print("| |");
} else {
System.out.print(" |");
}
}
System.out.print("\n");
}
}
}

You can add an X in the first field with the following code:
[...]
int width = Integer.parseInt(part1);
int height = Integer.parseInt(part2);
int playerPosX = 0;
int playerPosY = 0;
for (int h = 0; h < height; h++) {
for (int w = 0; w < width; w++) {
String temp = " |";
if (w == 0) {
temp = "| |";
}
if (playerPosX == w && playerPosY == h) {
temp = temp.replace(' ', 'X');
}
System.out.print(temp);
}
System.out.println();
}
}
}
You can also specify the position of the player, respectively the position of the X with the variables playerPosX and playerPosY.
BUT, moving the player without drawing the whole map after each move is not possible, because System.out is technically a stream and it's not possible to manipulate data which was already sent to the stream.
I would suggest that you create your own window in which you add a text field and print the map on that.
Tutorial for creating Swing windows.
Tutorial for creating text areas.

Related

Why the dynamic programming solution only works for squre board?

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...

search a given word into a letter puzzle diagonally

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();
}

How to add a class that prints to the console on to a JPanel

I have this class that randomly creates rooms next to each other, and prints brackets (which represent the rooms) to the console. But I wanted to know how to add something like that to a JPanel for a GUI. Here is the room generator class:
public class Rooms {
static final int width = 15, height = 10;
static final int rooms = 19;
static boolean[][] room = new boolean[width][height];
static int neighborCount(int x, int y) {
int n = 0;
if (x > 0 && room[x-1][y]) n++;
if (y > 0 && room[x][y-1]) n++;
if (x < width-1 && room[x+1][y]) n++;
if (y < height-1 && room[x][y+1]) n++;
return n;
}
public void Rooms() {
room[width/2][height/2] = true;
Random r = new Random();
int x, y, nc;
for (int i = 0; i < rooms; i++) {
while (true) {
x = r.nextInt(width);
y = r.nextInt(height);
nc = neighborCount(x, y);
if (!room[x][y] && nc == 1) break;
}
room[x][y] = true;
}
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++)
System.out.print(room[x][y] ? "[]" : " ");
System.out.print();
}
}
}
Thanks for the help!
You probably want to use java.awt.Graphics. It lets you draw primitive shapes like lines, rectangles, circles, etc. This might get you started. Section 2 also covers how to draw on a JPanel.

replacing a string in an array and keeping it in memory?

so im having problems polishing up my program. this program is supposed to create a 1D array with a user input. then it creates a box of 'O's like this..
N = 4
OOOO
OOOO
OOOO
OOOO
the user inputs coordinates based on the box and the 'O' is changed to an 'X'.
the program is supposed to repeat itself after the coordinates are selected while remembering the position of X and including it in the next loop.
i tried implementing a while loop but it seems that code just loops over the Array without remembering the last position of X.
how could i change the code so it does what i need it to do?
public static void makeArray(int M) {
String input = "";
boolean repeat = false;
int N = InputNumber(input);
String[] Board = new String[N];
M = (int) Math.sqrt(N);
String A = "O";
String B = "X";
System.out.println("Printing " + (M) + " x " + (M) + " board...");
System.out.println("Done.");
System.out.println();
while (!repeat) {
int X = Xvalue(M);
int Y = Yvalue(M);
int C = convertIndex(X, Y, M);
System.out.println("Marking location " + X + "," + Y + ")");
for (int i = 0; i < (Board.length); i++) {
{
Board[i] = A;
if ((i % M == 0)) {
System.out.println();
}
if (i == C) {
Board[i] = Board[i].replace(A, B);
}
if (i == C && C == -1) {
repeat = true;
}
}
System.out.print(Board[i]);
}
System.out.println();
}
}
public static int convertIndex(int x, int y, int N) {
int valX = (x - 1) * N;
int valY = y;
int targetIndex = valX + valY;
return (targetIndex - 1);
}
public static int Xvalue(int M) {
boolean repeat = false;
int X = 0;
while (!repeat) {
System.out.print("Please enter the X-coordinate: ");
String InputX = new Scanner(System.in).nextLine();
X = Integer.parseInt(InputX);
if (X > M) {
System.out.println();
System.out.println("Error, please enter a valid X Coordinate...");
repeat = false;
} else {
repeat = true;
}
}
return X;
}
public static int Yvalue(int M) {
boolean repeat = false;
int Y = 0;
while (!repeat) {
System.out.println();
System.out.print("Please enter the Y-coordinate: ");
String InputY = new Scanner(System.in).nextLine();
Y = Integer.parseInt(InputY);
if (Y > M) {
System.out.println("Error, please enter a valid Y Coordinate...");
repeat = false;
} else {
repeat = true;
}
}
return Y;
}
The trouble with you loop is that it defines every element in you your array before it prints them:
while (!repeat) {
//...
for (int i = 0; i < (Board.length); i++) {
{
Board[i] = A; //Makes each element "O"
//...
if (i == C) { //Makes only the current cooridinate "X"
Board[i] = Board[i].replace(A, B);
}
//...
}
System.out.print(Board[i]);
}
}
To fix it so that old X's are retained, you need to remove assignment Board[i] = A;. But you'll still need to initialize your board, or else you'll have null strings. So you need to add something before the loop like:
String[] Board = new String[N];
M = (int) Math.sqrt(N);
String A = "O";
String B = "X";
//initialize board
for (int i = 0; i < Board.length; i++)
Board[i] = A;
Try using a char[][] instead of a String[]. Then you can just plugin the coordinates the user inputs (e.g. board[x][y] = B). This better represents what you're showing the user as well.
This saves you from having to loop through your String[] and then finding the right character to change. Remember, Strings are immutable, so you'd have to reassign the entire string after replacing the right character. With the char[][] you simply assign 'X' to the right coordinates.
EDIT:
Since a single array is required, you should be able to do the following (instead of looping):
board[x] = board[x].substring(0, y) + A + board[x].substring(y + 1);

Find inside of rectangle using outside points

I have a csv file with numbers(i.e. 0, 2, 34, 0, 2,...) all on one line. I am using a scanner to read them from a file. The file represents an in-game map which is quite large. I know the width and height of this map. While scanning this file, I only want to capture the brown rectangle(part of the game's map) in the image below. I am scanning the file and wanting to put the values from the csv file into a short[].
int mapWidth = 8;
int mapHeight = 6;
int rectangleWidth = 5;
int rectangleHeight = 3;
short[] tmpMap = new short[rectangleWidth * rectangleHeight];
Scanner scanner = new Scanner(new File(path));
scanner.useDelimiter(", ");
I also am lucky enough to know the 4 corners of the rectangle that I need. The dark brown squares(four corners of the rectangle I need to capture) can be represented as:
int topLeftIndex = 17;
int topRightIndex = 21;
int bottomLeftIndex = 33;
int bottomRightIndex = 37;
I know that during my scan method I can check to see if I am within bounds of the rectangle and the blue highlighted boxes with the following:
if (count >= topLeftIndex && count <= bottomRightIndex){
//within or outside (east and west) of rectangle
I am having trouble thinking of the logic for identifying and not storing the blue highlighted squares.
The size of this rectangle, size of the overall map, and dark brown point are just numeric examples and will change, but I will always know them. Can anyone help me out?
Here is what I have so far:
private static short[] scanMapFile(String path, int topLeftIndex,
int topRightIndex, int bottomLeftIndex, int bottomRightIndex)
throws FileNotFoundException {
Scanner scanner = new Scanner(new File(path));
scanner.useDelimiter(", ");
short[] tmpMap = new short[mapWidth * mapHeight];
int count = 0;
int arrayIndex = 0;
while(scanner.hasNext()){
if (count >= topLeftIndex && count <= bottomRightIndex){
//within or outside (east and west) of rectangle
if (count == bottomRightIndex){ //last entry
tmpMap[arrayIndex] = Short.parseShort(scanner.next());
break;
} else { //not last entry
tmpMap[arrayIndex] = Short.parseShort(scanner.next());
arrayIndex++;
}
} else {
scanner.next(); //have to advance scanner
}
count++;
}
scanner.close();
return tmpMap;
}
NOTE: this is not school work :) Any help would be tremendously appreciated.
You could to it like this:
public boolean isInside(int n) {
if(n >= topLeftIndex && n <= bottomRightIndex) {
if(n % mapWidth >= topLeftIndex % mapWidth
&& mapWidth % mapWidth <= bottomRightIndex % mapWidth) {
return true;
}
}
return false;
}
This first checks, what you have already checked and then checks, whether the "column" is right as well.
This works always if you know the top-left index, the bottom-right index, and the map width.
Here is what I did to capture all of the sides:
int topLeftChunkIndex = characterX - (chunkWidth / 2) + ((characterY - (chunkHeight / 2)) * mapWidth);
int topRightChunkIndex = topLeftChunkIndex + chunkWidth - 1;
//int bottomRightChunkIndex = characterX + (chunkWidth / 2) + ((characterY + (chunkHeight / 2)) * mapWidth);
//int bottomLeftChunkIndex = bottomRightChunkIndex - chunkWidth + 1;
int[] leftChunkSides = new int[chunkHeight];
int[] rightChunkSides = new int[chunkHeight];
for (int i = 0; i < chunkHeight; i++){
leftChunkSides[i] = topLeftChunkIndex + (mapWidth * i);
rightChunkSides[i] = topRightChunkIndex + (mapWidth * i);
}
And here is how I checked later:
public static boolean isInsideMapChunk(int n, int[] leftChunkSides, int[] rightChunkSides) {
for (int i = 0; i < chunkHeight; i++){
if (n >= leftChunkSides[i] && n <= rightChunkSides[i]){
return true;
}
}
return false;
}

Categories