here's the deal, I have to make a game that resembles PacMan, with a map, points, ghosts, etc.
The whole thing works as an array[8][8], it reads the positions of walls and the initial position of ghosts from a .txt file, PacMan starts at a fixed location and Fruits are random. Any blank space at the beginning of the game gets filled with a simple point pellet.
I've got the map done, it shows it and everything, but I can't seem to come up with a method that allows the player to control PacMan with the keyboard... This is what I've tried so far...
In the Player class
BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
String mov = read.readLine();
if (mov.equals("w"))
{
PacMan.MoveU();
}
It then repeats that for the other movement keys.
The individual Move methods in PacMan class look like this
public static void MoverR()
{
for (int i=0;i<Tablero.length;i++)
{
for (int j=0;j<Tablero.length;j++)
{
if (Tablero[i][j] instanceof PacMan)
Tablero[i][j]=null;
Tablero[i][j+1]=new PacMan();
}
}
}
}
This obviously isn't working, so I'm wondering if anyone can help me with a more efficient way to do this? I really don't mind starting these two classes from scratch...
Thanks.
It always gives me an ArrayOutOfBounds Exception
The ArrayOutOfBounds Exception is caused by Tablero[i][j+1]=new PacMan(); when j == 7, because you try to access to an invalid position (Tablero[i][8]).
anyone can help me with a more efficient way to do this?
You don't need to check the whole array to find out the position of Pacman, you could store the position as a private variable of Pacman, but in that case you shouldn't create a new instance of Pacman every time you need to move it, like you are doing with your current implementation.
One reason why you get ArrayOutOfBoundsException is the fact that in your loop you're moving PacMan to position [i][j +1], where j + 1 may be greater than array length.
You need to check if j + 1 < Tablero.length when you're 'moving' PacMan.
Also you can simply move the same instance of PacMan instead of creating a new one:
...
if (Tablero[i][j] instanceof PacMan) {
if (j + 1 < Tablero.length) {
Tablero[i][j+1] = Tablero[i][j];
Tablero[i][j] = null;
}
}
Related
As a preface, I have searched the forums but found nothing relating to my specific situation. I just started learning Java about a week ago, and this is my first foray into object oriented programming.
I'm building a basic game (think somewhat like Space Invaders when it comes to mechanics). I have a "Projectile" class, a "FallingThings" class (which is the parent class to the classes I have for objects falling down (Money, Friend, Enemy)). Each projectile that is shot is stored in an ArrayList, and as is every instance of Money, Friend, and Enemy (each in their own ArrayList).
The problem happens when I implement collision detection. First off, it takes multiple bullets to make the collision mechanism work (I think I might have just messed up some numbers here but I'm not 100% sure). Now, sometimes after I fire multiple bullets (and they are long gone), a collision is detected without me firing another bullet and a FallingThings object disappears from the screen. Also, at other times, multiple objects disappear at once. The weirdest thing is that all this is inconsistent, and not always reproducible in the same fashion. However, my collisions with the player character work perfectly.
Anyone have some ideas as to how I can fix this? My code is below:
Method in the "FallingThings" class (the ArrayLists are defined in the StartingClass (the main class)).
public void checkBulletCollision(Rectangle rectangle) {
for (int j = 0; j < Character.getProjectiles().size(); j++) {
Projectile p = (Projectile) Character.getProjectiles().get(j);
if (p.isVisible() == true) {
for (int i = 0; i < StartingClass.getMoneys().size(); i++) {
Money m = (Money) StartingClass.getMoneys().get(i);
if (m.getR().intersects(rectangle)) {
m.remove(i);
System.out.println("bullet collision");
}
}
for (int i = 0; i < StartingClass.getEnemies().size(); i++) {
Enemy e = (Enemy) StartingClass.getEnemies().get(i);
if (e.getR().intersects(rectangle)) {
e.remove(i);
}
}
for (int i = 0; i < StartingClass.getFriends().size(); i++) {
Friend f = (Friend) StartingClass.getFriends().get(i);
if (f.getR().intersects(rectangle)) {
f.remove(i);
}
}
}
}
}
My update method for projectiles:
public void update() {
y -= speedY;
if (y < 0) {
visible = false;
}
rectangle.setBounds(getRectangle());
}
I've been trying to fix this for the entire day, and still can't get a proper implementation. I have tried using ListIterator, but that caused the program to freeze and a typecasting error to be thrown.
Thank you so much for the help! =)
I suspect you are having problems because you are removing items from the list by index while looping over that list. Removing items causes the index counter to get out of allignment. Try use an actual Iterator. No need to even think about indexes. The Iterator has a remove method for these situations..
Iterator<Enemy> iterator = StartingClass.getEnemies().iterator();
while (iterator.hasNext()) {
Enemy e = iterator.next();
if (e.getR().intersects(rectangle)) {
iterator.remove();
}
}
I don't understand what m.remove does, you get the item from the list but then call "remove" on the item. do you want to delete it from the List instead?
StartingClass.getMoneys().remove(i);
Looks like the issue is that you are letting all types of loops to run. So even after removing a Money with your Projectile, you are on to removing and Enemy and a Friend also with the same Projectile - which is possible if that Projectile is fired from anything bigger or from a .44 magnum.
Anyway, to me, looks like you need to break your iteration once you remove one item with one projectile.. so your code should be like(Use generics and enhanced for loops) :
foreachprojectile:
for( Projectile projectile : Character.getProjectiles()){
if (projectile.isVisible() == true) {
Iterator<Money> iterator = StartingClass.getMoneys().iterator();
while (iterator.hasNext()) {
Money m = iterator.next();
if (m.getR().intersects(rectangle)) {
iterator.remove();
projectile.setVisible(false); // or any other method that does similar
break foreachprojectile; //Found a hit, so do not
//look for any more hits with current projectile
}
}
//And so on..
}
}
Above code probably will get done what you are looking for; but this logic can be encapsulated better to clearly communicate the intent.
I figured out what was wrong and fixed the problem. It turns out that the issue was not in my implementation of the for loops (although using a listIterator is still more efficient and less error-prone, so I've still opted to change that aspect of my code), but rather in the implementation of my collision detection. I forgot that the projectile and rectangle (for the projectile) are two different objects, and as such, the rectangle was not moving with the projectile, resulting in all sorts of problems.
I determined the issue by painting the rectangle to the screen to check how it behaved, and sure enough, it just stayed in one place, not moving with the projectile. I made some changes to the projectile's update() method so that when called, the rectangle moves with the bullet. This resulted in proper collision detection and a functioning program!
Thank you so much to everyone for all the help, I learned a lot here about writing efficient code and debugging techniques! I really appreciate it! =)
OK, so I created a console app that, among other things, takes an array of numbers and prints them out one by one, line by line. Now, I have to take the class that I created for that console app, and pop it into a separate GUI app we're creating. I have all of the other methods working fine, but for the life of me I cannot get the array method to print out correctly. It just gives me the last number I typed into the text field. I'm hoping someone can give me a nudge to help me figure this part out so I can move along, and get to the whole SpringLayout stuff, (the main part of the new assignment) I am limited in what I can show you here because this is a current assignment, so I will have to stick to this stuff as specifically as I can. And please, don't just post the code as an answer, (because then I can't use it), thanks.
Here's what I had for my original project for the array method:
int [] getArray(int x)
{
breakUpNum(x);
return numAry;
}
From there, inside my new class I have this, in an attempt to get it to print:
private class ButtonTest implements ActionListener
{
public void actionPerformed(ActionEvent ae)
{
Lab1 tester = new Lab1();
int[] test4 = tester.getArray(num);
for(int i = 0; i < test4.length; i ++)
{
crossTest.getArrCross.setText("" + test4[i]);
}
}
}
Any help pointing me in the right direction would be greatly appreciated, thanks!
setText does just that, sets the text you pass to as the current text content, it does not append it.
If you were to use JTextArea, you could use it's append method...however, for a JTextField you need to have a different approach.
Now you could use getArrCross.setText(getArrCross.getText() + test4[i])...but to quite frank, that's rather inefficient, as each call to setText is going to stage a paint event...
StringBuilder sb = new StringBuilder(128);
for(int i = 0; i < test4.length; i ++)
{
sb.append(test4[i]);
}
crossTest.getArrCross.setText(sb.toString());
Now, if you want to separate each element, you need to add
if (sb.length() > 0) {
sb.append(", ");
}
Before sb.append(test4[i]);
The last bit of actionPerformed in the for loop isn't working right. setText replaces the current text with its argument, and it doesn't seem like you want to do that. To fix it, replace the line in the for loop with this:
crossTest.getArrCross.setText(crossTest.getArrCross.getText() + test4[i]);
I created two methods for my Bingo Game in Java. One method creates a new board which populates the Bingo Board with integers according to the Bingo rule (1-75). My second method generates random numbers with a range of 1 - 75.
public static int drawNum(){
Random rand = new Random();
int num = rand.nextInt(75)+1;
return num;
}
public static void bingoCard(){
int [][]card=new int [5][5];
ArrayList<Integer> alreadyUsed = new ArrayList<Integer>();
boolean valid = false;
int tmp = 0;
for(int i = 0; i <= 4; i++){
for(int row = 0; row < card.length; row++){
while(!valid){
tmp = (int)(Math.random() * 15) + 1 + 15 * i;
if(!alreadyUsed.contains(tmp)){
valid = true;
alreadyUsed.add(tmp);
}
}
card[row][i] = tmp;
valid = false;
}
}
card[2][2] = 0;
//create array to make title.
String title []={"B","I","N","G","O"};
for(int i=0;i<title.length;i++){
System.out.print(title[i]+ "\t");
}
System.out.println();
for(int row=0;row<card.length;row++){
for(int col=0;col<card[row].length;col++){
System.out.print(card[row][col]+ "\t");
}
System.out.println();
}
}
What I need help with is, how do I check whether or not the drawNum() method corresponds to any values stored inside my bingoCard() array? If so, print out a new array with the integers filled in. If the condition is met for a bingo, then you win.
I hope I don't make it sound like I want you to do it for me, but I am confused as to how to start coding that part. Thank you.
This my recommendation - Learn Object Oriented Programming immediately
I see you are using objects provided in the JDK, so why not learn to make your own?
Make two classes with the following methods (-) and members (+) (PS. This is not a formal way to document code)
BingoCard
+list of numbers on card
-reset() : gets new numbers for this card
-test(BingoDrawer) : Tests to see if this card won on this drawing
-toString() : returns a String representation of this card
BingoDrawer
+list of numbers drawn
-reset() : draws new numbers
-hasNumber(int number) : tests if this number was drawn
-toString() : returns a String representation of this drawing
One more suggestions
Instead of keeping track of what you used, keep track of what you have not used, it will make things much easier because you can just choose stuff from that list randomly. Unlike your current action which is choosing (a logical number) from thin air and hoping (which causes issues) it is not a collision
If you follow my recommendation you can write code like this
public static void main(String[] args) {
BingoCard bc = new BingoCard();
BingoDrawer bd = new BingoDrawer();
while(thePlayerWantsToPlay()) { //function to be defined by you
bc.reset();
bd.reset();
System.out.println(bc);
System.out.println(bd);
System.out.println(bc.test(bd));
}
}
You can take it a step further and make a BingoGame class and do what I did in main there and just create an instance of BingoGame and call some start method on the object.
For checking if you have the number in your board, read through the board in a similar manner as you do for the already_used numbers, except with the number the user just entered.
The conditions for the user to win should be checked after the board has another number guessed.
There are a few ways to do this, a simple one would be to iterate over every possible pattern that could win, checking to see if there are tokens there.
All of this would be in a loop, that goes a little like this:
Set up board via user entering numbers.
Start loop
set either a timer to wait for, or wait for a keypress (so the game doesn't just play really fast)
Get random number
Possibly add to board
Check if winner
if winner, break the loop and do something else.
Print the new board out.
(end of loop)
If they got here, that could mean they won!
Wait to exit
You can just write it out as pseudo-code and fill in the methods after that. It usually helps to work on these things in a top-down fashion. So, for bingo you might have:
board = generateBoard();
while (!bingoFound(board)) {
number = drawNumber();
board = stampNumbers(board, number);
}
If that makes sense, you can go a step deeper and define each method. For example, bingoFound might look like:
public boolean bingoFound(int[][] board) {
boolean wasFound = bingoRowFound(board)
|| bingoColFound(board)
|| bingoDiagonalFound(board);
return wasFound;
}
Again, I've defined everything in (mostly) pseudo-code. If this looks ok, you can move a step deeper. Let's define the bingoRowFound method.
public boolean bingoRowFound(int[][] board) {
for (int row = 0; row < NUM_ROWS; row++) {
boolean rowIsABingo = true;
for (int col = 0; col < NUM_COLS; col++) {
// We have to check that everything up until this point has
// been marked off. I am using -1 to indicate that a spot has
// been marked.
rowIsABingo = rowIsABingo && board[row][col] == -1;
}
if (rowIsABingo) { return rowIsABingo; }
}
return false; // If we didn't find a bingo, return false.
}
Some of the methods (like drawNumber) will be really easy to implement. Others, like looking for a diagonal bingo might be a bit more difficult.
Feb 12 2014 Update:
Retracted code, since this was a college course assignment, and I want to prevent people just copying the code. I almost got in trouble for being accused of sharing code (which is a nono in assignments) when another student lifted my code from my Github repo and sent it in as their own.
There were two classes, one main class and a class to hold my methods and constructors.
BINGOFINAL.java was my main class.
Bingo_Card.java held my constructor and methods.
If you want to run this, make sure you create a new project called BINGOFINAL, and put Bingo_Card.java into that same */src/ extension.
I have an 2d array that represent a tic tac toe board.
And empty box is just "" ;
My current game board is saved in ar1 which is 2d string array.
I want to make an array of game boards which is array of 2d array = 3d array.
So I guess it would be like that:
String[][][]ar3 = new String[80][9][9]; // array of game boards
for(int k=0;k<ar3.length;k++)// filling the array with the current game board
{
ar3[k] = ar1;
}
Yea I want 80 boards and the game would be 9x9.
Till now everything is fine .. but now I would like to look on the game board(ar1) and make every possible move on the ar3.
So for every possible move I got a board on ar3.
For that I would create an array that would contain the empty indexes on the board which is every possible move on ar2:
int[][]ar2 = new int[81][2]; // contains blank boxes indexes
int line = 0;
for(int k=0;k<SIZE;k++) //finds blank boxes indexes and adding to the array
for(int j=0;j<SIZE;j++,line++)
{
if(ar1[k][j].equals(""))
{
ar2[line][0] = k;
ar2[line][1] = j;
}
else
{
ar2[line][0] = -1;
ar2[line][1] = -1;
}
}
As you can see in case that the box has something else then "" which is X or O then I put -1
This code is doing what I want but here comes the problem now I will try to generate all the possible moves which stored in ar2 in ar3:
String[][][]ar3 = new String[80][9][9]; // array of game boards
for(int k=0;k<ar3.length;k++)// filling the array with the current game board
{
ar3[k] = ar1;
}
for(int k=0;k<ar3.length;k++)// making a move
{
int i1 = ar2[k][0];
int i2 = ar2[k][1];
if(!(i1 == -1 || i2 == -1))
if(num%2==0)
ar3[k][i1][i2] = "X";
else
ar3[k][i1][i2] = "O";
}
I have no idea why instead of making a single move for each board , for each index in ar3 it's making all of the moves for all of the boards .. for example (I will demonstrate on a 3x3 board)
^ means empty
The board before looks like this:
^ ^ ^
^ X ^
^ ^ ^
but after the "move" i'm trying to make (let's say 0,0)
all of the boards looks like this:
O ^ ^
^ X ^
^ ^ ^
Instead just of the first 1... and then I'm doing the same thing with diffrent indexes for the second board (ar3[1]) but it affects all of the boards.. (ar3[0-k]) so eventually I got 80 boards which are the same.
Any one got an idea?
Why it changes all of the boards?instead just the one on the K index?
Thanks!
I'm not sure I understand the code fully, so this is a wild guess, but:
In the first excerpt you're giving all slots in ar3 a reference to the same object, ar1. This means that if you change ar1's contents, you'll see that change across all ar3 items because all those items are references to the same object. You could check to see whether this is your problem.
Now, as a comment, I'd advise you to start doing two things that help me personally in these cases: The first is to give your identifiers as meaningful names as possible, so much that comments aren't really needed to understand what's what. The second is to take advantage of the fact that you're writing in a language like Java and try to write your code in a more object oriented fashion. For instance, if, instead of a 3D array, you have a normal array of (say) GameBoard objects, each of which contains its 2D information, it could have a very positive effect in making any "suspicious" code patterns (that don't correspond to your actual intention, that is) more apparent.
I am creating a game using a 10x10 2D array. The player starts at the top left hand corner indicated as "P" and the objective is to get the player to avoid obstacles to get to the treasure indicated as "T" located in the lower right corner.
How would I go about making the player move about the grid using commands Up/Down/Left/Right?
Would I use a for loop to count through the elements in the array to designate the move?
Here is what I have so far:
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++) {
double random = Math.random();
if(random <=.05) {
grid[i][j]='*';
}
else if(random > .06 && random <= .15) {
grid[i][j]='X';
}
else {
grid[i][j]='.';
}
grid[0][0]='P';
grid[9][9]='T';
System.out.print(grid[i][j]);
}
System.out.println("");
}
System.out.print("Enter your move (U/D/L/R)>");
}
}
you should keep track of the current position of the player and just update those variables.
initial values would be (0,0) as you said.
int px = 0;
int py = 0;
when a move is made, update the variables accordingly:
grid[px][py] = <empty cell>;
switch (move) {
case 'u': py += 1; break;
case 'r': px += 1; break;
...
}
grid[px][py] = 'P';
of course you shouldn't just updated the values "blindly", you should insert some validation logic to follow the rules of the game:
if (grid[px][py] != <obstacle> )
// update player coordinates...
Looks like you're using row-major ordering, judging from the way your board prints out. Based on that, here's what you'll need to do:
First, you need to store the player's position somewhere. Right now it's hardcoded to 0,0.
Second, you need to read in the player's move. That will have to happen in a loop, where you get a move, check if the move is allowed, perform the move, and display the results.
Third, you need to be able to calculate the new position based on the move. Up means row -= 1. Right means column += 1. Etc.
Given the new coordinates, you need to make sure the move is valid. At the very least, you have to stop them from walking off the board, but you may also prevent them from entering a square with an obstacle, etc.
Once you know that the move is valid, you have to update the variables you're storing the current coordinates in.
At the end of the loop, you'll need to redraw the board.
That's the basic gist of it. Right now you are doing everything in main(), and that's okay, but if it were me I would start to split things out into separate methods, like InitializeBoard(), GetNextMove(), CheckIfMoveIsValid(int r, int c), and so on. That way, main() becomes a high-level view of your game loop, and the guts of the different operations are compartmentalized and more easy to deal with. This will require storing off things like your game board into class variables rather than local variables, which should actually make things like obstacle detection easier than it would be currently.
All of the above answers are great. Here are a few suggestions I would make:
Instead of a char two-dimensional array, I would make a custom object, such as Space, and define a two-dimensional array of Spaces (eg, Space[][]). There are a few reasons for this:
You can define a space in a variety of ways (rather than just 1 character). For example, Space[i][j].hasTreasure() can return a boolean to let you know whether or not you found the treasure.
If you want to add functionality later, its as easy as adding an attribute to your Space class. Again, you are not limited to one character here.
More to your question of movement, I would also recommend a few things. Similar to redneckjedi's suggestion of a CheckIfMoveIsValid() method, I would pass the grid and move direction as parameters and return a boolean. To ensure that you do not end up with ArrayIndexOutOfBounds issues, I would also suggest adding a row/column of walls on each side. I would widen the grid out to 12x12 and put a strip of obstacle-type blocks around the outside. This will ensure that you cannot step outside of the grid as hitting a wall will always return 'false' on a valid move.