Java ArrayList for Tic Tac Toe game - java

Hello I'm starting out with Java and I need a little help. I'm currently working on a tic tac toe game project and I'm stuck. At the beginning of the game I want all 9 spots on the game board to have a ' ' so that the board shows as empty, but when players select their next move I want them to use the following format: A1, A2, A3, B1, etc. How do I link my arrayList with these strings?
Example A1 would be = 0, A2 = 1.... C3=8
public static void printGameBoard() {
System.out.println(" A B C");
System.out.println(" ______________");
System.out.println(" | | | |");
System.out.println("1 |" + board.get(0) + " | " + board.get(1) + " | " + board.get(2) + " | ");
System.out.println(" |----|----|----|");
System.out.println("2 |" + board.get(3) + " | " + board.get(4) + " | " + board.get(5) + " | ");
System.out.println(" |----|----|----|");
System.out.println("3 |" + board.get(6) + " | " + board.get(7) + " | " + board.get(8) + " | ");
System.out.println(" |____|____|____|\n");
public static int gameplay() {
boardSize = 9;
board = new ArrayList();
for(int i = 0; i < boardSize; i++) {
board.add(Character.valueOf(' '));
}
return playerTurn();
}

So, you're ArrayList is a linear container, contain 0-n elements. Your grid is a two dimensional container, allowing elements to be referenced via yxx reference. You need a means to be able to convert between these.
You know that the grid is a 3x3 matrix (3 rows by 3 columns), so a little bit of simple maths will come in handy.
A references the first col, so your index would be (y - 1) + (0 * 3) (remember, Java is 0 indexed)
B references the second col, so your index would be (y - 1) + (1 * 3)
And C references the third col, so your index would be (y - 1) + (2 * 3)
Now, what you need is away to convert the letters to a number, astonishing, this is actually very simply...
String cell = "A1";
int col = cell.charAt(0) - 'A';
will return 0.
A slightly safer solution would be to remove the case entirely from your operation, something like...
int col = cell.toLowerCase().charAt(0) - 'a';
Now, you'd need to do some validation on the input to make sure the values are within range.
But what about the row??
String cell = "A1";
int col = cell.toLowerCase().charAt(0) - 'a';
int row = Integer.parseInt(cell.substring(1)) - 1;
System.out.println(row + "x" + col);
Simple :)
So, you could then put it together something like...
if (row >= 0 && row < 3 && col >= 0 && col < 3) {
int index = (row * 3) + col;
board.set(index, "x");
}
or something along those lines
And because I got my maths all turned around backwards....
String[] cols = new String[]{"A", "B", "C"};
for (int rowIndex = 1; rowIndex < 4; rowIndex++) {
for (String colValue : cols) {
String cell = colValue + rowIndex;
int col = cell.toLowerCase().charAt(0) - 'a';
int row = Integer.parseInt(cell.substring(1)) - 1;
int index = (row * 3) + col;
System.out.println("Cell = " + cell + "; index = " + index);
}
}
Outputs
Cell = A1; index = 0
Cell = B1; index = 1
Cell = C1; index = 2
Cell = A2; index = 3
Cell = B2; index = 4
Cell = C2; index = 5
Cell = A3; index = 6
Cell = B3; index = 7
Cell = C3; index = 8

try this.
for(int i = 0; i < boardSize; i++) {
board.add(Character.valueOf(i+1));
}

Related

JavaFX Connect 4 game win method

