In this tutorial I do something kind of crazy. I try to teach programming logic by writing code right out of my head. You probably won’t understand everything in this video, but that’s OK.
I continue making a simple game in Java. I specifically make a method that allows my monsters to move on the game board without landing on each other and blocks them from falling off the board.
If you missed part 1 definitely check out Java Video Tutorial pt 1.
The code follows the video. It is heavily commented and will help you better understand the video, so definitely look at it.
If you like videos like this share it
Code From the Video
MONSTERTWO.JAVA
import java.util.Arrays; import org.apache.commons.lang3.ArrayUtils; // Basic class definition // public means this class can be used by other classes // Class names should begin with a capital letter // A file can't contain two public classes. It can contain classes that are not public // If you place class files in the same folder the java compiler will be able to find them public class MonsterTwo{ // Creates a multidimensional array of chars static char[][] battleBoard = new char[10][10]; // This static method builds an empty battle board public static void buildBattleBoard(){ // Cycles through the array and gives a default value of * to everything for(char[] row : battleBoard) Arrays.fill(row, '*'); } // Redraws the board public static void redrawBoard() { int k = 1; while(k <= 30){ System.out.print('-'); k++; } System.out.println(); for(int i = 0; i < battleBoard.length; i++) { for(int j = 0; j < battleBoard[i].length; j++) { System.out.print("|" + battleBoard[i][j] + "|"); } System.out.println(); } k = 1; while(k <= 30){ System.out.print('-'); k++; } System.out.println(); } // Class Variables or Fields // You declare constants with final public final String TOMBSTONE = "Here Lies a Dead monster"; // private fields are not visible outside of the class private int health = 500; private int attack = 20; private int movement = 2; // Monitors whether the monster is alive or dead private boolean alive = true; // public variables are visible outside of the class // You should have as few as possible public fields public String name = "Big Monster"; public int xPosition = 0; public int yPosition = 0; public char nameChar1 = 'B'; public static int numOfMonsters = 0; // Class Methods // Accessor Methods are used to get and set the values of private fields public int getAttack() { return attack; } public int getMovement() { return movement; } public int getHealth() { return health; } public boolean getAlive() { return alive; } // You can create multiple versions using the same method name // Now setHealth can except an attack that contains decimals // When overloading a method you can't just change the return type // Focus on creating methods that except different parameters public void setHealth(int decreaseHealth) { health = health - decreaseHealth; if (health < 0) { alive = false; } } public void setHealth(double decreaseHealth) { int intDecreaseHealth = (int) decreaseHealth; health = health - intDecreaseHealth; if (health < 0) { alive = false; } } public void moveMonster(MonsterTwo[] monster, int arrayItemIndex) { // isSpaceOpen will be used to track whether the space the // monster plans to move into is occupied boolean isSpaceOpen = true; // Define the maximum x and y for the battle board // It's 1 less because the array index starts at 0 int maxXBoardSpace = battleBoard.length - 1; int maxYBoardSpace = battleBoard[0].length - 1; // while loop used to make sure I don't move a monster // into an occupied space while(isSpaceOpen) { // Randomly generate move direction N, S, E, or W int randMoveDirection = (int) (Math.random() * 4); // Randomly generate move distance based on max move distance int randMoveDistance = (int) (Math.random() * (this.getMovement() + 1)); // Prints move distance and move direction System.out.println(randMoveDistance + " " + randMoveDirection); // Erase monsters character on the board by replacing it with a * battleBoard[this.yPosition][this.xPosition] = '*'; if(randMoveDirection == 0) { // Find new xPosition & yPosition based on the current position on the board // If statements won't allow monster to move off the board if((this.yPosition - randMoveDistance) < 0) { this.yPosition = 0; } else { this.yPosition = this.yPosition - randMoveDistance; } } else if (randMoveDirection == 1) { if((this.xPosition + randMoveDistance) > maxXBoardSpace) { this.xPosition = maxXBoardSpace; } else { this.xPosition = this.xPosition + randMoveDistance; } } else if (randMoveDirection == 2) { if((this.yPosition + randMoveDistance) > maxYBoardSpace) { this.yPosition = maxYBoardSpace; } else { this.yPosition = this.yPosition + randMoveDistance; } } else { if((this.xPosition - randMoveDistance) < 0) { this.xPosition = 0; } else { this.xPosition = this.xPosition - randMoveDistance; } } // monster.length returns the number of items in the array monster for (int i = 0; i < monster.length; i++) { // if statement skips checking the same monster position against itself if (i == arrayItemIndex) { continue; } // onMySpace receives the monster array, index for the object I'm // checking currently, and the index for the monster sent to // this function if(onMySpace(monster, i, arrayItemIndex)) { // If a monster tries to move to an occupied space the // while loop repeats after I break out of the for loop isSpaceOpen = true; break; } else { // There was no monster in the space so end the while loop isSpaceOpen = false; } } } // End of while loop // Set the value in the array to the first letter of the monster battleBoard[this.yPosition][this.xPosition] = this.nameChar1; } // Checks if one monster is trying to move into the same x/y position as // another monster public boolean onMySpace(MonsterTwo[] monster, int indexToChk1, int indexToChk2) { // Checks if the 2 monsters have the same x/y position if((monster[indexToChk1].xPosition)==(monster[indexToChk2].xPosition)&&(monster[indexToChk1].yPosition)==(monster[indexToChk2].yPosition)) { // If they are equal return true so a new x/y position is calculated return true; } else { // If false I know the x/y position isn't occupied return false; } } /* The Constructor * Code that is executed when an object is created from this class definition * The method name is the same as the class * The constructor is only executed once per object * The constructor can't return a value */ public MonsterTwo(int health, int attack, int movement, String name) { this.health = health; this.attack = attack; this.movement = movement; this.name = name; /* If the attributes had the same names as the class health, attack, movement * You could refer to the objects fields by proceeding them with this * this.health = health; * this.attack = attack; * objectFieldName = attributeFieldName; */ // Define the maximum x and y for the battle board // It's 1 less because the array index starts at 0 int maxXBoardSpace = battleBoard.length - 1; int maxYBoardSpace = battleBoard[0].length - 1; // The random starting position for a monster int randNumX, randNumY; // We use a do loop because we always want to define a start // position for each monster do { // Calculate start position based on max board space randNumX = (int) (Math.random() * maxXBoardSpace); randNumY = (int) (Math.random() * maxYBoardSpace); } while(battleBoard[randNumY][randNumX] != '*'); // Only allow monster to start on a space with a * on it // Assign x and y position to the object that called this method this.xPosition = randNumX; this.yPosition = randNumY; // Assign character in the array based on the first initial // of the monsters name charAt(0) returns first letter of name this.nameChar1 = this.name.charAt(0); // Put first character of monster in the array battleBoard[this.yPosition][this.xPosition] = this.nameChar1; numOfMonsters++; // Adds 1 to the number of monsters on the board } // You can overload constructors like any other method // The following constructor is the one provided by default if you don't create any other constructors // Default Constructor public MonsterTwo() { numOfMonsters++; // Adds 1 to the number of monsters on the board } public static void main(String[] args) { } }
LESSONTEN.JAVA
import java.util.Arrays; import org.apache.commons.lang3.ArrayUtils; // Basic class definition // public means this class can be used by other classes // Class names should begin with a capital letter // A file can't contain two public classes. It can contain classes that are not public // If you place class files in the same folder the java compiler will be able to find them /* The Goal of this tutorial is to make a game like this ------------------------------ |*||*||*||*||*||*||*||*||*||*| |*||*||*||*||*||*||*||*||*||*| |*||*||*||*||*||*||*||*||*||*| |*||M||F||*||*||*||*||*||*||*| |*||*||*||*||*||*||*||*||*||*| |*||*||*||*||*||*||*||*||*||*| |*||*||*||*||*||*||*||*||*||*| |P||*||*||*||*||*||*||*||*||*| |*||*||*||*||D||*||*||*||*||*| |*||*||*||*||*||*||*||*||*||*| ------------------------------ [9,9] */ public class LessonTen { public static void main(String[] args) { MonsterTwo.buildBattleBoard(); // char[][] tempBattleBoard = new char[10][10]; // ObjectName[] ArrayName = new ObjectName[4]; MonsterTwo[] Monsters = new MonsterTwo[4]; // MonsterTwo(int health, int attack, int movement, String name) Monsters[0] = new MonsterTwo(1000, 20, 1, "Frank"); Monsters[1] = new MonsterTwo(500, 40, 2, "Drac"); Monsters[2] = new MonsterTwo(1000, 20, 1, "Paul"); Monsters[3] = new MonsterTwo(1000, 20, 1, "George"); MonsterTwo.redrawBoard(); for (MonsterTwo m : Monsters) { if(m.getAlive()) { int arrayItemIndex = ArrayUtils.indexOf(Monsters, m); m.moveMonster(Monsters, arrayItemIndex); } } MonsterTwo.redrawBoard(); } }
getting an error:
“Exception in thread “main” java.lang.Error: Unresolved compilation problem:
ArrayUtils cannot be resolved”
in this line…
“int arrayItemIndex = ArrayUtils.indexOf(Monsters, m);”
You need to install the ArrayUtils library. I show you how in this article How to install Java libraries That will fix the error
okay, working now…
thanks..
I understand the need for ‘this.’ in front of member variables when you need to disambiguate member variables from method arguments of the same name. You seem to use ‘this.’ in many places where they are not strictly necessary. Is this just a personal preference (possbily to help remind you that what follows is a member variable) or is there another reason?
Also, thanks for the great videos. I’m actually watching the videos and translating your code into C++ as a vehicle to learn C++ programming. Working out very well (so far)!
I over did it with this in these early videos. You are correct that they aren’t normally needed except in the situation you mentioned. For some reason people get confused by this so I wanted to make sure the used it when needed even if it was over used. In later tutorials I stop doing that.
I’ll eventually make a c++ tutorial. I just want to finish java first. I wish I would have made complete tutorials in the past like I do now. C++ will be covered completely as well when I get to it.
I have the exact same code… i think, yet my board is not drawn properly. It just prints a single row with all the symbols from the board.
Feel free to skip to the next tutorial in the series. I review everything as it continues
Omar,
I think your problem is that you are using println() instead print() in both while loops: while(k <= 30){ System.out.print('-'); k++; }
Also try double quotes instead of single quotes in System.out.print('-'); I don't why that last part let it work for me, but it worked.
Hi Derek,
In your code you have:
// Randomly generate move direction N, S, E, or W
int randMoveDirection = (int) (Math.random() * 4);
I haven’t run the program to see the functionality of it yet. But shouldn’t it be (Math.random() * 5; since there are 4 directions a monster can move? In earlier tutorials I believe you indicated that when using Math.random() it must be one value above the numbers you wish to generate.
Great tutorials, by the way. I’m loving it!
You may be correct. I can’t remember this tutorial very well. I didn’t particularly like the way parts 8 and 10 came out.
I constantly try new ways of teaching. Here was one of the first times I started to program 100% out of my head. I was trying to teach the way a person thinks when programming. I think I failed here, but eventually by doing this I have succeeded in later tutorials.
I now regularly program 100% out of my head. I hope that in trying to improve my overall tutorials, that you don’t feel that you have wasted your time. I promise that aside from parts 8 and 10 that the rest of the tutorial series is very good. At least they are as good as I could make them. I hope that makes sense
You are awesome Dude. Keep doing this.
Thank you 🙂 Ill keep covering java until I’ve covered everything
Your tutorials are really awesome!!! I just wish you could provide some kind of practice questions or task after a series of tutorials so that would be great..
Any ways you are great man!! Cheers
Thank you 🙂 Sorry I didn’t do that in the past. I have been practicing with ideas on how I could provide homework and make the videos more interactive.
Java Video Tutorial 10 is not working… Is there anyway you can get it back up?
Feel free to skip it all together. The rest of the tutorial is much better. I consider parts 8 and 10 to be failed experiments. Sorry about that.
Hi Derek,
Thank you very much for the great tutorials. You are making the world to be a better place and I really appreciate your hard work.
I have a request from you. I understand your tutorials. But, how can we practice. I mean to have problems to think on our own as an assignments.
Thank you.
You’re very welcome 🙂 For practice one path would be to look at my Android development tutorials. I make one app after another there.
I thought of the Java tutorial as a type of video API. I thought the best way to watch it was to print out the code and then take notes as you watch in your own words. Then you could go back and use what you learned for anything.
In the Android tutorials I have started to teach while making apps. This is much harder for me, but people seem to enjoy that style. I’ll continue to try and get better 🙂
Hi Derek,
Don’t keep saying this Lesson 10 is a “failure”….I don’t think this “over kill” coding of the fly is bad at all. I enjoy it a lot.
You showed an excellent coding practice, based upon your rich experience.
James
Thank you 🙂 I just thought it was a mistake to cover logic when I had very limited tools to work with at this point. I’m glad you found it useful.
what does the Arrayutils.indexof() do ??
and thanks for everything man , keep going !!
You’re very welcome 🙂 It finds the index for a specific value that you provide