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)
Related
I am confused on how to print the location of the player in this array and have it update every time an input is plugged in for the direction it is moving? Currently I only get the - symbol in a 10 by 10 pattern but would like (0,0) to be an X where the player starts.
private final static int SIZEX = 10; // Board size
private final static int SIZEY = 10; // Board size
int[][] gameboard = new int[SIZEX][SIZEY];
for(int i=0; i<gameboard.length; i++)
{
for(int j=0; j<gameboard.length; j++)
{
System.out.print("-");
}
System.out.println("");
}
Use an if statement (or ternary operator) in your inner loop to print X if i and j match the x and y coordinate of the player
You could add a KeyListener to your games Component and set the x and y if the input matches the one required to move the player arround and print the position once the key is released.
To really answer your question we would need some sort of fields you have that hold the current players position
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.
Hello I am creating a basic tic tac toe game for my own pleasure that has 4x4 fields I have the program pretty much completed but I am stuck on one part in my game i have to decide a winner if any x's or o's are grouped by 2x2 i already have the horizontal and vertical and diagonal algorithms to decide a winner completed
so for example if we have
x|x|o|o
x|x|o|x
| | |
| | |
X will be the winner since he has a 2x2 group
thank you for any help!
example code for my vertical winner code
public boolean checkForWin()
{
char symbol = SYMBOL[turn];
//check vertical win
Check1:
for(int i=0; i<BOARD_SIZE; i++)
{
for(int j=0; j<BOARD_SIZE; j++)
if(board[i][j] != symbol)
continue Check1;
//if reached, winning line found
return true;
}
//check horizontal win
Check2:
for(int j=0; j<BOARD_SIZE; j++)
{
for(int i=0; i<BOARD_SIZE; i++)
if(board[i][j] != symbol)
continue Check2;
//if reached, winning line found
return true;
}
//check back slash diagonal win q
for(int i=0; i<BOARD_SIZE; i++)
if(board[i][i] != symbol)
break;
else if(i == BOARD_SIZE-1)
return true; // winning line found
//check forward slash diagonal win
for(int i=0; i<BOARD_SIZE; i++)
if(board[i][BOARD_SIZE - i - 1] != symbol)
break;
else if(i == BOARD_SIZE-1)
return true; // winning line found
//if reach here then no win found
return false;
}
where would i input that code ?
Create a list of winning configurations each having 4 locations. There are 4 winning rows, 4 winning columns, 2 diagonals, and 9 blocks. Then just check each configuration.
Code would be roughly
// Set this up once at the start
WinningConfiguration[] allWinningConfigurations = {
WinningConfiguration.row(0),
...
WinningConfiguration.row(3);
WinningConfiguration.column(0);
...
WinningConfiguration.column(3);
WinningConfiguration.block(0,0);
...
WinningConfiguration.block(3,3);
WinningConfiguration.diagonal();
WinningConfiguration.reversedDiagonal();
}
..
// Now all your checks, (row, column, diagonal and blocks) become
for(WinningConfiguration config : allWinningConfigurations) {
boolean configWins = true;
for(int i=0; i<4; ++i) {
if(board[config.pts[i].x][config.pts[i].y]!=symbol) {
configWins = false;
break;
}
}
if(configWins)
return true;
}
return false;
And if you then want to add other winning combinations (say all four corners) you only need to add one row to your winning Configurations array and you're done.
There's further refactoring that could be done to make this neater too, like moving the check into the WinningConfiguration class so that the loop becomes
for(WinningConfiguration config : allWinningConfigurations) {
if(config.wins(symbol)
return true;
}
return false;
Think of it this way: EVERY winning 2x2 square will have a topleft corner. So if you see a mark, you can check to see if the square to the right, bottom, and bottomright are all the same type, and if so, marker that player a winner. Since you're starting your check on the topleft corner, you never need to put a starter check on the rightmost or bottommost lines (because you won't have a square extend outside your board!)
So for int i extending from 0 to BOARD_SIZE-1, and for int j extending from 0 to BOARD_SIZE-1, if board[i][j] == board[i+1][j] == board[i][j+1] == board[i+1][j+1] == symbol then you have yourself a winner.
There are a few things you could do beyond that to make it a bit more efficient, but since it's tic-tac-toe I don't think you're too concerned with scalability =)
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.
I am writing a method to switch the player number after each player's turn. I am using a boolean array that keeps track of the players still playing (that have not been eliminated). So the array at the beginning of the game is initialized to true and is the size of the number of players in the game. As players get eliminated, the corresponding value of the index gets set to false (For example if Player 2 gets eliminated, the third index of the array gets set to false). (Note: Player 0 does exist, so if two players are playing they are Players 0 and Player 1.) If the player number is equal to the last player, then it needs to start back at the beginning and find the first player that is still in the game. Otherwise, the player number increments to the first player that is still playing. Here is what I have:
public static int switchPlayer(int currentPlayer, boolean[] playerList) {
if(currentPlayer == playerList.length) {
for(int i = 0; i < playerList.length; i++) {
if(playerList[i] == true) {
currentPlayer = i;
break;
}
}
}
else {
for(int i = (currentPlayer+1); i < playerList.length; i++) {
if(playerList[i] == true) {
currentPlayer = i;
break;
}
}
}
return currentPlayer;
}
Any changes or suggestions? It is not quite working and cannot see where it is going wrong.
I have tried to implement one of the answers, but I cannot figure out how to get it implemented. Does anyone have a solution?
If you have Players 0,1,2,3. Then length is 4.
But the argument currentPlayer can only have 0-3 value, since thats the player numbers, so try changing this:
if(currentPlayer == playerList.length) {
for(int i = 0; i < playerList.length; i++) {
if(playerList[i] == true) {
currentPlayer = i;
break;
}
}
}
to:
if(currentPlayer + 1 == playerList.length) {
for(int i = 0; i < playerList.length; i++) {
if(playerList[i] == true) {
currentPlayer = i;
break;
}
}
}
What if you use an ArrayList data structure where you store all players that are currently not eliminated. So when a player is eliminated you remove that object from the ArrayList. This way you wouldn't need to use boolean to keep track of player status.
public static int switchPlayer(int currentPlayer, ArrayList playerList) {
// move to the next player
currentPlayer++;
// reset back to the first player if we reached the end player
if(currentPlayer >= playerList)
currentPlayer = 0;
return currentPlayer;
}
Now originally, in some part of your code I think you are setting the value "false" to indicate that the user has been eliminated. However, my idea is to remove the eliminated player. For example, if you want the second player to be eliminated, then you can do something like this in an array list:
list.remove(2);