I am new to programming and I have an assignment in Java that asks the user to navigate a 10X10X10 cubic maze, where there must be 500 monsters randomly generated, 499 open cells, and 1 treasure chest. The treasure chest must also be randomly generated, but it cannot occur within the same spot as a monster. The program I have to write asks for user input to check a cell in the array to see if its the treasure chest. If the cell is empty, I have to give a hint as to where the treasure chest is (how many cells away and if you're in the same row, column, or page). The user gets three tries to find the treasure chest. At the end of the three tries, or if they hit a monster, the user loses and is told in what cell the chest was placed. For the purposes of the assignment, an empty cell = 0, the only cell with the treasure chest = 1, and the monster cell = 2.
I am having trouble populating the cells with only 500 monsters and one chest. My code below populates all the cells with a random amount of 0's, 1's and 2's. I need to limit the 2's to five-hundred instances, the 1's to one instance (and check beforehand to make sure a monster isn't in the cell), and keep the rest 0. I also need to make sure I'm not populating the same cell with more than one monster. This is as far as I've got:
import java.util.Random;
public class FindTheCheese
{
public static void main(String args[ ])
{
int size = 10;
int[][][] maze = new int[10][10][10];
Random gen = new Random();
for(int i = 0; i < 10; i++){
for(int j = 0; j < 10; j++) {
for(int k = 0; k <10; k++) {
maze[i][j][k] = gen.nextInt(3);
System.out.print(maze[i][j][k] + ", "); // this won't be part of the final code, just used to check if I'm populating correctly
}
System.out.println();
}
}
}//closing main
}//closing class FindTheCheese
Create a one-dimensional array of length 1000 to hold all the values to go into the maze. Set 500 elements to 2 (the monsters), one element to 1 (the treasure chest) and 499 elements to 0 (the free cells).
Shuffle the array using Collections.shuffle(Arrays.asList(yourOneDimArray)).
Now fill the values from the shuffled array into your 3-dimensional matrix in turn. Underway when you encounter the chest, record its coordinates in the maze. You will need this for reporting back to the user.
When you first create the maze, all cells will be zero by default. Next, add the single treasure to a random spot. Finally, pick a random cell and see if it's empty. If it isn't, pick another random cell. If it is, place a monster. Repeat that 500 times with a for loop:
public static void main(String[] args) {
int size = 10;
int[][][] maze = new int[10][10][10]; // every cell is zero by default!
Random gen = new Random();
// place the treasure
maze[gen.nextInt(size)][gen.nextInt(size)][gen.nextInt(size)] = 1;
// place 500 monsters
for(int monsters = 1; monsters <= 500; monsters++) {
int i, j, k;
do {
i = gen.nextInt(size);
j = gen.nextInt(size);
k = gen.nextInt(size);
} while (maze[i][j][k] != 0);
maze[i][j][k] = 2;
}
// display the results
for(int i = 0; i < size; i++){
for(int j = 0; j < size; j++) {
for(int k = 0; k < size; k++) {
System.out.print(maze[i][j][k] + " ");
}
System.out.println();
}
}
}
I've made a tic-tac-toe game and while I have a working computer move code, it just seems to go from left to right across the board instead of picking a random board slot.
Here's my code for the computer move:
public static void compTurn(char[][] board, char computer)
{
for (int i = 0; i < board.length; i++)
{
for (int j = 0; j < board.length; j++)
{
if(board[i][j] == ' ')
{
board[i][j] = computer;
return;
}
}
}
}
What you are doing right now is going sequentially through the spaces and checking if they are open. If they are, the computer will move there. what you need to do instead is select a random spot until it finds one. Even better, you could keep a list of spots that are occupied in an array and attempt to move to a spot that is vacant.
Here is a basic solution, but in all honesty using the array is a much better way to go, both in terms of performance and elegance. You would basically create 2 arrays; one to contain occupied slots (that holds what player occupies that slot), another array to hold vacant spots (could be a simple boolean value to indicate spot is available for a move.). Each turn, check the vacant array for a space that is open, randomly, them move to it.
public static void compTurn(char[][] board, char computer)
{
Random rand;
boolean moved = false;
/* If we haven't moved, look for a space to move to
max = the highest space you have
min = the lowest space you have
*/
while (!moved) {
int randomSpace = rand.nextInt((max - min) + 1) + min;
/* I leave this part for you to figure out */
if(thisSpace == ' ')
{
//make the computer move to this space
moved = true;
}
};
}
As this is very obviously an assignment, I left some blanks for you to fill in yourself, but this should be what you are looking for.
So, I'm creating a game, and when the user's player hits a location(There are many), I want it to be game over.
I have two ArrayLists like this.
ArrayList<Integer> ex = new ArrayList<Integer>(), ey = new ArrayList<Integer>();
And the 'bad' square (which the user dies if they hit it) appear after they've gotten a powerup, so there are Integers added on often.
I've trying to do a for loop to loop through the size(shown below), but that doesn't work as i only selects the latest one, obviously.
for(int i = 0; i < ex.size() - 1; i++) {
if(x.get(0)==ex.get(i) && y.get(0) == ey.get(i)){
gameover = true;
}
}
If I just loop through the whole arrayList like this
(int i : ex)
Then it gives me this(below) error upon starting the game:
Exception in thread "Animation Thread" java.lang.IndexOutOfBoundsException: Index: 10, Size: 1
at java.util.ArrayList.rangeCheck(ArrayList.java:653)
at java.util.ArrayList.get(ArrayList.java:429)
at snakegame.SnakeGame.draw(SnakeGame.java:113)
at processing.core.PApplet.handleDraw(PApplet.java:2386)
at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:240)
at processing.core.PApplet.run(PApplet.java:2256)
at java.lang.Thread.run(Thread.java:745)
So, is there anyway to store all the numbers of the ArrayList in one variable?
You are getting confused with the semantics of the "enhanced for"
for(int i = 0; i < ex.size() - 1; i++) {
puts into i the values 0, 1, 2... up to ex.size()-1. i works as the index
for(int i : ex) {
puts into i the values ex.get(0), ex.get(1). It is the content.
In the second case, the logic should be
int j = 0;
for (int i : ex) {
if(x.get(0) == i && y.get(0) == ey.get(j)){
..
}
j++;
}
In this case the enhanced for makes little sense.
If it helps you visualize, thing that with enhanced for, the variable must be always of the type of the array / iterator (in this case, it just happens that you can autooutbox Integer to int)
From what I understand, you have an x,y grid in which there are coordinates that cause the user to die. As your user moves through the grid, you want to check whether or not the square they're currently on is a bad square.
Instead of two ArrayLists, it might be better to store it as a multidimensional array.
class Grid {
private int[][] spaces;
public Grid(int xdim, int ydim) {
spaces = new int[xdim][ydim];
for (int x=0; x<xdim; x++) {
for (int y=0; y<ydim; y++) {
spaces[x][y] = 0;
}
}
}
private void addBadSpace(int x, int y) {
spaces[x][y] = 999;
}
private boolean isBadSpace(int x, int y) {
return (spaces[x][y] != 0);
}
}
Whether you take this approach depends on the size of your application and your grid. The multidimensional array will be very quick, but will take up a lot of space in memory. If it's a sparse matrix (i.e. very few 'bad' spaces exist) and your grid is very large, there are more efficient approaches.
To this question:
The superqueen is a chess piece that can move like a queen, but also like a knight. What is the maximal number of superqueens on an 8X8 chessboard such that no one can capture an other?
I want to write a brute force algorithm to find the maximum. Here's what I wrote:
public class Main {
public static boolean chess[][];
public static void main(String[] args) throws java.lang.Exception {
chess = new boolean[8][8];
chess[0][0] = true;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
/*Loop to check various possibilities*/
if (!checkrow(i) && !checkcolumn(j) && !checkdiagonals(i, j) && !checkknight(i, j)) {
if (i != 0 || j != 0) {
chess[i][j] = true;
}
}
}
}/*printing the array*/
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
System.out.print(((chess[i][j]) ? "T" : "x") + "|");
}
System.out.println();
}
}
/*All working fine here*/
public static boolean checkrow(int a) {
for (int i = 0; i < 8; i++) {
if (chess[a][i]) {
return true;
}
}
return false;
}
/*All working fine here*/
public static boolean checkcolumn(int a) {
for (int i = 0; i < 8; i++) {
if (chess[i][a]) {
return true;
}
}
return false;
}
/*All working fine here*/
public static boolean checkdiagonals(int pi, int pj) {
int i = pi - Math.min(pi, pj);
int j = pj - Math.min(pi, pj);
for (int k = i, l = j; k < 8 && l < 8; k++, l++) {
if (chess[k][l]) {
return true;
}
}
int i_2 = pi - Math.min(pi, pj);
int j_2 = pj + Math.min(pi, pj);
for (int k = i_2, l = j_2; k < 8 && l > 1; k++, l--) {
if (chess[k][l]) {
return true;
}
}
return false;
}
/*Not All working fine here try commenting out this method above so that that it doesn't run during the check*/
public static boolean checkknight(int pi, int pj) {
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
if (0 <= pi + 2 * i && pi + 2 * i <= 8 && 0 <= pj + j && pj + j <= 8) {
if (chess[pi + 2 * i][pj + j]) {
return true;
}
}
if (0 <= pi + i && pi + i <= 8 && 0 <= pj + 2 * j && pj + 2 * j <= 8) {
if (chess[pi + i][pj + 2 * i]) {
return true;
}
}
}
}
return false;
}
}
I have two questions:
My algorithm for checkknight looks for all knight positions, is it wrong? or there is some coding error.Everything is working fine when I comment out it and I get a nice solution.
Secondly it'll result only in one solution.For other solutions I have to offset(or change position) of other pieces bit by bit after each mega-loop of this, I am confused about implementing it. My instincts guide me that I need to change whole of the code. Is there a modification or a way to do it?
Additional Thoughts: I think we would add to a counter each time we place a piece and add to a long array and output the maximum and array after storing the relevant data.
Code Location: You may view/edit/fork/download it at http://ideone.com/gChD8a
This a rough brute-force method starting from the opposite direction, i.e. from the solved eight-queens puzzle. This will allow us to find a bunch of viable solutions.
The brute-force technique for going from a single superqueen to potentially 8 seems to be especially complex due to the knight's traversal. Based on the runs, about 60% of the viable paths for normal queens are invalid with superqueens. So if we were to instead brute force normal queens, and then work backwards, that is potential time saved for finding a solution, and we can better determine the run-time. Because we know normal queens is easier.
We start off with the 12 fundamental solutions, we would then use these as inputs. Solving normal queens is outside this, but the wiki page has a fantastic article describing everything.
In my case, I stored them as Strings representing the coordinate of the queen (the rows are indices).
So: "17468253" = A1, B7, C4, D6, E8, F2, G5, H3
By brute-forcing the opposite direction from solved queens, we only have to test at most 12 x 8! possible solutions. Because order doesn't matter, additional optimization could occur by eliminating duplicate boards and solutions for processing.
First up, checkKnight, which appears to be your source of confusion. Using absolute values, you can reasonably determine whether or not a piece is within knight's range by checking whether the X offset is 2 and Y offset is 1, or vice versa. You've made a complex checkKnight function to check each individual location and whether or not a piece is on the border. Working the other way by hitscanning each queen to each other queen is logically simpler and less of a nightmare to debug.
Queen class
public class Queen {
int i, j;
public Queen(int i, int j) {
this.i = i;
this.j = j;
}
public boolean checkKnight(Queen queen) { // if any queen meets another
// queen at 2 and 1 offset, we
// eliminate it.
return (Math.abs(i - queen.i) == 2 && Math.abs(j - queen.j) == 1)
|| (Math.abs(i - queen.i) == 1 && Math.abs(j - queen.j) == 2);
}
}
This board has been modified since I originally posted. It takes a String input and converts it to a full chessboard. It has some minor work towards the potential any-size board, but right now it handles child board creation. When a child board is created, the queens are passed by reference rather than making a whole new set of queens. A total of 96 queens are stored in memory, 1 for each one on the original 12-board solution. Not perfectly optimized, but better than 96 -> 672 -> 4032 -> ...
Board class
public class Board {
static int boardSize = 8;
ArrayList<Queen> queens = new ArrayList<Queen>();
public Board(String s) {
for (int i = 0; i < s.length(); i++) {
queens.add(new Queen(i, s.charAt(i) - 49)); // you could implement
// base 16 here, for
// example, for a 15x15
// board
}
}
public Board(Board b) { // duplicates the board, but keeps references to
// queens to conserve memory, only 96 total queens
// in existence through search!
for (Queen q : b.queens) {
queens.add(q);
}
}
public boolean checkForImpact() {
for (int i = 0; i < queens.size(); i++) {
for (int j = i + 1; j < queens.size(); j++) {
if (queens.get(i).checkKnight(queens.get(j))) { // just check
// for any
// queens
// intersecting,
// one hit is
// enough
return true;
}
}
}
return false;
}
public ArrayList<Board> getChildBoards() { // create child boards with a
// single queen removed
ArrayList<Board> boards = new ArrayList<Board>();
for (int i = 0; i < queens.size(); i++) {
boards.add(new Board(this));
}
int i = 0;
for (Board b : boards) {
b.queens.remove(i);
i++;
}
return boards;
}
public String drawBoard() {
String s = "";
char[][] printableBoard = new char[boardSize][boardSize];
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
printableBoard[i][j] = '_';
}
}
for (Queen q : queens) {
printableBoard[q.i][q.j] = 'Q';
}
s += " A B C D E F G H\n";
for (int i = 0; i < 8; i++) {
s += (8 - i) + "|";
for (int j = 0; j < boardSize; j++) {
s += printableBoard[i][j];
s += "|";
}
s += "\n";
}
return s;
}
}
Test class
import java.util.ArrayList;
public class Test {
static String[] boards = { "24683175", "17468253", "17582463", "41582736",
"51842736", "31758246", "51468273", "71386425", "51863724",
"57142863", "63184275", "53172864" }; // all 12 solutions for the 8
// queens problem
static ArrayList<Board> boardObjects = new ArrayList<Board>();
public static void main(String[] args) {
for (String queens : boards) { // create starter boards
boardObjects.add(new Board(queens));
}
int i;
ArrayList<Board> foundBoards = null;
for (i = 8; i > 0; i--) {
ArrayList<Board> newBoards = new ArrayList<Board>();
foundBoards = new ArrayList<Board>();
for (Board b : boardObjects) {
if (b.checkForImpact()) { // if any queen intercepts we get
// children
ArrayList<Board> boardsToBeAdded = b.getChildBoards(); // pass
// all
// permutations
// of
// queens
// once
// removed
for (Board bo : boardsToBeAdded) {
newBoards.add(bo); // add it in to the next list
}
} else {
foundBoards.add(b); // if we have no impact, we have a
// solution
}
}
if (!foundBoards.isEmpty())
break;
boardObjects.clear();
boardObjects = newBoards;
}
System.out.println("The maximum number of super-queens is: " + i);
ArrayList<String> winningCombinations = new ArrayList<String>();
for (Board board : foundBoards) {
String createdBoard = board.drawBoard();
boolean found = false;
for (String storedBoard : winningCombinations) {
if (storedBoard.equals(createdBoard))
found = true;
}
if (!found)
winningCombinations.add(createdBoard);
}
for (String board : winningCombinations) {
System.out.println(board);
}
}
}
The end output is:
The maximum number of super-queens is: 6
A B C D E F G H
8|Q|_|_|_|_|_|_|_|
7|_|_|_|_|_|_|Q|_|
6|_|_|_|Q|_|_|_|_|
5|_|_|_|_|_|_|_|_|
4|_|_|_|_|_|_|_|Q|
3|_|Q|_|_|_|_|_|_|
2|_|_|_|_|Q|_|_|_|
1|_|_|_|_|_|_|_|_|
A B C D E F G H
8|Q|_|_|_|_|_|_|_|
7|_|_|_|_|_|_|_|_|
6|_|_|_|_|Q|_|_|_|
5|_|_|_|_|_|_|_|Q|
4|_|Q|_|_|_|_|_|_|
3|_|_|_|_|_|_|_|_|
2|_|_|_|_|_|Q|_|_|
1|_|_|Q|_|_|_|_|_|
A B C D E F G H
8|_|_|_|_|Q|_|_|_|
7|Q|_|_|_|_|_|_|_|
6|_|_|_|_|_|_|_|Q|
5|_|_|_|Q|_|_|_|_|
4|_|_|_|_|_|_|_|_|
3|_|_|_|_|_|_|_|_|
2|_|_|Q|_|_|_|_|_|
1|_|_|_|_|_|Q|_|_|
A B C D E F G H
8|_|_|_|_|Q|_|_|_|
7|Q|_|_|_|_|_|_|_|
6|_|_|_|_|_|_|_|Q|
5|_|_|_|Q|_|_|_|_|
4|_|_|_|_|_|_|_|_|
3|_|_|_|_|_|_|Q|_|
2|_|_|Q|_|_|_|_|_|
1|_|_|_|_|_|_|_|_|
A B C D E F G H
8|_|_|_|_|Q|_|_|_|
7|Q|_|_|_|_|_|_|_|
6|_|_|_|_|_|_|_|Q|
5|_|_|_|_|_|_|_|_|
4|_|_|Q|_|_|_|_|_|
3|_|_|_|_|_|_|Q|_|
2|_|_|_|_|_|_|_|_|
1|_|_|_|Q|_|_|_|_|
I've removed the duplicates and made a nice board printing method. don't remember the exact math, but this highlights 40 possible locations. There are others, just by looking, but we've found a fair chunk of them already! From here, we can gently shift individual queens around. From a cursory look, each board has a single piece that can be moved to 3 additional spaces, so now we know there are probably about 160 solutions.
Conclusions
With this application, the run-time on my machine was less than a second, meaning that if we attached this to a standard queens application, the additional knight's brute-forcing would have no impact on that process and have almost the same run-time. In addition, because only 6-piece puzzles are possible, we know that your eventual application run will finish its finding at the 6th piece being placed, as no more solutions are possible, since there are no viable 7-piece and 8-piece solutions.
In other words, finding the maximum super-queen layout is likely actually shorter than the maximum queen layout due to the additional restrictions!
Trying to brute-force such a question is a good way to get a feel for it. So I won't suggest looking up pre-cooked solutions at first.
One little remark though: I don't see the reason for the condition if (i != 0 || j != 0) { that you have there. You are working on Java arrays. Instead of 1 through 8, they go 0 through 7, but the 0 is the first column, you should not eliminate it, otherwise it's only a 7x7 board.
First, let me address your technical question: how to calculate the knight positions.
Take a sheet of quad paper, put a queen somewhere not less than two squares away from the edge. Then mark the end positions of a knight-move from it.
You'll end up with just 8 squares that need to be considered. There is no point in doing a 3x3 loop to find them. A better idea would be to prepare a static array with the relative coordinates of the knight moves - an array of 8 pairs of numbers - and loop on that. So you have only an 8-step loop. In each step of the loop, check for bounds (0 ≤ X + Xoffset < 8, 0 ≤ Y + Yoffset < 8 ), and you have the knight coordinates.
Second, there is no point checking the part of the board that's ahead of you. Since you have not covered the next row and those below it, there is no point in looking for queens there. The implications of this:
You'll never put another queen in the same row where you have just marked a queen position (because you threaten it horizontally). This means that if you mark a queen, you should use continue to break out of the inner loop to the next row.
You don't need checkrow(). When you start a row, there is no queen ahead of you. And if you followed the above bullet point, there is no queen on your back, either.
When you use checkcolumn, you start at row 0, but you can finish at the row before the one you are on (i-1). There are still no queens in the rows below you! The same is true for the diagonal checks.
Earlier I said that you need to prepare and check 8 knight positions. But now you know there is no queen at the knight positions ahead of you. So you only need to prepare an array with four knight positions - the ones above your position.
But most importantly... once you have finished and you have your queens in positions and print the board: you have a single solved board. You have proved that this number of queens is possible. But is it the highest number possible? You have not checked what happens if you don't put a queen on the first square of the first row, but on the second. Perhaps this will allow you to put in an extra queen later. And what about the queen in the second row? Maybe if you moved that, you would be able to put a queen somewhere below where you couldn't before?
So, now you have to actually do the same thing over again, changing one decision every time and working from there. In effect, you have many potential boards. Why? Because there may be more than one valid position on each row where you put that row's queen. So you have decided to put it in the first valid position. But what if you decide to put it in the second valid position? Or leave that row empty? Each such decision is followed by another set of decisions on the next row.
The different boards created by different decisions form a decision tree. The problem for you to consider, therefore, is how to work such a tree out. How to write your decision trail and then backtrack, change, fill another board and count the queens at each level. People here suggested recursion, because it lends itself nicely to such problems. Or you can keep a stack of decisions if you want. You can eliminate some of the potential boards based on symmetries.
I suggest you first make sure you understand your single board well, and then consider how to represent your decision tree and how to traverse it.
There are several questions here.
The first is: how many knight-queens can be placed on an nxn chessboard? Since a k-piece solution can trivially be reduced to a k-1 piece solution, it makes sense to start from the upper bound. That is, look for an n-piece solution, if that fails look for an n-1 piece solution, and so forth.
The second question is: how should I look for a k-piece solution? There are two classic strategies: depth-first and breadth-first. In the former, you consider one vertex of the search tree at a time and use backtracking on failure. In the latter, you consider one complete level of the search tree at a time.
Something that can make a great deal of difference to your search is to account for symmetry (in this case, rotations and reflections).
The third (implicit) question is: what is a good representation here? If your chess-boards are less than 8x8 in size then a 64-bit bit-pattern will do very nicely!
In practical terms, try to separate the three levels of your problem as far as you can. If you don't, you'll find that a choice in one level will severely limit your options at another level.
I have the following code to set 10 random values to true in a boolean[][]:
bommaker = new boolean[10][10];
int a = 0;
int b = 0;
for (int i=0; i<=9; i++) {
a = randomizer.nextInt(9);
b = randomizer.nextInt(9);
bommaker[a][b] = true;
}
However, with this code, it is possible to have the same value generated, and therefore have less then 10 values set to random. I need to build in a checker, if the value isn't already taken. And if it is already taken, then it needs to redo the randomizing. But I have no idea how to do that. Can someone help me?
simplest solution, not the best:
for (int i=0; i<=9; i++) {
do {
a = randomizer.nextInt(10);
b = randomizer.nextInt(10);
} while (bommaker[a][b]);
bommaker[a][b] = true;
}
You're problem is similar to drawing cards at random from a deck if I'm not mistaken...
But first... The following:
randomizer.nextInt(9)
will not do what you want because it shall return an integer between [0..8] included (instead of [0..9]).
Here's Jeff's take on the subject of shuffling:
http://www.codinghorror.com/blog/2007/12/shuffling.html
To pick x spot at random, you could shuffle your 100 spot and keep the first 10 spots.
Now of course seen that you'll have only 10% of all the spots taken, simply retrying if a spot is already taken is going to work too in reasonable time.
But if you were to pick, say, 50 spots out of 100, then shuffling a list from [0..99] and keeping the 50 first value would be best.
For example here's how you could code it in Java (now if speed is an issue you'd use an array of primitives and a shuffle on the primitives array):
List<Integer> l = new ArrayList<Integer>();
for (int i = 0; i < 100; i++) {
l.add(i);
}
Collections.shuffle(l);
for (int i = 0; i < n; i++) {
a[l.get(i)/10][l.get(i)%10] = true;
}