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.
Related
I have created a working tic-tac-toe engine. So far it supports player vs player, and player vs a very basic AI that selects completely random moves. I would like to add the ability for the AI to continue selecting randomly UNLESS it sees a move that will win the game. I.E. The AI moves randomly until it has 2 in a row with one spot that is empty, and at that point it will choose to play in the winning position.
Here is what I have so far :
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (board[i][j] == ' ') {
possibleMove[0] = i;
possibleMove[1] = j;
}
if (board[i][j] == playerAI.moveType) {
winCount++;
if (winCount == 2) {
myMove = possibleMove;
winCount = 0;
System.out.println("row area " + Arrays.toString(myMove));
}
}
}
winCount = 0;
}
My idea is to check every space on the board ^^ this one checks the rows. I will store any possible move the board finds, and then it will up a counter if we have a move in that row already. If the counter hits 2, then we should go to whatever our stored move is.
I have 4 more functions for columns, diagonals, and anti diagonals, that are the exact same principle.
Can someone please help me find where the flaw in my logic is?
Another solution is for each cell to check if its two neighbours are full and it is empty:
public class StackOverflow{
static char[][] board = {{'x', 'x', ' '}, {'x', ' ', ' '}, {' ', ' ', ' '}};
public static int[] checkRow(){
for (int i = 0; i<3; i++){
for (int j = 0; j<3; j++){
if (board[i][(j+1)%3]=='x' && board[i][(j+1)%3]=='x' && board[i][j]==' '){
return new int[]{i, j};
}
}
}
return null;
}
public static void main(String[] args){
System.out.println(checkRow()[0] + " "+checkRow()[1]);
}
}
This will iterate through every cell, and check the ones 1 and 2 to the left, mod 3 so that you never check out of bounds. It returns null on a failed attempt. (which will throw because of the print statement, not because of the function itself)
One issue: If [0,0], [0,1] and [0,2] are all filled, when you reach [0,3] winCount will be 2 but possibleMove won’t have been set in this particular loop. It’ll set myMove to whatever nonsense was there previously e.g. [0,0], which obviously has nothing to do with row 0.
To get around this (for rows) you could reset winCount to 0 and possibleMove to [-1,-1] on each iteration of the outer loop, then you should use the check if (winCount == 2 && possibleMove[0] != -1 && possibleMove[1] != -1) before setting myMove.
Obviously that’s only for rows, for columns/diags you’d need to reset the values slightly differently.
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'm a student, working on a Chutes and Ladders game. I'm using methods to determine how many chutes and ladders should be placed on the game board. I'm specifying 10 for each in main using parameters but I keep getting anywhere from 6 to 11 placed across the board.
Is there something going on with the two methods interfering with each other?
Or is there a problem with the way I set up the for loops for random placement?
I'm new to this site, please let me know if you need more clarification, I didn't want to place the whole program in here. Thanks.
//main
ChutesAndLadders cl = new ChutesAndLadders();
cl.setBoard(new String[100]);
cl.makeChutes(10);
cl.makeLadders(10);
//methods
public String [] board;
private int chutes, ladders;
public int position;
public Random rand = new Random();
//set board
public void setBoard(String [] n){
board = n;
for(int i = 0; i < board.length; i++)
board[i] = " ";
}
//set and place chutes
public void makeChutes(int n){
chutes = n;
for(int i = 0; i <= chutes; i++)
board[rand.nextInt(board.length)] = "C" + chutes;
}
//set and place ladders
public void makeLadders(int n){
ladders = n;
int lcell = 0;
for(int i = 0; i <= ladders; i++)
board[rand.nextInt(board.length)] = "L" + ladders;
Firstly, you wrote:
for(int i = 0; i <= chutes; i++)
board[rand.nextInt(board.length)] = "C" + chutes;
The assignment statement in the loop will run chutes+1 times. (Eleven times in your case.) [Use i < chutes instead.] This is the same in your ladders code. This explains why you might have up to 11 chutes or ladders when the code is done running.
Secondly, you do not take care to prevent the same space being assigned a chute or ladder multiple times. rand.nextInt(board.length) is not guaranteed to generate unique values each time it is run (otherwise it wouldn't really be random.) This explains why you may not see as many as 11 chutes and ladders when the code is done running.
To make this clearer, put a constant value in there:
for(int i = 0; i < chutes; i++)
board[11] = "C" + chutes;
and notice that you end up with one chute (at space eleven)--unless the ladder code overwrites it with a ladder.
Hope that helps.
Good luck!
At first glance my guess is that you are winding up with overlapping entries. Because you generate a random placement and don't check to see if there is already a chute or ladder there, you are likely winding up with overlaps.
It should be fairly straightforward to generate the random position and then check if there is something there prior to placement. If a collision is found, just generate another random and repeat until you can place it.
Also, as an aside, it is always a good practice to avoid for loops and if statements without curly braces. It is very easy to add a second like to the block and wonder why it is not executing as part of the block.
Your for loops have an inclusive upper limit check, 0 .. 10 yields 11 entries.
Like Mike said, the lower number of results are due to collisions, you can prevent those by setting up the board by filling it with the elements needed and then shuffling the board to get the end result, something like:
public void setupBoard(String [] n, int nrLadders, int nrChutes){
board = n;
int index = 0;
while (index < board.length && 0 < nrLadders--) {
board[index++] = "L" + nrLadders;
}
while (index < board.length && 0 < nrChutes--) {
board[index++] = "C" + nrChutes;
}
while (index < board.length) {
board[index++] = " ";
}
board = Collections.shuffle(Arrays.asList(board)).toArray(new String[board.length]);
}
This is like creating a deck of cards containing a number of ladder cards, a number of chute cards, a larger number of empty spot cards and shuffling that deck to get the game board.
What this program does :
This program takes values from a class and uses those as the starting values for a Sudoku puzzle. We are to print these out in a typical Sudoku 9x9 grid. The program then prompts the user to give a coordinate point on the grid and a value to put in there. Currently what I am working on is making sure that the values put in by the user are valid to solve this puzzle. Once the puzzle is filled out and there are no longer any repeated values in each column, row, and 3x3 square, the game should end and the output should be "Puzzle Complete".
As of right now, my program checks for repeated values in columns and rows successfully, but I have no idea where to begin for checking each 3x3 square.
The numbers for this puzzle are saved in a 9x9 array.
Basicly : Any tips for how to check for repeated values in each 3x3 part of the array?
What I'd do instead of a big 9x9 array is storing a 3x3 array of 3x3 arrays of numbers. Or do both, for ease of computation (storing 81 more bytes of data (you do use bytes for the fields I hope?) isn't going to cause memory problems in all but the most memory starved devices and I doubt you'd want to play games on such anyway).
It depends on how you are storing the sudoku board. If you are storing it as a 2D array, you could have your logic identify the 3x3 box the user has chosen to enter the new value and use the code you already have to check a row and column sections.
What you could also have would be to have a collection of 9 sets. Each set would correspond to a specific 3x3 block. So, when the user selects the coordinates of where he/she would like to add the value, you would select the given set and perform an add operation in the set.
Since sets do not allow repetition, the add method will return false if the number already exists in the set. This will also allow you to identify any duplicate values (however, unlike the array option, you would also need to update the set should the user opt to remove values from the 3x3 grid).
I wrote the following code about 4 years ago in C to solve the exact same problem, it's as brute-force-y as it looks, though. The int array was a 9x9 grid. The "index" specifies the 0...8th line, 0...8th column, and 0...8th box.
int checkBox(int a[][9], int index)
{
int i, j, isValid = 1;
int m, n;
for(i = 3*(index%3) ; isValid && (i < (3*(index%3) + 3)); i++)
{
for(j = 3*(index/3); isValid && (j < (3*(index/3) + 3)); j++)
{
for(m = (3*(index%3)) ; isValid && (m < (3*(index%3) + 3)); m++)
{
for(n = 3*(index/3); isValid && (n < (3*(index/3) + 3)); n++)
{
if(isValid && (a[m][n] == 0) || ((i != m) || (j != n)) && (a[i][j] == a[m][n])) //select given element and compare others to it
{ //if any element is the same that is not itself then the sudoku is not valid
isValid = 0; //this checks for 3x3 box
}
}
}
}
}
return isValid;
}
Basically what I did was just manipulate the index until it selected a specific box, and in that box I checked all numbers to see if there's any kind of match. If there is a match, the sudoku is invalid.
In the end, I checked the validity like this:
int checkSudoku(int a[][9]) //check every row, column and box
{ //if there is no contradiction then it is valid
int i, isValid = 1;
for(i = 0; isValid && (i < 9); i++)
{
isValid = (checkLine(a, i) && checkColumn(a, i) && checkBox(a, i));
}
return isValid;
}
Of course, the same concept can be applied to Java, considering it's just array management.
I want to place obstacles on a game board using a random number generator. 5% of the board will have a pit which is defined as "*", but the asterisk will not show unless the players lands in that spot; 10% of the board will be blocked spots indicated as "X"; the remaining 85% will be open spaces shown as "." The game board is a 10x10 array with the letter "P" at the upper left hand corner as the starting point for the player, and a "T" at the bottom right hand corner for the ending (treasure). So far I've got this, and I been watching video tutorials as well as reading to try and put this all together, but still stuck:
import java.util.Scanner;
import java.util.Random;
public class Adventure {
public static void main(String[] args) {
char grid[][]= new char[10][10];
Scanner move = new Scanner(System.in);
System.out.println("Here is the current game board:");
System.out.println("-------------------------------");
for(int i=0; i<grid.length; i++) {
for(int j=0; j<grid.length; j++) {
grid[i][j]='.';
grid[0][0]='P';
grid[9][9]='T';
System.out.print(grid[i][j]);
}
Random obstacle = new Random();
int obstacleNum;
for(int k=1; k<=100; k++) {
obstacleNum = 1+obstacle.nextInt(100);
}
System.out.println("");
}
System.out.printf("Enter your move (U/D/L/R)>");
}
}
Not sure where to go after "obstacleNum = 1+obstacle.nextInt(100);"
If your game board has 100 spots, then it will have 5 pits, 10 blocks, and 85 open spaces.
Choose 15 random numbers from 1 to 100; the first 5 identify the pits, and the next 10 identify the blocks.
Create a list to keep track of the 15 numbers. Each time you choose a random number, check to see if the number is already present to the list. If it is, discard it and choose a different random number. Otherwise add it to the list and continue until you've chosen all 15 numbers.
As for the actual interactivity, here is an outline:
x = 0; //coordinates of player, location of P
y = 0;
To hide the pits, before printing, stick in and if statement:
if(grid[i][j]=='*') {
System.out.println("."); //looks like ordinary land
} else {
System.out.println(grid[i][j]);
}
Now have this run when it receives input (pseudo)
//following if for moving left
if(grid[y][x+1] isn't out of bounds and right key is pressed and grid[y][x+1]!='X') {
grid[y][x] = '.'; //removes current position
x++; //change location
}
//following if for moving right
if(grid[y][x-1] isn't out of bounds and left key is pressed and grid[y][x-1]!='X') {
grid[y][x] = '.'; //removes current position
x--; //change location
}
//following if for moving down
if(grid[y+1][x] isn't out of bounds and down key is pressed and grid[y+1][x]!='X') {
grid[y][x] = '.'; //removes current position
y++; //change location
}
//following if for moving up
if(grid[y-1][x] isn't out of bounds and up key is pressed and grid[y-1][x]!='X') {
grid[y][x] = '.'; //removes current position
y--; //change location
}
if(grid[y][x] == '*') { //when trapped in a pit
System.out.println("You fell in a pit. Game over.");
} else {
grid[y][x] = 'P'; //update grid
}
Do you need a fixed amount of obstacles? You are better off putting the code in your loop that defines your the board:
for(int i=0; i<grid.length; i++) {
for(int j=0; j<grid.length; j++) {
int random = Math.random();
if (random <.05){
grid[i][j]='*';
}else if (random < .15) {
grid[i][j]='X'
}else {
grid[i][j]='.';
}
System.out.print(grid[i][j]);
}
}
grid[0][0]='P';
grid[9][9]='T';
Also you should put the cod just above define P and T outside the loop afterwards as it seems it only needs to be done once.
EDIT: this method will give you a representation of the game board, to cover the *, you can either change the print method to print them as . Or maintain a display grid, as well as the actual grid (eg make 2 grids)