I am creating a Connect 4 game in JavaFX here is my checkWin method. The way my game works is that every cell in board has a blank circle in it and only when user chooses a column does it then have setFill(Color.RED) (or blue depending on the player). Everything is working fine except this method.
public void checkWin(int row, int column, GridPane board) {
Circle piece = ((Circle)getNodeByRowColumnIndex(row, column, board));
// Horizontal check
if (column - 3 <= 0) {
for(int i = 1; piece.equals((Circle)getNodeByRowColumnIndex(row, column + i, board)) ; i++) {
System.out.println("Checking : (" + (row) + " , " + (column + i) + ")");
if(i == 4) hasWon = true;
}
} else if (column + 3 > Columns) {
for(int i = 1; piece.equals((Circle)getNodeByRowColumnIndex(row, column - i, board)) ; i++) {
System.out.println("Checking : (" + (row) + " , " + (column - i) + ")");
if(i == 4) hasWon = true;
}
}
// Vertical check
if (row - 3 <= 0) {
for(int i = 1; piece.equals((Circle)getNodeByRowColumnIndex(row + i, column, board)) ; i++) {
System.out.println("Checking : (" + (row + i) + " , " + (column) + ")");
if(i == 4) hasWon = true;
System.out.println(i);
}
} else if (row + 3 > Rows) {
for(int i = 1; piece.equals((Circle)getNodeByRowColumnIndex(row - i, column, board)) ; i++) {
System.out.println("Checking : (" + (row - i) + " , " + (column) + ")");
if(i == 4) hasWon = true;
}
}
// Ascending diagonal check
if (row - 3 <= 0 && column - 3 <= 0) {
for(int i = 1; piece.equals((Circle)getNodeByRowColumnIndex(row + i, column + i, board)) ; i++) {
System.out.println("Checking : (" + (row + i) + " , " + (column + i) + ")");
if(i == 4) hasWon = true;
}
} else if (row + 3 > Rows && column + 3 > Columns) {
for(int i = 1; piece.equals((Circle)getNodeByRowColumnIndex(row - i, column - i, board)) ; i++) {
System.out.println("Checking : (" + (row - i) + " , " + (column - i) + ")");
if(i == 4) hasWon = true;
}
}
// Descending diagonal check
if (row + 3 > Rows && column - 3 <= 0) {
for(int i = 1; piece.equals((Circle)getNodeByRowColumnIndex(row - i, column + i, board)); i++) {
System.out.println("Checking : (" + (row - i) + " , " + (column + i) + ")");
if(i == 4) hasWon = true;
}
} else if (row - 3 <= 0 && column + 3 > Columns) {
for(int i = 1; piece.equals((Circle)getNodeByRowColumnIndex(row + i, column - i, board)); i++) {
System.out.println("Checking : (" + (row + i) + " , " + (column - i) + ")");
if(i == 4) hasWon = true;
}
}
}
First, and in general, try to separate your data from your representation. So keep some array or other data structure where you only store if there is a stone and what. Don't store circles
Second. The actual problem is closely related and shows why you should do so:
You only want to compare the colors of the circles. Not the circles themselves.
(I'm only guessing that these are JavaFX Circles because you don't show the complete code...)
Because every circle has a radius and a center. And every center is most probable different your equals method will always return false.
So compare only colors. Or better: separate data from representation.

Need to fix for loop

