Save all generation in Game of Life for later access - java

My Game of Life works perfectly. I also have a counter that shows the current generation (for each iteration generation++).
Now I want to be able to access and display any generation during the game. The whole game consists of a two-dimensional array (Cell[][]). So after each iteration, the respective array must be saved with a unique name.
But how can I save an array multiple times in a loop? I can't add the iteration-number to the array name like Cell[][] cells+generation = ... to become cells0, cells1, cells2... arrays.
Another idea was, to create a class generation and create a new object of this class for each iteration, but even then the problem of the name of the object generation remains (to be able to access the respective object, a unique name is required, e.g. generation13, generation154 ...).
public class Generation {
private Cell[][] cells;
public Generation(Cell[][] cells) {
this.cells = cells;
}
public Cell[][] getCells() {
return cells;
}
public void setCells(Cell[][] cells) {
this.cells = cells;
}
}
Does anyone have an approach on how to achieve this? I think that with the class generation makes the most sense, because this way you can also access (get) the constructor (two-dimensional array) for displaying.

What about making an ArrayList<Cell[][]>? So, If you want to add a new generation, just use
arrayListOfCells.add(generation);
And then access it with
arrayListOfCells.get(index);

You're almost there. Just add generation number to the Generation class.
public class Generation {
private final int generation;
private Cell[][] cells;
public Generation(int generation, Cell[][] cells) {
this.generation = generation;
this.cells = cells;
}
public Cell[][] getCells() {
return cells;
}
public void setCells(Cell[][] cells) {
this.cells = cells;
}
public int getGeneration() {
return generation;
}
}

Related

can variable have multiple enum constants in java?

I am building simple java game which the user has to find gold. There are some obstacles like Orc, Goblin, and Poop.
What I am trying to do is that I am creating Cell and Board class.
Inside of my Cell class,
public Cell{
public enum TheCell { Orc, Goblin, Poop, Gold, Empty};
TheCell type;
public Cell(TheCell type){
this.type = type;
}
}
and I make two dimensions in Board class,
public Board{
Cell[][] grid = new Cell[7][7];
Random r = new Random();
for(int i = 0; i<3; i++){
int randNum1 = r.nextInt(7);
int randNum2 = r.nextInt(7);
grid[randNum1][randNum2] = new Cell(Cell.TheCell.Orc);
}
for(int i = 0; i<3; i++){
int randNum1 = r.nextInt(7);
int randNum2 = r.nextInt(7);
grid[randNum1][randNum2] = new Cell(Cell.TheCell.Goblin);
}
}
My question is that, in case of Orc and Goblin are same cell, I wanna keep them both monster in same cell. Is there some how I can keep both or multiple obstacles in same cell? Thank you!
One way to achieve this is to have the Cell class hold a list of all monsters/things that are currently on the cell (using the enum, that is already available)
A more "low level" approach is to use an Integer for the cell and then use bitflags to model multiple obstacles on the same cell.
Update:
I agree with #ajb, in this case an Enum Set should be used
As pointed out by #JimGarrison, the EnumSet approach only works until you need to have more than one instance of an enum value for one cell.
public Cell{
public enum TheCell { Orc, Goblin, Poop, Gold, Empty};
List<TheCell> type = new ArrayList<TheCell>();
public Cell(TheCell type){
addType(type);
}
public addType(TheCell type) {
this.type.add(type);
}
}

When I create a 2D array outside of my constructor, I'm not able to resize it, but when I create one inside of it, I'm not able to access it

I'm trying to create a method which will create an object which contains a 2D boolean array, with int parameters as the number of rows and columns. Then inside the class, I have methods that try to grab the length and width of that array. The two ways I tried to solve this problem were:
public GameOfLife(int rows, int cols) {
boolean[][] society = new boolean[rows][cols];
}
public int numberOfRows() {
return society.length;
}
In my tests, this attempt was giving me the error that society cannot be resolved to a variable. Then I tried:
private boolean[][] society;
public GameOfLife(int rows, int cols) {
boolean[][] temp = new boolean[rows][cols];
society = temp;
}
EDIT: Oops, forgot to add my method for numberOfColumns:
public int numberOfColumns() {
return cols;
}
But the issue with this one was that it was returning 0 instead of 4 when I tried:
#Test
public void FailedTestingRowsAndCols(){
GameOfLife g1 = new GameOfLife(4,4);
assertEquals(4, g1.numberOfColumns());
}
I'm rather new to this, so I apologize if this is a dumb question, but I'm not really sure about all the details of where and when variables expire, which is giving me a lot of difficulties. THank you for any help!
When I create a 2D array outside of my constructor, I'm not able to resize it, but when I create one inside of it, I'm not able to access it
Take note that you will never be able to resize an array. An array once created has its size fixed. You are merely assigning your current array to reference to another newly created array (which gives you the illusion that you successfully resized it).
As for your question of not being able to access it is highly likely the variable you created exist within different scope.
You can use the following codes (which is very similar to yours), it works fine for me. Hence I am guessing your error does not actually comes from the code snippet you showed.
class TestRunner
{
public static void main(String[] args){
GameOfLife gol = new GameOfLife(5, 3);
System.out.println(gol.getColumns());
System.out.println(gol.getRows());
}
}
class GameOfLife
{
private boolean[][] society;
public GameOfLife(int rows, int cols){
society = new boolean[rows][cols];
}
public int getColumns(){
return society[0].length;
}
public int getRows(){
return society.length;
}
}
Output:
5
3
I don't see any problems with what you have posted so far. The below example works fine for me:
public class GameOfLife {
public static void main(String[] args) {
GameOfLife g1 = new GameOfLife(4,4);
System.out.println(g1);
}
private boolean[][] society;
#Override
public String toString() {
final StringBuffer sb = new StringBuffer("GameOfLife{");
sb.append("society=").append(society == null ? "null" : Arrays.deepToString(society));
sb.append('}');
return sb.toString();
}
public GameOfLife(int rows, int cols) {
boolean[][] temp = new boolean[rows][cols];
society = temp;
}
}

