Hi could anybody help me understand this particular piece of code from this Langton's Ant sketch.
antLoc = new int[]{rows/2,columns/2};
I don't exactly understand what is actually happening here, here is the rest of the code for context. (originally from here http://www.openprocessing.org/visuals/?visualID=13653)
boolean[][] state;
int[] antLoc;
int antDirection;
int squareSize = 5;
int columns, rows;
color bgCol = color(0,128,128);
color antCol = color (255,0,0);
color sqCol = color(128,128,128);
void setup(){
size(800,600);
background(bgCol);
columns = width/squareSize;
rows = height/squareSize;
state = new boolean[rows][columns];
for(int j = 0; j < rows; j++){
for(int i = 0; i < columns; i++){
state[j][i] = false;
}
}
antLoc = new int[]{rows/2,columns/2};
antDirection = 1;
}
void drawScene(){
fill(sqCol);
for(int j = 0; j < rows; j++){
for(int i = 0; i < columns; i++){
if(state[j][i]){
rect(i*squareSize,j*squareSize,squareSize,squareSize);
}
}
}
fill(antCol);
rect(antLoc[1]*squareSize,antLoc[0]*squareSize,squareSize,squareSize);
}
void turnLeft(){
if (antDirection > 1){
antDirection--;
} else{
antDirection = 4;
}
}
void turnRight(){
if (antDirection < 4){
antDirection++;
} else {
antDirection = 1;
}
}
void moveForward(){
if (antDirection == 1){
antLoc[0]--;
}
if (antDirection == 2){
antLoc[1]++;
}
if (antDirection == 3){
antLoc[0]++;
}
if (antDirection == 4){
antLoc[1]--;
}
}
void updateScene(){
moveForward();
if (state[antLoc[0]][antLoc[1]] == false){
state[antLoc[0]][antLoc[1]] = true;
turnRight();
} else {
state[antLoc[0]][antLoc[1]] = false;
turnLeft();
}
}
void draw(){
background(bgCol);
drawScene();
for(int i = 0; i < 10; i++){
updateScene();
}
}
The line you mention:
antLoc = new int[]{rows/2,columns/2};
is broadly similar to:
antLoc = new int[2];
antLoc[0] = rows / 2;
antLoc[1] = columns / 2;
It's just syntactic shorthand, for convenience.
Your code creates a new array of int with length 2, and initialises the elements with the given expressions. It is equivalent to:
antLoc = new int[2];
antLoc[0] = rows/2;
antLoc[1] = columns/2;
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed last month.
Improve this question
I have been working on this java code for the doomsday-fuel problem which deals with the absorbing markov chains. It has passed every test except for test four. Is there any particular type of input I may have missed while testing my code? I have only about 12 hours left. I have tested four one dimensional arrays and am curious as to if this test failure is somehow a precision error or something else.
Context:
Making fuel for the LAMBCHOP's reactor core is a tricky process because of the exotic matter involved. It starts as raw ore, then during processing, begins randomly changing between forms, eventually reaching a stable form. There may be multiple stable forms that a sample could ultimately reach, not all of which are useful as fuel.
Commander Lambda has tasked you to help the scientists increase fuel creation efficiency by predicting the end state of a given ore sample. You have carefully studied the different structures that the ore can take and which transitions it undergoes. It appears that, while random, the probability of each structure transforming is fixed. That is, each time the ore is in 1 state, it has the same probabilities of entering the next state (which might be the same state). You have recorded the observed transitions in a matrix. The others in the lab have hypothesized more exotic forms that the ore can become, but you haven't seen all of them.
Write a function solution(m) that takes an array of array of nonnegative ints representing how many times that state has gone to the next state and return an array of ints for each terminal state giving the exact probabilities of each terminal state, represented as the numerator for each state, then the denominator for all of them at the end and in simplest form. The matrix is at most 10 by 10. It is guaranteed that no matter which state the ore is in, there is a path from that state to a terminal state. That is, the processing will always eventually end in a stable state. The ore starts in state 0. The denominator will fit within a signed 32-bit integer during the calculation, as long as the fraction is simplified regularly.
public static int[] returnFractionPair(double x) {
double tolerance = 1.0E-14;//Handles the extent of precision used
double numerator=1;//Kept as one because initially the decimal may be greater than zero
double numeratorStorage=0;
double denominator=0;
double denominatorStorage=1;//prevents division by zero
double decimal = x;
double comparison = 0;
do {
double flooredDecimal = (double)(int)decimal;//Floors decimal
double aux = numerator;//Sets auxilary to be the numerator
numerator =(flooredDecimal*numerator)+numeratorStorage;
numeratorStorage = aux;
aux = denominator;
denominator = (flooredDecimal*denominator)+denominatorStorage;
denominatorStorage = aux;
decimal = 1/(decimal-flooredDecimal);
comparison = x-(numerator/denominator);
} while( returnAbs(comparison) > (x*tolerance) );//Tests if the difference between the initial decimal and this new numerator/denominator is greater than that of x multiplied by the level of tolerance it has
int[] res = new int[]{(int)numerator, (int)denominator};
return res;
}
public static double returnAbs(double value){
if(value < 0){
value *= -1;
}
return value;
}
public static int getLCD(int[][] fractions){
int num = 0;
int den = 1;
int lcd = 1;
for(int i = 0; i < fractions.length; i++){
lcd *= fractions[i][den];
}
for(int i = 2; i < lcd; i++){
boolean foundLeastCommon = true;
for(int j = 0; j < fractions.length; j++){
if( (double)( i%fractions[j][den] ) != 0){
foundLeastCommon = false;
}
}
if(foundLeastCommon == true){
lcd = i;
return lcd;
}
}
return lcd;
}
public static double[] returnRowSums(int[][] matrix){
//Assume all values in matrix are positive
double[] sumsOfEachRow = new double[matrix.length];
for(int i = 0; i < matrix.length; i++){
for(int j = 0; j < matrix.length; j++){
sumsOfEachRow[i] += matrix[i][j];
}
}
return sumsOfEachRow;
}
public static double returnMatrixCellSum(double[] row, double[] column){//Assume row size == column size.
if(row.length != column.length){
return 0;
}
double sum = 0;
for(int i = 0; i < row.length; i++){
sum += (column[i] * row[i]);
}
return sum;
}
public static int[] returnRearrangedIndices(double[] sumsOfEachRow){
int[] indicesOfRearrangedMatrix = new int[sumsOfEachRow.length];
int indicesIndex = 0;
for(int i = 0; i < sumsOfEachRow.length; i++){
if(sumsOfEachRow[i] <= 1){
indicesOfRearrangedMatrix[indicesIndex] = i;
indicesIndex++;
}//TerminalStates first
}
for(int i = 0; i < sumsOfEachRow.length; i++){
if(sumsOfEachRow[i] > 1){
indicesOfRearrangedMatrix[indicesIndex] = i;
indicesIndex++;
}
}
return indicesOfRearrangedMatrix;
}
public static double[][] subtractMatrix(double[][] matrix1, double[][] matrix2){//assumes matrices are of same dimensions
double[][] matrix3 = new double[matrix1.length][matrix1.length];
for(int i = 0; i < matrix1.length;i++){
for(int j = 0; j < matrix1[i].length; j++){
matrix3[i][j] = matrix1[i][j] - matrix2[i][j];
}
}
return matrix3;
}
public static double[][] rotateMatrix(double[][] matrix){
double[][] rotatedMatrix = new double[matrix[0].length][matrix.length];
for(int i = 0; i < rotatedMatrix.length;i++){
for(int j = 0; j < rotatedMatrix[0].length; j++){
rotatedMatrix[i][j] = matrix[j][i];
}
}
return rotatedMatrix;
}
public static double[][] getRemainingValues(double[][] matrix, int rowIgnored, int columnIgnored){
double[][] newMatrix = new double[matrix.length-1][matrix.length-1];
int iC = 0;
int iR = 0;
for(int k = 0; k < matrix.length; k++){
if(k != rowIgnored){
iR = 0;
for(int j = 0; j < matrix[k].length;j++){
if(j != columnIgnored){
newMatrix[iC][iR] = matrix[k][j];
iR++;
}
}
iC++;
}
}
return newMatrix;
}
public static double getDeterminant(double[][] matrix){
//uses top rows only
double determinant = 0;
if(matrix.length == 1 && matrix[0].length == 1){
return matrix[0][0];
}
boolean negative = false;
double[][] newMatrix = new double[matrix.length-1][matrix.length-1];
for(int i = 0; i < matrix.length; i++){
newMatrix = getRemainingValues(matrix, 0, i);
if(negative == false){
determinant += matrix[0][i]*getDeterminant(newMatrix);
negative = true;
}else{
determinant -= matrix[0][i]*getDeterminant(newMatrix);
negative = false;
}
//System.out.println(determinant);
}
return determinant;
}
public static double[][] getMinorMatrix(double[][] matrix){
double[][] newMatrix = new double[matrix.length][matrix.length];
double[][] remainderMatrix;
if(matrix.length-1 != 0){
remainderMatrix = new double[matrix.length-1][matrix.length-1];
}else{
remainderMatrix = new double[matrix.length][matrix.length];
}
for(int i = 0; i < newMatrix.length;i++){
for(int j = 0; j < newMatrix.length;j++){
remainderMatrix = getRemainingValues(matrix, i, j);
newMatrix[i][j] = getDeterminant(remainderMatrix) + 0.0;//Prevent -0.0 float values
}
}
return newMatrix;
}
public static double[][] divideMatrixByScalar(double[][] matrix, double scalar){
double[][] newMatrix = new double[matrix.length][matrix[0].length];
newMatrix = matrix;
for(int i = 0; i < matrix.length; i++){
for(int j = 0; j < matrix[i].length;j++){
newMatrix[i][j] /= scalar;
}
}
return newMatrix;
}
public static double[][] invertMatrix(double[][] matrix){
double[][] minorMatrix = new double[matrix.length][matrix.length];
if(minorMatrix.length == 2){
minorMatrix = matrix;
double temp = minorMatrix[0][0];
minorMatrix[0][0] = minorMatrix[1][1];
minorMatrix[1][1] = temp;
minorMatrix[0][1] *= -1;
minorMatrix[0][1] += 0;
minorMatrix[1][0] *= -1;
minorMatrix[1][0] += 0;
for(int i = 0; i < minorMatrix.length; i++){
for(int j = 0; j < minorMatrix[i].length; j++){
System.out.print(minorMatrix[i][j] + " ");
}
System.out.print("\n");
}
}else{
minorMatrix = getMinorMatrix(matrix);
System.out.println("Getting minorMatrix");
for(int i = 0; i < minorMatrix.length; i++){
for(int j = 0; j < minorMatrix[i].length; j++){
System.out.print(minorMatrix[i][j] + " ");
}
System.out.print("\n");
}
boolean isNegative = false;
System.out.println("Getting adjoint of minorMatrix");//Not doing things correctly
for(int i = 0; i < minorMatrix.length;i++){
for(int j = 0; j < minorMatrix[i].length;j++){
if(isNegative == true){
minorMatrix[i][j] *= -1;
minorMatrix[i][j] += 0;
isNegative = false;
}else{
isNegative = true;
}
System.out.print(minorMatrix[i][j] + " ");
}
if(minorMatrix[i].length % 2 == 0){
if(isNegative == true){
isNegative = false;
}else{
isNegative = true;
}
}
System.out.print("\n");
}
minorMatrix = rotateMatrix(minorMatrix);//rotates the minorMatrix
}
double determinant = getDeterminant(matrix);
System.out.println(determinant);
if(determinant != 0){
minorMatrix = divideMatrixByScalar(minorMatrix, determinant);
System.out.println("Result");
for(int i = 0; i < minorMatrix.length; i++){
for(int j = 0; j < minorMatrix[i].length; j++){
System.out.print(minorMatrix[i][j] + " ");
}
System.out.print("\n");
}
return minorMatrix;//Inverse is good
}else{
return matrix;
}
}
public static double[][] returnUnabsorbedToUnabsorbed(double[][] matrix, int terminalStates){//Assumes matrix layers go from absorbed to unabsorbed
double[][] unabsorbedToUnabsorbed = new double[matrix.length-terminalStates][matrix.length-terminalStates];
int uIndex = 0;
int uuIndex = 0;
for(int i = terminalStates; i < matrix.length;i++){
uuIndex = 0;
for(int j = terminalStates; j < matrix.length;j++){
unabsorbedToUnabsorbed[uIndex][uuIndex] = matrix[i][j];
uuIndex++;
}
uIndex++;
}
return unabsorbedToUnabsorbed;
}
public static double[][] returnUnabsorbedToAbsorbed(double[][] matrix, int terminalStates){//Assumes matrix layers go from absorbed to unabsorbed
double[][] unabsorbedToAbsorbed = new double[matrix.length-terminalStates][terminalStates];
int uIndex = 0;
int uuIndex = 0;
for(int i = terminalStates; i < matrix.length;i++){
uuIndex = 0;
for(int j = 0; j < terminalStates;j++){
unabsorbedToAbsorbed[uIndex][uuIndex] = matrix[i][j];
uuIndex++;
}
uIndex++;
}
return unabsorbedToAbsorbed;
}
public static double[][] getFundamental(double[][] matrix){
double[][] modifiedMatrix = new double[matrix.length][matrix[0].length];
modifiedMatrix = matrix;
double[][] identity = new double[matrix.length][matrix.length];
for(int i = 0; i < identity.length; i++){
for(int j = 0;j < identity[i].length;j++){
if(i == j){
identity[i][j] = 1;
}else{
identity[i][j] = 0;
}
}
}
modifiedMatrix = subtractMatrix(identity, modifiedMatrix);//Modified matrix is returning properly
/*System.out.println("Getting matrix to be inverted");
for(int i = 0; i < modifiedMatrix.length; i++){
for(int j = 0; j < modifiedMatrix[i].length; j++){
System.out.print(modifiedMatrix[i][j] + " ");
}
System.out.print("\n");
}*/
modifiedMatrix = invertMatrix(modifiedMatrix);//Problem here(?)
return modifiedMatrix;
}
public static double[][] multiplyMatrix(double[][] matrix1, double[][] matrix2){//Assume all rows are equal.
double[][] result = new double[matrix1.length][matrix2[0].length];
double[][] rotatedM2 = new double[matrix2[0].length][matrix2.length];
rotatedM2 = rotateMatrix(matrix2);
for(int i = 0; i < result.length;i++){
for(int j = 0; j < result[i].length; j++){
result[i][j] = returnMatrixCellSum(matrix1[i], rotatedM2[j]);
//RotateMatrix does not increase matrix sums by how it should be
}
}
return result;
}
public static int[] algorithm(int[][] matrix, int startingPoint){
if(matrix.length == 0){
return new int[]{0, 1};
}
if(matrix.length == 1){
int[] ans = new int[matrix.length+1];
for(int i = 0; i < ans.length;i++){
ans[i] = 1;
}
for(int i = 0; i < ans.length; i++){
System.out.println(ans[i]);
}
return ans;
}
double[] sumsOfEachRow = new double[matrix.length];
sumsOfEachRow = returnRowSums(matrix);
double[][] probMatrix = new double[matrix.length][matrix.length];
int terminalStates = 0;//Number of terminal states
for(int i = 0; i < probMatrix.length; i++){
for(int j = 0; j < probMatrix[i].length; j++){
if(sumsOfEachRow[i] != 0){
probMatrix[i][j] = (double)matrix[i][j];
probMatrix[i][j] /= sumsOfEachRow[i];
}else{
probMatrix[i][j] = 0;
}
}
}
boolean startingIsTerminal = false;
for(int i = 0; i < probMatrix.length;i++){
boolean foundOne = false;
for(int j = 0; j < probMatrix[i].length;j++){
if(probMatrix[i][j] == 1 && i == j){
terminalStates++;
foundOne = true;
if(i == startingPoint){
startingIsTerminal = true;
}
}
}
if(foundOne == false){
if(sumsOfEachRow[i] == 0){
terminalStates++;
}
}
}
if( (sumsOfEachRow[startingPoint] == 0) || startingIsTerminal == true){
int[] ans = new int[terminalStates+1];
for(int i = 0; i < terminalStates;i++){
if(i != startingPoint){
ans[i] = 0;
}else{
ans[i] = 1;
}
}
ans[terminalStates] = 1;
for(int i = 0; i < ans.length; i++){
System.out.println(ans[i]);
}
return ans;
}
int[] indicesOfRearrangedMatrix = new int[probMatrix.length];
indicesOfRearrangedMatrix = returnRearrangedIndices(sumsOfEachRow);
double[][] rearranged = new double[probMatrix.length][probMatrix[0].length];
for(int i = 0; i < matrix.length; i++){
for(int j = 0; j < matrix[i].length; j++){
rearranged[i][j] = probMatrix[indicesOfRearrangedMatrix[i]][indicesOfRearrangedMatrix[j]];
System.out.print(rearranged[i][j] + " ");
}
System.out.print("\n");
}//Get rearranged matrix divided
System.out.println("Matrix rearranged");
double[][] unabsorbedToUnabsorbed = new double[probMatrix.length-terminalStates][probMatrix.length-terminalStates];
unabsorbedToUnabsorbed = returnUnabsorbedToUnabsorbed(rearranged, terminalStates);//Get Unabsorbed Matrix
for(int i = 0; i < unabsorbedToUnabsorbed.length; i++){
for(int j = 0; j < unabsorbedToUnabsorbed[i].length; j++){
System.out.print(unabsorbedToUnabsorbed[i][j] + " ");
}
System.out.print("\n");
}
System.out.println("unabsorbedToUnabsorbed");
double[][] unabsorbedToAbsorbed = new double[probMatrix.length-terminalStates][terminalStates];
unabsorbedToAbsorbed = returnUnabsorbedToAbsorbed(rearranged, terminalStates);
for(int i = 0; i < unabsorbedToAbsorbed.length; i++){
for(int j = 0; j < unabsorbedToAbsorbed[i].length; j++){
System.out.print(unabsorbedToAbsorbed[i][j] + " ");
}
System.out.print("\n");
}
System.out.println("unabsorbedToAbsorbed");
double[][] fundamental = new double[unabsorbedToUnabsorbed.length][unabsorbedToUnabsorbed.length];
fundamental = getFundamental(unabsorbedToUnabsorbed);//Gets fundamental
double[][] probResult = multiplyMatrix(fundamental, unabsorbedToAbsorbed);
System.out.println("ProbResult got");
for(int i = 0; i < probResult.length; i++){
for(int j = 0; j < probResult[i].length; j++){
System.out.print(probResult[i][j] + " ");
}
System.out.print("\n");
}
int[][] fractionPairs = new int[terminalStates][2];
for(int i = 0; i < probResult[startingPoint].length; i++){
fractionPairs[i] = returnFractionPair(probResult[startingPoint][i]);
}
int lcd = getLCD(fractionPairs);
int[] ans = new int[terminalStates+1];
int num = 0;
int den = 1;
for(int i = 0; i < fractionPairs.length;++i){
int newNumerator = (lcd/fractionPairs[i][den]) * fractionPairs[i][num];
ans[i] = newNumerator;
}
ans[ans.length-1] = lcd;
for(int i = 0; i < ans.length; i++){
System.out.println(ans[i]);
}
return ans;
}
public static int[] solution(int[][] m) {
return algorithm(m, 0);
}
}
I have no idea what the problem is .I printed the moveVal all the time it prints 0 and its going in a horizontal order.
The I have been editing a changing the code by using Google and YouTube but, there was no good
static class Move {
int row, col;
}
private boolean equals(JButton a, JButton b, JButton c){
return a.getText().equals(b.getText()) && b.getText().equals(c.getText()) && !a.getText().equals("");
}
private boolean isGameOver() {
for (int i = 0; i < 3; i++) {
if (equals(board[i][0], board[i][1], board[i][2])) {
return true;
}
}
for (int i = 0; i < 3; i++) {
if (equals(board[0][i], board[1][i], board[2][i])) {
return true;
}
}
if (equals(board[0][0], board[1][1], board[2][2])) {
return true;
}
else if (equals(board[2][0], board[1][1], board[0][2])) {
return true;
}
int openSpots = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (board[i][j].getText().equals("")) {
openSpots++;
}
}
}
return openSpots == 0;
}
private int evaluate(JButton[][] b) {
for (int row = 0; row < 3; row++)
{
if (b[row][0] == b[row][1] &&
b[row][1] == b[row][2])
{
if (b[row][0].getText().equals(ai))
return 20;
else if (b[row][0].getText().equals(human))
return -10;
}
}
for (int col = 0; col < 3; col++)
{
if (b[0][col] == b[1][col] &&
b[1][col] == b[2][col])
{
if (b[0][col].getText().equals(ai))
return 20;
else if (b[0][col].getText().equals(human))
return -10;
}
}
if (b[0][0] == b[1][1] && b[1][1] == b[2][2])
{
if (b[0][0].getText().equals(ai))
return 20;
else if (b[0][0].getText().equals(human))
return -10;
}
if (b[0][2] == b[1][1] && b[1][1] == b[2][0])
{
if (b[0][2].getText().equals(ai))
return 20;
else if (b[0][2].getText().equals(human))
return -10;
}
return 0;
}
private int minimax(JButton[][] position, int depth, boolean isMax) {
if (isGameOver() || depth == 0){
return evaluate(position);
}
else if (isMax)
{
int best = -1000000000;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (position[i][j].getText().equals(""))
{
position[i][j].setText(ai);
JButton[][] position1 = position;
best = Math.max(best, minimax(position1, depth - 1, false));
System.out.println(best);
position[i][j].setText("");
}
}
}
return best;
}
else
{
int best1 = 1000000000;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (position[i][j].getText().equals(""))
{
position[i][j].setText(human);
JButton[][] position1 = position;
best1 = Math.min(best1, minimax(position1, depth - 1, true));
position[i][j].setText("");
}
}
}
return best1;
}
}
private void BestMove(JButton[][] board) {
int bestVal = -1000000000;
Move bestMove = new Move();
bestMove.row = -1;
bestMove.col = -1;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (board[i][j].getText().equals(""))
{
board[i][j].setText(ai);
int moveVal = minimax(board, 3, false);
board[i][j].setText("");
if (moveVal > bestVal)
{
bestVal = moveVal;
bestMove.row = i;
bestMove.col = j;
}
}
}
}
board[bestMove.row][bestMove.col].setText(ai);
playersTurn = true;
CheckWinner();
}
Any ideas & please help is needed
past 3 days I have been debugging I know this code is not the best in fact this code might be the worst you have ever seen.
Blockquote
You have only 3 possible evaluations:
20, if the AI wins
-10, if the human wins
0, in all other cases
As you only look at 4 turns (ai, human, ai, human), it's impossible to find a winning position, so the evaluation is always 0.
There is no obvious issue with your implementation of the minimax, however your evaluation function is too simple.
You can, for example:
Give more points to playing in a position that creates a row of 2
Give more points to playing in a position that creates multiple rows of 2
Give less points to a position that is already blocked
However, there is only so much you can do. This game is obviously solved, and a perfect player can always get a draw playing either sides.
The program below ask the user how many mines he wants to see on the field and then display the field with mines.
In next step I need to calculate how many mines are around each empty cell. And I know that I
need to check 8 cells if the cell is in the middle, 5 cells if the cell is in the side, and 3
cells if the cell is in the corner. If there are from 1 to 8 mines around the cell, I need to
output the number of mines instead of the symbol representing an empty cell.
import java.util.Scanner;
import java.util.Random;
public class Minesweeper {
char[][] minesweeper = new char[9][9];
Random randNum = new Random();
Scanner sc = new Scanner(System.in);
public Minesweeper() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
minesweeper[i][j] = '*';
}
}
}
public void printMinesweeper() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
System.out.print(minesweeper[i][j]);
}
System.out.println();
}
}
public void randomX() {
System.out.print("How many mines do you want on the field?: ");
int numberOfMines = sc.nextInt();
int i = 0;
while (i < numberOfMines) {
int x = randNum.nextInt(9);
int y = randNum.nextInt(9);
if (minesweeper[x][y] == '*') {
minesweeper[x][y] = 'X';
i++;
}
}
printMinesweeper();
}
}
You can do it like this:
import java.util.Random;
import java.util.Scanner;
public class Minesweeper {
public static void main(String[] args) {
Minesweeper minesweeper = new Minesweeper();
minesweeper.randomX();
minesweeper.printMinesweeper();
}
char[][] minesweeper = new char[9][9];
Random randNum = new Random();
Scanner sc = new Scanner(System.in);
public Minesweeper() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
minesweeper[i][j] = '*';
}
}
}
public void printMinesweeper() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
System.out.print(getCharAt(i, j));
}
System.out.println();
}
}
private String getCharAt(int i, int j) {
if (mineAt(i, j)) {
return "X";
}
int minesNear = countMinesNear(i, j);
return Integer.toString(minesNear);
}
private boolean mineAt(int i, int j) {
return minesweeper[i][j] == 'X';
}
private int countMinesNear(int i, int j) {
int mines = 0;
for (int x = -1; x <= 1; x++) {//near fields in x direction
for (int y = -1; y <= 1; y++) {//near fields in y direction
if (x + i >= 0 && x + i < minesweeper.length && y + j >= 0 && y + j < minesweeper.length) {//check whether the field exists
if (minesweeper[x+i][y+j] == 'X') {//check whether the field is a mine
mines++;
}
}
}
}
return mines;
}
public void randomX() {
System.out.print("How many mines do you want on the field?: ");
int numberOfMines = sc.nextInt();
int i = 0;
while (i < numberOfMines) {
int x = randNum.nextInt(9);
int y = randNum.nextInt(9);
if (minesweeper[x][y] == '*') {
minesweeper[x][y] = 'X';
i++;
}
}
printMinesweeper();
}
}
The countMinesNear(int, int) method check whether the field near exists (to prevent index errors on the edges) and counts the mines if the fields exist.
I have used Libgdx to generate a dungeon out of keyboard characters. I have decided to print out the array as a text file.
However this is what I got:
Furthermore, It isn't consistent
I don't get what is wrong?
I checked over my algorithm and didn't find anything wrong.
Here is my code:
public class test1 extends ApplicationAdapter {
SpriteBatch batch;
Texture img;
int X = 50;
int Y = 25;
////////// # wall
////////// . ground
char[][][] mapChars = new char[1000][1000][1000];
private void genDung() {
int clearance = 4;
for (int i = 0; i < Y; i++) {
for (int j = 0; j <= X; j++) {
if(j == X)
mapChars[0][i][j] = '\n';
else
mapChars[0][i][j] = '#';
}
}
int roomCount = MathUtils.random(2, 2);
int[] roomPosX = new int[roomCount];
int[] roomPosY = new int[roomCount];
int[] roomCenterPosX = new int[roomCount];
int[] roomCenterPosY = new int[roomCount];
int[] roomSizeX = new int[roomCount];
int[] roomSizeY = new int[roomCount];
for (int i = 0; i < roomCount; i++) {
int attempts = 0;
while(true) {
boolean rePosition = false;
roomPosX[i] = MathUtils.random(1, X-1);
roomPosY[i] = MathUtils.random(1, Y-1);
roomSizeX[i] = MathUtils.random(2, 12);
roomSizeY[i] = MathUtils.random(2, 8);
for(int j = 0; j <= i; j++) {
if(i != j) {
if(roomPosX[i] >= roomPosX[j] && roomPosX[i] <= (roomPosX[j] + roomSizeX[j] + clearance)) {
if(roomPosY[i] >= roomPosY[j] && roomPosY[i] <= (roomPosY[j] + roomSizeY[j] + clearance)) {
rePosition = true;
break;
}
}
if((roomPosX[i]+roomSizeX[i]) >= roomPosX[j] && (roomPosX[i]+roomSizeX[i]) <= (roomPosX[j] + roomSizeX[j] + clearance)) {
if((roomPosY[i]+roomSizeY[i]) >= roomPosY[j] && (roomPosY[i]+roomSizeY[i]) <= (roomPosY[j] + roomSizeY[j] + clearance)) {
rePosition = true;
break;
}
}
if((roomPosX[i]) >= roomPosX[j] && (roomPosX[i]) <= (roomPosX[j] + roomSizeX[j] + clearance)) {
if((roomPosY[i]+roomSizeY[i]) >= roomPosY[j] && (roomPosY[i]+roomSizeY[i]) <= (roomPosY[j] + roomSizeY[j] + clearance)) {
rePosition = true;
break;
}
}
if((roomPosX[i]+roomSizeX[i]) >= roomPosX[j] && (roomPosX[i]+roomSizeX[i]) <= (roomPosX[j] + roomSizeX[j] + clearance)) {
if((roomPosY[i]) >= roomPosY[j] && (roomPosY[i]) <= (roomPosY[j] + roomSizeY[j] + clearance)) {
rePosition = true;
break;
}
}
}
else if(roomPosX[j] + roomSizeX[j] >= X-1){
rePosition = true;
}
else if(roomPosY[j] + roomSizeY[j] >= Y-1){
rePosition = true;
}
}
attempts++;
if(attempts >= 10000) break;
if(!rePosition) break;
}
}
for(int r = 0; r < roomCount; r++) {
for (int a = roomPosX[r]; a <= (roomPosX[r] + roomSizeX[r]); a++) {
for (int b = roomPosY[r]; b <= (roomPosY[r] + roomSizeY[r]); b++) {
mapChars[0][b][a] = '.';
}
}
}
Gdx.app.log("roomCount", String.valueOf(roomCount)+"\n\n\n");
for(int i =0; i< roomCount; i++) {
roomCenterPosX[i] = roomPosX[i] + roomSizeX[i]/2;
roomCenterPosY[i] = roomPosY[i] + roomSizeY[i]/2;
Gdx.app.log("room", String.valueOf(i)+"\n");
Gdx.app.log("roomPosX", String.valueOf(roomPosX[i]));
Gdx.app.log("roomPosY", String.valueOf(roomPosY[i]));
Gdx.app.log("roomSizeX", String.valueOf(roomSizeX[i]));
Gdx.app.log("roomSizeY", String.valueOf(roomSizeY[i])+"\n");
Gdx.app.log("RoomCenterPosX", String.valueOf(roomCenterPosX[i]));
Gdx.app.log("RoomCenterPosY", String.valueOf(roomCenterPosY[i])+"\n\n");
}
int difference = X;
int[] roomNum = new int[2];
for(int i = 0; i < roomCount; i++) {
for(int j = 0; j < roomCount; j++) {
if(i != j) {
if(abs(roomCenterPosX[i] - roomCenterPosX[j]) < difference) {
difference = abs(roomCenterPosX[i] - roomCenterPosX[j]);
roomNum[0] = i;
roomNum[1] = j;
}
}
}
}
Gdx.app.log("FarthestRooms", String.valueOf(roomNum[0]));
Gdx.app.log("FarthestRooms", String.valueOf(roomNum[1]));
int differenceX = X;
int differenceY = Y;
int[] connectRooms = new int[2];
// int[] roomsConnected = new int[roomCount];
connectRooms[0] = MathUtils.random(0, roomCount - 1);
// roomsConnected[0] = connectRooms[0];
int count;
for(int i = 0; i < roomCount-1; i++) {
int j;
while(true) {
connectRooms[1] = MathUtils.random(0, roomCount - 1);
/* while (true) {
connectRooms[1] = MathUtils.random(0, roomCount - 1);
count = 0;
for (j = 0; j < i; j++) {
if (connectRooms[1] != roomsConnected[j] && connectRooms[0] != roomsConnected[j]){
count++;
}
}
if(count >= i-2)
break;
}*/
if(connectRooms[0] != connectRooms[1])
break;
}
// roomsConnected[i+1] = connectRooms[1];
differenceX = roomCenterPosX[connectRooms[0]] - roomCenterPosX[connectRooms[1]];
differenceY = roomCenterPosY[connectRooms[0]] - roomCenterPosY[connectRooms[1]];
if(roomCenterPosX[connectRooms[0]] < roomCenterPosX[connectRooms[1]])
differenceX *= -1;
if(roomCenterPosY[connectRooms[0]] < roomCenterPosY[connectRooms[1]])
differenceY *= -1;
int k;
try {
if (differenceX > 0) {
for (k = 0; k < differenceX; k++) {
mapChars[0][roomCenterPosY[i]][roomCenterPosX[i] + k] = '.';
}
} else if (differenceX < 0) {
for (k = 0; k > differenceX; k--) {
mapChars[0][roomCenterPosY[i]][roomCenterPosX[i] + k] = '.';
}
} else k = 0;
if (differenceY < 0) {
for (int z = 0; z > differenceY; z--) {
mapChars[0][roomCenterPosY[i] + z][roomCenterPosX[i] + k] = '.';
}
} else if (differenceY > 0) {
for (int z = 0; z < differenceY; z++) {
mapChars[0][roomCenterPosY[i] + z][roomCenterPosX[i] + k] = '.';
}
} else {
}
}
catch (ArrayIndexOutOfBoundsException e) {
Gdx.app.log("Non Fatal Exception", String.valueOf(e));
}
Gdx.app.log("Connect", String.valueOf(connectRooms[0]));
Gdx.app.log("Connect", String.valueOf(connectRooms[1]));
Gdx.app.log("DifferenceX", String.valueOf(differenceX));
Gdx.app.log("DifferenceY", String.valueOf(differenceY)+"\n");
}
for(int q = 0; q < Y; q++) {
mapChars[0][q][X] = '\n';
}
for(int w = 0; w < Y; w++) {
mapChars[0][w][X-1] = '#';
}
for(int e = 0; e < Y; e++) {
mapChars[0][Y-1][e] = '#';
}
}
private void export() {
if(Gdx.files.isLocalStorageAvailable()) {
FileHandle fileHandle = Gdx.files.local("map.txt");
if(Gdx.files.local("map.txt").exists())
fileHandle.writeString("", false);
for(int i = 0; i<= Y; i++) {
for (int j = 0; j <= X; j++) {
fileHandle.writeString(""+mapChars[0][i][j] , true);
}
}
}
}
#Override
public void create () {
batch = new SpriteBatch();
img = new Texture("badlogic.jpg");
// genMap();
// for(int i = 0; i< 4; i++)
// refineMap();
genDung();
export();
}
#Override
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(img, 0, 0);
batch.end();
if(Gdx.input.isTouched()) {
// genMap();
// for(int i = 0; i< 4; i++)
// refineMap();
genDung();
export();
}
}
}
I want the two rooms to connect properly every time.
As you can see, one of the time, the rooms connected
The other time the rooms don't connect.
Thanks in advance
The whole thing can be simplified and definitely needs refactoring. Regarding the 2 room connection - check this piece carefully
differenceX = roomCenterPosX[connectRooms[0]] - roomCenterPosX[connectRooms[1]];
differenceY = roomCenterPosY[connectRooms[0]] - roomCenterPosY[connectRooms[1]];
if(roomCenterPosX[connectRooms[0]] < roomCenterPosX[connectRooms[1]])
differenceX *= -1;
if(roomCenterPosY[connectRooms[0]] < roomCenterPosY[connectRooms[1]])
differenceY *= -1;
As #kiheru pointed out it is equivalent to Math.abs(roomCenterPosX[connectRooms[0]] - roomCenterPosX[connectRooms[1]]) (same for Y). So you always "dig" to right and down, never up or left.
Drop that invertion and have fun with the rest of your algorithm :)
I'm doing a collegeproject to make tetris, however I'm stuck at the moment.
I have a nullpointerexception when I simply want to change a value of an array. Should be easy right?
Apparently not...
I'm not an advanced programmer yet, so if anyone could help me find the incorrect code, and specifically explain to me why it's wrong, it'll be appreciated.
Here's my code:
package tetris;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import engine.*;
public class Tetris extends Game {
private int x = 0, y = 0, maxWidth = 0, bSize = 25;
private int[][] field;
private boolean busy;
private Blok blok = null;
public Tetris() {
title = "Tetris";
height = 600;
width = 400;
delay = 100;
delay2 = 10;
field = new int[20][10];
field[19][7] = 1;
field[18][7] = 2;
field[17][7] = 3;
field[19][2] = 4;
field[19][3] = 5;
}
public static void main(String arg[]) {
GameApplication.start(new Tetris());
}
#Override
/**
* Right Arrow: keycode 39
* Left Arrow: keycode 37
*/
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == 37) {
if (tryMove(-1)) {
x--;
}
}
else if(e.getKeyCode() == 39) {
if (tryMove(1)) {
x++;
}
} else if(e.getKeyCode() == 40) {
if (tryMove(0)) {
y++;
}
}
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void update() {
if(!busy) {
int random = (int) (Math.random()*7);
//debug mode
random = 0;
///
System.out.println(random);
blok = new Blok(random);
y = 1;
x = 3;
busy = true;
}
if (!tryMove(0)){
field[y][x] = 1;
busy = false;
} else {
y++;
}
scanLine();
}
#Override
public void update2() {
}
#Override
public void draw(Graphics2D g) {
g.fillRect(0, 0, width, height);
g.setColor(Color.LIGHT_GRAY);
g.fillRect(0, 0, 250, 500);
for (int i = 0; i<20; i++){
for (int j = 0; j<10; j++){
if (field[i][j]>0) {
g.setColor(Color.black);
g.fillRect(j*25,i*25,bSize,bSize);
}
}
}
if(busy) {
maxWidth = blok.getWidth();
for (int i = 0; i<3; i++){
g.fillRect(blok.getX(i)*25,blok.getY(i)*25,bSize,bSize);
}
}
}
public boolean tryMove(int a) {
boolean b = true;
if (a == -1){
if (x <= 0 || field[y][x-1] != 0){
b = false;
}
} else if (a == 0){
if (y >= 19 || field[y+1][x] != 0){
b = false;
}
} else if (a == 1){
if (x >= (9-maxWidth) || field[y][x+1] != 0){
b = false;
}
}
return b;
}
public void scanLine(){
for (int i = 0; i<20; i++){
boolean vol = true;
for (int j = 0; j<10; j++){
if (field[i][j]==0) {
vol = false;
}
}
if (vol) {
removeLine(i);
}
}
}
public void removeLine(int a){
for (int i = a; i>0; i--){
for (int j = 0; j<10; j++){
field[i][j] = field[i-1][j];
}
}
}
}
and for making the block(and where it goes wrong)
package tetris;
public class Blok {
private int type;
private int[] x,y;
private int width;
public Blok(int type) {
this.setType(type);
setCoords(type);
x = new int[4];
y = new int[4];
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public void setCoords(int type) {
if (type == 0){
setWidth(3);
setX(0,1); setY(0,0);
setX(1,2); setY(1,0);
setX(2,3); setY(2,0);
setX(3,0); setY(3,0);
//x[0] = 1; y[0] = 0;
//x[1] = 2; y[1] = 0;
//x[2] = 3; y[2] = 0;
//x[3] = 0; y[3] = 0;
} else if (type == 1){
setWidth(2);
x[0] = 1; y[0] = 0;
x[1] = 2; y[1] = 0;
x[2] = 0; y[2] = -1;
x[3] = 0; y[3] = 0;
} else if (type == 2){
setWidth(2);
x[0] = 1; y[0] = 0;
x[1] = 2; y[1] = 0;
x[2] = 2; y[2] = -1;
x[3] = 0; y[3] = 0;
} else if (type == 3){
setWidth(2);
x[0] = 1; y[0] = 0;
x[1] = 2; y[1] = 0;
x[2] = 1; y[2] = -1;
x[3] = 0; y[3] = 0;
} else if (type == 4){
setWidth(2);
x[0] = 1; y[0] = -1;
x[1] = 1; y[1] = 0;
x[2] = 0; y[2] = -1;
x[3] = 0; y[3] = 0;
} else if (type == 5){
setWidth(1);
x[0] = 1; y[0] = 0;
x[1] = 1; y[1] = -1;
x[2] = 2; y[2] = -1;
x[3] = 0; y[3] = 0;
} else if (type == 6){
setWidth(2);
x[0] = 1; y[0] = 0;
x[1] = 1; y[1] = 1;
x[2] = 2; y[2] = 1;
x[3] = 0; y[3] = 0;
}
}
public int getX(int type) {
return x[type];
}
public int getY(int type) {
return y[type];
}
public void setX(int index, int value){
x[index] = value; //This is line 82, goes wrong here.
}
public void setY(int index, int value){
y[index] = value;
}
public int getWidth() {
return width;
}
public void setWidth(int w) {
this.width = w;
}
}
Here's the errorcode:
Exception in thread "Thread-2" java.lang.NullPointerException
at tetris.Blok.setX(Blok.java:82)
at tetris.Blok.setCoords(Blok.java:26)
at tetris.Blok.<init>(Blok.java:10)
at tetris.Tetris.update(Tetris.java:75)
at engine.Engine.run(Engine.java:18)
In your constructor you put
public Blok(int type) {
this.setType(type);
setCoords(type);
x = new int[4];
y = new int[4];
}
You call setCoords that calls setX(..) and setX use x that is null then NullPointerException is thrown.
A workaround is to change order.
public Blok(int type) {
this.setType(type);
x = new int[4];
y = new int[4];
setCoords(type);
}
But calling an overridable method in a constructor is not a good practice. Read more What's wrong with overridable method calls in constructors?. A workaround is making setCoords(..) final or making your class final or make that method private or remove from constructor and call it from client code of this class.