I'm taking online classes, which makes it harder to get help, which is why I'm here. This week's lecture is on nested-loops. They are confusing the heck out of me. I am currently stuck on this problem.
Given numRows and numColumns, print a list of all seats in a theater. Rows are numbered, columns lettered, as in 1A or 3E. Print a space after each seat, including after the last. Use separate print statements to print the row and column. Ex: numRows = 2 and numColumns = 3 prints:
1A 1B 1C 2A 2B 2C
>
I have tried many possible solutions which have yield many wrong results. This is my current solution
int numRows;
int numColumns;
int currentRow;
int currentColumn;
char currentColumnLetter;
numRows = scnr.nextInt();
numColumns = scnr.nextInt();
currentColumnLetter = 'A';
for (currentRow = 1; currentRow <= numRows; currentRow++)
{
for (currentColumn = 1; currentColumn < numColumns; currentColumn++)
{
System.out.print(currentRow);
System.out.print(currentColumnLetter + " ");
}
if( currentColumn == numColumns)
{
currentColumnLetter++;
}
}
The code yields this result
1A 1A 2B 2B
The desired result is
1A 1B 2A 2B
I've been going at it for two days and its making me seriously frustrated. Thanks in advance for any help.
You're pretty close.
However, you're not handling the column name correctly. As each row starts, you need to go back to A, and increment by one with each column:
for (currentRow = 1; currentRow <= numRows; currentRow++) {
currentColumnLetter = 'A'; //Starting a new row, reset the column to `A`
for (currentColumn = 1; currentColumn < numColumns; currentColumn++){
System.out.print(currentRow);
System.out.print(currentColumnLetter + " ");
currentColumnLetter++;
}
}
It's also pretty weird to be using 1-based indexing. Indexing in Java (as well as many other languages) should be started at 0. Your column loop doesn't perform enough iterations as a result - if you set numColumns to 2, you'll only print a single column.
It would be more idiomatic to write the loops like this:
for (currentRow = 0; currentRow < numRows; currentRow++) {
currentColumnLetter = 'A';
for (currentColumn = 0; currentColumn < numColumns; currentColumn++) {
System.out.print(currentRow + 1);
System.out.print(currentColumnLetter + " ");
currentColumnLetter++;
}
}
Yo, the thing is deeper than one might think. I always found these loop over character examples nasty, i got it at my last job interview. So here we go:
If the exercise would be this way: rows got from 1..n, columns for 1..n, output should be "1/1, 1/2...3/1, 3/2...", it would be straight forward, wouldn't it?
public void seatnumbersNumbersOnly() {
int numRows = 3;
int numColumns = 3;
for (int currentRow = 1; currentRow <= numRows; currentRow++) {
for (int currentColumn = 1; currentColumn < numColumns; currentColumn++) {
System.out.print(currentColumn + "/" + currentRow + " ");
}
}
}
But the task is different, they want letters for the columns. Let's brute force it on the same basis.
public void seatnumbersNumbersMappedAgain() {
String[] seatLetters = new String []{"A", "B", "C"}; // so many letters as there are columns. Note: array index is 0-based
int numRows = 3;
int numColumns = 3;
for (int currentRow = 1; currentRow <= numRows; currentRow++) {
for (int currentColumn = 1; currentColumn < numColumns; currentColumn++) {
// seatLetters[i] is a string "s", not a char 'c', so everything's fine
System.out.print(seatLetters[currentColumn - 1] + currentRow + " "); // -1: seatLetters indexing is zero based
}
}
}
But then: in Java char and byte are interchangeable as long as you're in the ascii-range, you can assign a char literal to a byte and the other way round.
#Test
public void charByteEquivalence() {
// check out http://www.asciitable.com/
char ca = 'A';
byte ba = 0x41;
assertEquals(ca, ba);
ca = 0x41;
ba = 'A';
assertEquals(ca, ba);
}
This means, you also can use the char variable directly for looping. But watch out, building the output string becomes messy, since you have to watch what gets "+"ed with what. You want String/char values for columns and numbers for rows. A "string" + char/byte/int ... becomes a string. char + int becomes and int? a byte? a char? Just certainly not a String. Disclosure: I trial-and-errored the string concatenation, and it becomes an int. Some examples for implicit type conversions are here, the official reference is here.
public void seatnumbersChar() {
int numRows = 3;
int numColumns = 3;
char firstColumnLetter = 'A';
for (int currentRow = 1; currentRow <= numRows; currentRow++) {
for (char currentColumn = firstColumnLetter; currentColumn < firstColumnLetter + numColumns; currentColumn++) {
// at this point you have to watch out currentColumn + currentRow + " " will get evaluated left to right
// currentRow is an int
// currentColumn becomes an int when "+"ed with currentRow
// so currentRow + currentColumn would add two numbers instead of concatenating 2 strings, therefore
// an explicit conversion to string is needed for one of the arguments
System.out.print(currentColumn + String.valueOf(currentRow) + " ");
}
}
}
The same example going the byte route, similar mess with string concatenation, but not quite the same.
public void seatnumbersByte() {
int numRows = 3;
int numColumns = 3;
byte firstColumnLetter = 'A';
for (int currentRow = 1; currentRow <= numRows; currentRow++) {
for (byte currentColumn = firstColumnLetter; currentColumn < firstColumnLetter + numColumns; currentColumn++) {
// same case other trick: (currentRow + " ") forces the result to be a string due to the + " "
// currentColumn here is declared as byte, when concatenated to a string the numeric representation would be taken (wtf...?)
// therefore a cast to char is needed "(char) currentColumn"
// what's left now ? (currentRow + " ") is a string
// "(char) currentColumn" is a char
// a char "+" a string is a string
System.out.print((char) currentColumn + (currentRow + " "));
}
}
}
Hope I got my revenge on that last interview. Have gotten the job anyway ;)
You need to increment the currentColumnLetter inside the inner loop. Remember for each row, you need to traverse each column. That's the reason you are nesting loops, right?
Try this:
for (currentRow = 1; currentRow <= numRows; currentRow++) {
currentColumnLetter = 'A';
for (currentColumn = 1; currentColumn <= numColumns; currentColumn++) {
System.out.print(currentRow);
System.out.print(currentColumnLetter + " ");
currentColumnLetter++
}
}
You do not need this condition in the outer loop:
if( currentColumn == numColumns)
{
currentColumnLetter++;
}