Java text based adventure game, what to put under my main method

I'm making a text based adventure game with java, im a first year computer science student.
I made a room, exit, creature, item and world class and put in the API that was given to me in the class. It was just basic methods and some constructors.
We're suppose to create a textAdventure class were we bring together all the other classes and create the game.
The player and game class was given to me and my professor did all the necessary code in order to make the game run in that class.
My problem is I don't know how to start in my TextAdventure Class, also thats where my main method is.
So I'm confused on how to make a starting room and how to put an exit in that room leading to another room.
Here's some code
public class MyTextAdventure {
private Room room1;
private Room room2;
private Room room3;
private Room room4;
private Room room5;
private Room room6;
private Room room7;
private Room room9;
private Room room10;
public static void main(String [] args){
}
If I wanted to make a player start in room1, can I just do this.
public static void main(String [] args){
public Room startingRoom;
}
I have already declared startingRoom in the room class.
I'm sorry if my skills are bad, I just have no idea what I'm doing and where to start.
Use an array to keep track of your rooms. This allows you to avoid having to keep track of 10 different variable names. It also allows you to do math on the array index. For example, if you wanted to set the current room from 3 to 4, you wouldn't have to check which room was set to current. You could just do currentRoom++
Try something like this.
public class MyTextAdventure {
private Room[] rooms; //array for all rooms
int currentRoom = 0;
boolean over;
//class constructor
public MyTextAdventure() {
rooms = new Room[10]; //Initialize new room array of size 10
over = false; //game is not over yet
for(int i = 0; i < rooms.length; i++) {
//Initialize all rooms
rooms[i] = new Room();
}
}
public void start() {
//do your game loop in here
while(!over) {
}
}
}
public static void main(String [] args){
MyTextAdventure adventure = new MyTextAdventure();
adventure.start();
}
The main function should just start your game. Functions and classes should be designed to accomplish a singular task that is clear. Name classes, functions and variables so that you know exactly what they are doing.
Using the current room as an integer allows you to make use of it as an array index. For example if you want to get the current room you can do this for a function.
public Room getCurrentRoom() {
return rooms[currentRoom];
}

Copying Array from ArrayList Element

I'm building a Java based game in Swing, which is essentially a grid of Jbuttons
I have an Object called Cell, which is a custom JButton with additional parameters for storing objects. The game grid is represented by Cell[][]
I have an arraylist of type Cell[][] to allow me to store the state of the gamegrid after each move. If I want to undo the move, I need to copy the last element of the ArrayList to the game grid to allow it to be displayed on the UI.
My gamegrid is panelHolder and my arraylist is moveHolder.
So far I've tried Collections.copy(panelHolder, moveHolder.get(moveHolder.size())); which will not compile due to the "arguments not being applicable for the type Cell[][]"
I've also tried System.arraycopy(moveHolder.get(moveHolder.size()-1), 0, panelHolder, 0, panelHolder.length);, which throws and out of bounds exception. Initially I thought this was due to the moveHolder.size()-1, but even just as moveHolder.size() it has the same problem.
I've found numerous questions on StackOverflow and others that both show these two ways of doing it, but I can't seem to get it to work. Is there something more obvious I'm missing? Full class method below:
public class UndoClass implements MoveCommand{
public ArrayList<Cell[][]> moveHolder = new ArrayList<Cell[][]>();
public Cell[][] execute(Cell[][] panelHolder) {
if (moveHolder.size() > 0){
Collections.copy(panelHolder, moveHolder.get(moveHolder.size()));
if (moveHolder.size() > 0){
moveHolder.remove(moveHolder.size());
}
}
System.out.println("Move Undone. Undos available:" + moveHolder.size());
return panelHolder;
}
public void addMove(Cell[][] panelHolder){
moveHolder.add(panelHolder);
}
public ArrayList<Cell[][]> getMoves(){
return moveHolder;
}
}
Cell Class
public class Cell extends JButton {
int co_x = 0;
int co_y = 0;
ArrayList<Players> current = new ArrayList <Players>();
}
Just wanted to point our your execute(...) method accepts the Cell[][] both as a parameter and the return argument. That approach is going to force all of your commands to keep copying your input param arrays to the return statement array. Notice if you don't need to keep the two in sync and you just use the return arg, you don't have to worry about copying at all:
Cell[][] lastState = moveHolder.get(moveHolder.size()-1);
moveHolder.remove(moveHolder.size()-1);
return lastState; // Not updating the panelHolder array, just returning
But of course now the input parm and return are out of sync. Instead you might want to encapsulate that state into a single object to make your life easier. Something like this (note that the execute now returns a void):
public ArrayList<GameState> previousStates = new ArrayList<GameState>();
public void execute(GameState currentState) {
if (previousStates .size() > 0) {
GameState lastState = previousStates.get(previousStates.size()-1);
currentState.restoreFrom(lastState);
previousStates .remove(moveHolder.size()-1);
}
}
Good luck on the game!
if (moveHolder.size() > 0) {
for (int i = 0; i < panelHolder.length; i++) {
panelHolder[i] = moveHolder.get(moveHolder.size()-1)[i].clone();
}
moveHolder.remove(moveHolder.size()-1);
}
Try this. You need to make copies of each internal array when copying 2D arrays.
Try a Linked List
LinkedList<Cell[][]> ll = new LinkedList();
ll.removeLast();
panelHolder = ll.clone();

Creating weapon classes and a Combat Class

I am creating a text based game and I am having some issues.. This is what I have so far. So far I have a Combat Class, and two Classes for two different Weapons. I am trying to assign hit points to the weapons themselves. But my biggest issue is in the Combat class. I am trying to create it to were there will be random weapon drops at random times and also random Weapons. So far in the Combat class I have this:
public class Combat {
final int chanceOfDrop = 3;
static Weapons[] wepArray = {new M4(), new M16()}
static boolean[] hasWeapon = {false, true};
public static int ranNumberGen(int chanceOfDrop) {
return (int) (Math.random()*1);
}
private void enemyDead() {
boolean canDrop = false;
if(ranNumberGen(chanceOfDrop)==0){
canDrop = true;
}
if(canDrop == true){
givePlayerWeapon(Weapon[Combat.ranNumberGen(Weapons.length)]);
}
private static void givePlayerWeapon(int w) {
hasWeapon[w] = true;
for w <(Weapons.length-1) {
if has weapon[w] {
System.out.println(wepArray[w].getWeaponName);
}
}
}
}
}
}
I have issues when I am creating the new M4(), and the new M16() it says Type mismatch: cannot convert form M4 to Weapons. I do have a class named Weapons, could that be the problem?
And here is my M4 Class, both M4 and M16 Classes are identical
public abstract class M4 {
private Integer weaponDamage = 5;
private Integer weaponAmmo = 25;
private String weaponName = "M4";
public M4(String name, int ammo, int damage) {
name = weaponName;
ammo = weaponAmmo;
damage = weaponDamage;
}
public String getWeaponName() {
return weaponName;
}
public Integer getAmmo() {
return weaponAmmo;
}
public Integer getDamage() {
return weaponDamage;
}
}
I don't think I have any issues here. Maybe my problem lies within this though. Although, I have a Weapons class, but nothing in it. Do I need that?
A few things to fix at first sight:
Create a generic Weapon class that defines some properties that apply to each weapon, like name, damage, ammo, scope multiplier, etc... Then create subclasses for Weapon, like M4 and M16, that specify the properties and eventually add weapon-specific properties.
Add brackets to this line:
System.out.println(wepArray[w].getWeaponName); // Change to getWeaponName()
Remove the abstract keyword from M4.
Fix the ranNumberGen method because it will always return 0 right now. Math.random() returns a float in the range [0,1[. This means that casting it to an int will always result in 0. Multiply it by n to have a random int in the range of [0, n[. You probably want this:
public static int ranNumberGen(int max) {
return (int) (Math.random() * max);
}
Change this line:
givePlayerWeapon(Weapon[Combat.ranNumberGen(Weapons.length)]);
to:
givePlayerWeapon(wepArray[Combat.ranNumberGen(wepArray.length)]);
The syntax of a for-loop is like this:
for (variable-initialization; condition; increment)
So in your case, you want:
for (int i = 0; i < hasWeapon.length; ++i)
{
if (hasWeapon[i]) System.out.println(wepArray[i].getWeaponName());
}
You might want to revisit your decision to use an inheritance-style heirarchy for game objects before it is too late.
In practice, I've found a component-entity model and/or prototype model to be much more effective. You could take a look at the code in my old Java roguelike game Tyrant for inspiration:
Weapon definitions: mikera/tyrant/Weapon.java (Github is down right now so can't find the exact link, but should be easy enough to Google)
The idea is that you make your objects by setting properties / composing compoenents in a Map-like game object rather than using static inheritance.
When you want to create a random weapon in this model, you can just get a list of all the possible weapon prototypes, and clone one of them at random to make a new weapon.
the mean of abstract in "public abstract class M4" is that you cannot make a new object with this class.
So you can put all commons fields of your weapons in the weapon class and make m4 and m16 extends the weapon and you code would compile.

Categories