Print a diamond shape with Java

I want to print a grid shape on the output console in Eclipse.
Basically I took an integer from user that is the number of stars in a single border of the grid.
Here the code I have up to now:
public class PrintDiamond {
public static void main(String[] args) {
System.out.print("Enter the number: ");
Scanner scan = new Scanner(System.in);
int num = scan.nextInt();
num--;
for (int i = num; i > 0; --i) {
//Insert spaces in order to center the diamond
for (int n = 0; n < i; ++n) {
System.out.print(" ");
}
System.out.print(" *");
for (int n = i; n < num; ++n) {
System.out.print(" + ");
System.out.print(" ");
}//Ending bracket of nested for-loop
System.out.println();
}//Ending bracket of for loop
//Print out a diamond shape based on user input
for (int i = 0; i <= num; ++i) {//<= to print the last asterisk
//Insert spaces in order to center the diamond
for (int n = 0; n < i; ++n) {
System.out.print(" ");
}
System.out.print(" *");
for (int n = i; n < num; ++n) {
System.out.print(" + ");
System.out.print(" ");
}//Ending bracket of nested for-loop
System.out.println();
}//Ending bracket of for loop
}
}
and the output is (for int. 6):
*
* +
* + +
* + + +
* + + + +
* + + + + +
* + + + +
* + + +
* + +
* +
*
Here is the code:
public static void main(String[] args) {
System.out.print("Enter the number: ");
Scanner scan = new Scanner(System.in);
int num = scan.nextInt();
final char[][] diamond = makeDiamond(num);
for (int i = 0; i < diamond.length; i++) {
for (int j = 0; j < diamond[i].length; j++) {
System.out.print(diamond[i][j]);
}
System.out.println();
}
}
public static char[][] makeDiamond(int n) {
int width = 1 + 4 * (n - 1);
int height = 1 + 2 * (n - 1);
char[][] out = new char[height][width];
int x0 = 2 * (n - 1);
int y0 = n - 1;
for (int i = 0; i < width; i += 2) {
// Top borders
int y1 = Math.abs(y0 - i / 2);
out[y1][i] = '*';
// Bottom borders
int y2 = height - Math.abs(i / 2 - y0) - 1;
out[y2][i] = '*';
if ((x0 - i) % 4 == 0) {
// Plus signs
for (int j = y1 + 1; j < y2; j++) {
out[j][i] = '+';
}
}
}
return out;
}
Some hints for your solution:
Create a method for printing a "diamond row" for a given row width and a given total width of the diamond.
Create a tool method for printing a given number of spaces.
Your main method should have two simple loops: One for the upper, one for the lower half.
The magic is in the method of printing a single diamond row for the given two parameters w and n.
This is always a good approach - reduce your complex problem to a problem with lesser complexity - in this case, by creating methods and using these e.g. in loops.
In your method for printing a single diamond row, you will need to check if you are in an "odd" or "even" row.
Ok, this looks like a school asignment, so I won't write any code.
First you need to understand and write, in pseudo-code or just plain English, what you want to do:
Instructions on how to draw the grid.
How many lines should I print?
How long is each line?
How do I know if I have to print a + or not?
General steps of your program.
Read size of the grid, N.
If N < 1, ask again (or exit program).
If N = 1 or greater, print the grid.
Detailed sub-steps of your program.
Print the grid
Loop for number of lines.
Create empty array/buffer/list/string with correct length for current line.
...
Because right now, it seems like you haven't figured out any of that. And if that's the case, then your problem has nothing to do with Java but rather with basic programming knowledge, which you won't get if we just code the algorith for you.
Two nested for loops from -n to n and one if else statement. The zero point is in the center of a diamond, and the boundary is obtained when:
Math.abs(i) + Math.abs(j) == n
Try it online!
public static void main(String[] args) {
printDiamond(0);
printDiamond(2);
printDiamond(5);
}
static void printDiamond(int n) {
System.out.println("n=" + n);
for (int i = -n; i <= n; i++) {
for (int j = -n; j <= n; j++)
if (Math.abs(i) + Math.abs(j) == n)
System.out.print("* ");
else if (Math.abs(i) + Math.abs(j) < n && j % 2 == 0)
System.out.print("+ ");
else
System.out.print(" ");
System.out.println();
}
}
Output (combined):
n=0
n=2
n=5
*
* * + * * + * * + * *
* * + * * + * * + + + * * + + + * * + + + + + * * + + + * * + + + * * + * * + * *
See also: Print an ASCII diamond of asterisks

start searching in a 2 dimensional array from a sertent element java

I am trying to write a code that searches through a 2 dimensional array and tries to find the closest element to "x" that is empty, if "x" has any data in. The elements' coordinates are given from another method. For example "x" is (3,2). If there's no empty element then the code must continue searching in the whole array.
public void find(int row, int column) {
for (int i = row - 1; i < row + 2; i++) {
for (int k = column - 1; k < column + 2; k++) {
if (this.arr[i][k].equals(" ")) {
System.out.println(i + "," + k + " is empty.");
return;
}
}
}
}
I am looking foreword for any helpful suggestions on how to code this method.
Thank you.
Under assumptions
this is matrix (each row has equal num of columns)
method arguments are valid: 0 <= row < numOfRows and 0 <= column < numOfColumns
this code will do search of 2 dimensional array around specified element in the way you've described.
Note that this is not clock direction round search around specified element, but search from top left corner to bottom right corner (from top to bottom and from left to right)
public void find(int row, int column) {
int distance = 1;
int numOfRows = arr.length;
int numOfColumns = 0;
if (arr.length > 0) {
numOfColumns = arr[0].length;
}
int maxDistance = Math.max(numOfRows, numOfColumns);
for (distance = 1; distance < maxDistance; distance ++) {
for (int i = Math.max(row - distance, 0); i <= Math.min(row + distance, numOfRows - 1); i++) {
if (Math.abs(i - row) == distance) {
// Check row
for (int k = Math.max(column - distance, 0); k <= Math.min(column + distance, numOfColumns - 1); k++) {
if (arr[i][k] == null || arr[i][k].trim().isEmpty()) {
System.out.println((i+1) + "," + (k+1) + " is empty.");
return;
} else {
System.out.println((i+1) + "," + (k+1) + " is not empty.");
}
}
} else {
// Check only edge elements
int k = column - distance;
if (k >= 0) {
if (arr[i][k] == null || arr[i][k].trim().isEmpty()) {
System.out.println((i+1) + "," + (k+1) + " is empty.");
return;
} else {
System.out.println((i+1) + "," + (k+1) + " is not empty.");
}
}
k = column + distance;
if (k < numOfColumns) {
if (arr[i][k] == null || arr[i][k].trim().isEmpty()) {
System.out.println((i+1) + "," + (k+1) + " is empty.");
return;
} else {
System.out.println((i+1) + "," + (k+1) + " is not empty.");
}
}
}
}
}
System.out.println("No empty elements");
}

Minesweeper implementation output seems ok but fails UVa Judge tests

The Input
The input will consist of an arbitrary number of fields. The first line of each field contains two integers n and m (0 < n,m <= 100) which stands for the number of lines and columns of the field respectively. The next n lines contains exactly m characters and represent the field. Each safe square is represented by an "." character (without the quotes) and each mine square is represented by an "*" character (also without the quotes). The first field line where n = m = 0 represents the end of input and should not be processed.
The Output
For each field, you must print the following message in a line alone:
Field #x:
Where x stands for the number of the field (starting from 1). The next n lines should contain the field with the "." characters replaced by the number of adjacent mines to that square. There must be an empty line between field outputs.
Sample Input
4 4
*...
....
.*..
....
3 5
**...
.....
.*...
0 0
Sample Output
Field #1:
*100
2210
1*10
1110
Field #2:
**100
33200
1*100
I get the correct output for the given inputs.
import java.util.*;
public class Main{
public static void main(String[] args) {
//field size
int n, m;
//string to hold a row of a minesweeper board
String line;
//array to hold all the minesweeper boards entered
ArrayList<char[][]> allBoards = new ArrayList<char[][]>();
Scanner scan = new Scanner(System.in);
//get the field size
n = scan.nextInt();
m = scan.nextInt();
//keep going until n=0 and m=0
while ((n+m)!=0) {
//create the minesweeper board
//the field sizes are 2 spaces bigger to prevent error checking
//at the edges of the minesweeper board
char[][] board = new char[n + 2][m + 2];
//fill the appropriate spaces with the mines '*' and blank spaces '.'
for (int row = 1; row < board.length - 1; row++) {
line = scan.next();
for (int col = 1; col < board[0].length - 1; col++) {
board[row][col] = line.charAt(col - 1);
}
}
//add the current minesweeper board to the array
allBoards.add(board);
//get new field size
n = scan.nextInt();
m = scan.nextInt();
}
printResults(allBoards);
}
//function to find out how many mines are around a certain position
//check all positions surrounding the current one.
public static int getMines(char[][] board, int row, int col) {
int nMines = 0;
if (board[row - 1][col - 1] == '*') {
nMines++;
}
if (board[row - 1][col] == '*') {
nMines++;
}
if (board[row - 1][col + 1] == '*') {
nMines++;
}
if (board[row][col - 1] == '*') {
nMines++;
}
if (board[row][col + 1] == '*') {
nMines++;
}
if (board[row + 1][col - 1] == '*') {
nMines++;
}
if (board[row + 1][col] == '*') {
nMines++;
}
if (board[row + 1][col + 1] == '*') {
nMines++;
}
return nMines;
}
//print the results
private static void printResults(ArrayList<char[][]> allBoards) {
for (int i = 1; i <= allBoards.size(); i++) {
System.out.println("Field #" + i + ":");
for (int row = 1; row < allBoards.get(i - 1).length - 1; row++) {
for (int col = 1; col < allBoards.get(i - 1)[0].length - 1; col++) {
if (allBoards.get(i - 1)[row][col] != '*') {
System.out.print(getMines(allBoards.get(i - 1), row, col));
} else {
System.out.print("*");
}
}
System.out.println();
}
System.out.println();
}
}
}

Categories

Resources