Basically, I'm making a yahtzee game in MVC. It works fine, but When I try to save a session of a game, It doesn't save the game object containing and arraylist of players. This without stopping the execution which would certainly clear the arraylist of games.
Basically, an instance of game has the following fields:
public String name;
public int numberOfPlayers;
public ArrayList<Player> players = new ArrayList<>();
int playerListIndex;
ArrayList<Boolean> checkable;
StandardRules yahtzeeRule = new StandardRules();
public int rounds;
public String date;
The Arraylist of players contains instances of the object Player which has it's own fields and gettters/setters.
I've managed to track the problem to not saving when I call the method:
public void saveGame(Game thisGame) {
DB.saveGame(thisGame);
}
Which in turn calls the class:
public class DB {
private static ArrayList<Game> savedGames = new ArrayList<>();
/**
* Saves the passed member into the database.
* #param game, the member to be saved.
*/
public static void saveGame(Game game) {
for (Game g : savedGames) {
if (g.name.equals(game.name)) {
savedGames.remove(g);
savedGames.add(game);
}
else {
savedGames.add(game);
}
}
}
The saveGame method basically checks the Arraylist of saved games if the name already exists, and if it does it removes the old one and adds the new one. If there is no game by that name, It just adds the game to the list. (I might Implement a MYSQL DB later, but for the sake of making sure the program works first, I'd like to use the arraylist to test things)
I'm under the impression that I need to have a static reference to the DB to ensure that I'm trying to access the same DB all the time and not mix up instances of a DB.
What am I doing wrong here?
Try to follow the logic. You are looping over the array to save the game. If the array is empty, what would you expect to happen? If the Array would have six elements what would you expect to be in this list? In addition, you would most likely run into a ConcurentModificationException if this loop would ever get executed with a name that is already in the List. You might want to loop over the List and store a duplicate into a variable. But donĀ“t do the saving and removing in the loop.
So in the end your problem is that you are looping over the empty list to save the Game, which in fact wont work because your List is empty and you will never reach the part where you add something to your List.
You are most likely out for such a solution to store the game in your List.
public static void saveGame(Game game) {
Game dupGame = null;
for (Game g : savedGames) {
if (g.name.equals(game.name)) {
dupGame = g;
}
}
if (dupGame != null) {
savedGames.remove(dupGame );
}
savedGames.add(game);
}
EDIT:
You could also make use of a Map, which would make finding duplicates and so on a bit faster and more easy.
public class DB {
private static Map<String,Game> savedGames = new HashMap<>();
/**
* Saves the passed member into the database.
*
* #param game
* , the member to be saved.
*/
public static void saveGame(Game game) {
savedGames.put(game.name.toLowerCase(), game);
}
}
You want to have these savedGames in memory right. There is no problem having them as static. The only problem you have is you are iterating through the savedGames list and also modifying it adding and removing the few games. This is wrong. It might give you concurrent update exception.
public class DB {
private static ArrayList<Game> savedGames = new ArrayList<>();
/**
* Saves the passed member into the database.
* #param game, the member to be saved.
*/
public static void saveGame(Game game) {
boolean exists=false;
boolean removalObject=null;
for (Game g : savedGames) {
if (g.name.equals(game.name)) {
exists=true;
removalObject=g;
}
}
savedGames.add(removalObject);
savedGames.add(game);
}
}
The first problem is , trying to add a game to the empty ArrayList will fail because the adding operation is done within the loop which will never run if the savedGames is empty. Also the remove(Object obj) method works as expected if the equals(Object obj) of the Object class is properly override in the Game class.
Try this below...
Override the equal() method in the Game Class:
#Override
public boolean equals(Object obj) {
if(obj != null && obj instanceof Game){
Game gameObj = (Game)obj;
if(this.name.equals(gameObj.name)){
return true;
}
}
return false;
}
Do the saveGame() method as follows:
public static void saveGame(Game g){
if(games.contains(g)){
games.remove(g);
}
// Add the game after removing the existing
// or if never existed
games.add(g);
}
You'r method can return a exception becuas you read from the ArrayList and add content to it in loop.
Try this. :)
for(Game g : savedGames) {
if(g.name.equals(game.name)) {
savedGames.remove(g);
savedGames.add(0, game);
} else {
savedGames.add(0, game);
}
}
Related
In my project, in one of the classes (Adventure) I created an ArrayList and worked on it (add elements, delete others...)
This ArrayList is then passed as a parameter when creating an instance of another class (Player) inside Adventure.
Therefore I of course needed to created an ArrayList in Player and constructor, to catch the ArrayList sent from Adventure.
I'm not really sure, that all what i've done is correct. I'm getting the warning in Player Class:
This private field "createdObjects" is never assigned
Should i change smtg, or just ignore the warning ?
Here's the code :
public class Player {
private ArrayList<Objects> createdObjects;
public Player(ArrayList<Objects> createdObjects) {
//Originally i have many other elements in this constructor
// but i let only what concerns this arrayList
}
public ArrayList<Objects> getCreatedObjects() {
return createdObjects;
}
}
public class Adventure {
private ArrayList<Objects> createdObjects = new ArrayList<>();
public ArrayList<Objects> getCreatedObjects() {
return createdObjects;
}
// ...methods that will add/modify... the arraylist
public Player letsStart(){
Player player = new Player(createdObjects);
return player;
}
}
So basically im creating a list with a lot of information that i get from the user, and i need to display that "Estudiante" created on a list asside. So this is what i first tried, but it tells me that setListData is for arrays, so i tried other thing that i found that included the using .toArray(array) but that didnt work too.
Just to clarify what modelo is i copied this first code
public class VentanaEstudiante extends javax.swing.JFrame {
private Sistema modelo;
/**
* Creates new form VentanaEstudiante
*/
public VentanaEstudiante(Sistema unSistema) {
modelo = unSistema;
this.setSize(400, 280);
initComponents();
}
private void BotonCrearEstudianteActionPerformed(java.awt.event.ActionEvent evt) {
Estudiante unEst=new Estudiante(NombreEstudiante.getText(), Integer.parseInt(CedulaEstudiante.getText()),MailEstudiante.getText(), Integer.parseInt(NumeroEstudiante.getText()), Integer.parseInt(SemestreEstudiante.getText()));
modelo.agregarEstudiante(unEst);
ListaEstudiantesJ.setListData((modelo.getListaEstudiantes()).toArray());
Estudiante has a toString method, and the superclass, also does.
public String toString(){
return super.toString() + "Numero:" + this.getNumero() + "Semestre: " + this.getSemestre();
}
Here you have my lists and i only copied the listaEstudiantes methods because this are the ones im asking right now. This class Sistema, doesnt have any toString methods because i throught that this arraylist didnt needed one.
public class Sistema {
private ArrayList<Estudiante> listaEstudiantes;
private ArrayList<Docente> listaDocentes;
private ArrayList<Equipo> listaEquipos;
public Sistema(){
listaEstudiantes = new ArrayList<>();
listaDocentes= new ArrayList<>();
listaEquipos=new ArrayList<>();
}
public void agregarEstudiante(Estudiante unEstudiante){
listaEstudiantes.add(unEstudiante);
}
public ArrayList<Estudiante> getListaEstudiantes(){
return listaEstudiantes;
}
I need to use ArrayList in case you have something that may work better, i just need to use them
This whole project has a lot of showing Lists and sometimes i have to even let the user select things from them, something that i also dont know how to do but i dont know if i can ask more than one question here. The list is also going to need to refresh and all of that but i think i can handle that. Thanks
JList.setListData() has two variants, one expecting an array of elements, the other expecting a vector of elements.
Behind the scenes these two methods create an instance of an anonymous subclass of AbstractListModel and pass that instance to JList.setModel().
You can easily implement similar code for any List instance:
static <E> void setListData(JList<E> jList, List<? extends E> listData) {
jList.setModel(new AbstractListModel<E>() {
public int getSize() { return listData.size(); }
public E getElementAt(int i) { return listData.get(i); }
});
}
I am currently working on an app that will use many objects as information holders (music things - artist, song, id of album cover img, and another id of 2nd img).
I decided that it would be the best to create "Track" class and use it to make objects and store them in ArrayList.
I created the class, I created the list, but I'm having trouble with accessing it (I want to change the ImageViews and TextViews basing on current Track object).
Here's the Track Class: (Track.java separate)
public class Track {
private String mNameArtist;
private String mNameTrack;
private int mTabResource;
private int mCoverResource;
public Track(String nameArtist, String nameTrack, int tabResourceId, int coverResourceId){
mNameArtist = nameArtist;
mNameTrack = nameTrack;
mTabResource = tabResourceId;
mCoverResource = coverResourceId;
}
public String getArtistName() {
return mNameArtist;
}
public String getTrackName() {
return mNameTrack;
}
public int getTabResourceId() {
return mTabResource;
}
public int getCoverResourceID() {
return mCoverResource;
}}
And here's ArrayList declaration: (PlayActivity.java, inside onCreate method)
ArrayList<Track> Tracks = new ArrayList<Track>();
Tracks.add(new Track("Artist Name", "Track Name", R.drawable.tabtemplate, R.drawable.testcover));
Tracks.add(new Track("Pink Floyd", "Comfortably Numb Solo 1", R.drawable.CNS1Tab, R.drawable.pink_floyd_the_wall));
There are more positions, but you get the idea.
Everything seems to work fine up to this point.
When I want to access it inside another method (even in the same PlayActivity.java) nothing happens or I see errors. I tried many different approaches but every single one fails. For example:
Track.getTabResource(); // can't even use the method.
Tracks.get(3); // does not work as well.
I just can not use objects or that arraylist inside my methods. The "Tracks array" won't even show up in Android Studio when typing. Track does, but I can't access positions from Array.
So to sum up, is there any other way I can use my Objects (ArrayList) items inside other classes and methods?
Thank you for your help in advance.
Create List as instance variable and access through Object of that class.
public class PlayActivity {
List<Track> tracks = new ArrayList<Track>();
public void onCreate() {
tracks.add(new Track("Artist Name", "Track Name", R.drawable.tabtemplate, R.drawable.testcover));
tracks.add(
new Track("Pink Floyd", "Comfortably Numb Solo 1", R.drawable.CNS1Tab, R.drawable.pink_floyd_the_wall));
}
public List<Track> getAllTracks() {
return Collections.unmodifiableList(tracks);
}
public Track getTrack(int index) {
return tracks.get(index);
}
}
As part of an assignment Im trying to access a cloned array list from another class so I can utilize it. But when attempting to do so I get the following error "non-static method getConnections() cannot be refrenced from a static context".
This is the code I'm using to access the cloned array. It is in the context of working out the best way to take flights from one destination to another.
public boolean determineRoute(City from, City to, ArrayList<City> flightRoute)
{
ArrayList<City> Connections = new ArrayList<City>();
Connections = City.getConnections();
return true;
}
And this is how the code for that class begins. It does start as static but as far as i can see it should only affect the first method how can I tell java that this method should not be considered static so I can access the cloned list from the non static class??
import java.util.*;
public class Lab9_Ex2_Main
{
//////// START-UP /////////
public static void main(String[] args)
{
new Lab9_Ex2_Main();
}
I have left out a lot of the code as I think it may not be right from me to put every thing up. But should you need more to get a clearer picture I will happily add more of the code.
This is the code from another class which contains a cloned array which im attempting to access.
import java.util.*;
// Class: City
// Purpose: To represent a place in the world that you can fly from/to.
public class City
{
private String name; // The name of the City
private ArrayList<City> connectsWith; // Which cities are connected to this one
public City(String cityName)
{
name = cityName;
connectsWith = new ArrayList<City>();
}
// Method: addConnection
// Purpose: To note that you can catch a flight to the destination, from this city
// Passed:
// destination - The City which you can fly to.
public void addConnection(City destination)
{
if (destination != null && destination != this)
connectsWith.add(destination);
}
// Method: getConnections
// Purpose: To retrieve a list of cities you can reach from this one.
// Note: You are given a clone, (to avoid a privacy leak), and can manipulate it however
// you like. E.g. you could delete elements.
public ArrayList<City> getConnections()
{
return (ArrayList<City>) connectsWith.clone();
}
public String getName()
{
return name;
}
public String toString()
{
return name;
}
}
City actually doesn't provide a static getConnections() method, since that doesn't make sense. The connections depend on an actual City instance and if you have access to one you can call getConnections() on it, even from a static method.
This is the comment on the array list that is cloned in getConnections():
// Which cities are connected to this one
Note that this means you just can't get the connections without specifying this city (the one you get the connections for) and thus just can't call that method on the City class only.
Comment on the method itself:
Purpose: To retrieve a list of cities you can reach from this one.
Assuming your determineRoute(...) method might be static, it could look like this:
public static boolean determineRoute(City from, City to, ArrayList<City> flightRoute)
{
ArrayList<City> connections = new ArrayList<City>();
connections = to.getConnections(); //or from.getConnections(); what ever makes sense
//connections is not used, so I assume you want to put them into flightRoute
flightRoute.addAll(connections);
return true;
}
Your determineRoute(...) logic seems quite odd. I assume you want to actually calculate the route between the from and the to city, which you are not doing right now. Fixing that, however, is an exercise for you.
You could then call that method in your main method (which has to be static) like this:
public static void main(String... args) {
City berlin = new City("Berlin");
City beijing = new City("Beijing");
//fill the connections here
ArrayList<City> route = new ArrayList<City>();
boolean success = determineRoute(berlin, beijing, route);
}
My personal mini project was to learn arrays here, doing a slightly big jump by making an Array of Objects. What I wanted to do was a mini RPG system where I create a class called monster and give it a couple parameters, and create an array of objects of the Monster class. So far I believe I created that Monster class and the Object of Arrays inside the main method class (Exec_Monster) listed below.
It took me a while initially, but I finally got to a point where I can create the array of Monsters and access them inside the Main class. But is there a way for me to create this Array of Objects and access each object from another class (and their individual values)? For Example, I would create a "Battle" class and then I would pull the "Health" value from an object of Monster.
I'm new to Arrays but I have had some experience with classes for the past two weeks here.
Class:
public class Monster
{
public int hp;
public String n;
public Monster(String name,int health){
n=name;
hp=health;
}
public int returnHealth(){
return hp;
}
public String returnName(){
return n;
}
}
Exec_Monster:
public class Exec_Monster{
public static void main(String args[])
{//Define Monsters
Monster[] monsterid=new Monster[]{
new Monster("Goblin",10),
new Monster("Elf", 8),
new Monster("Ant", 3),
new Monster("Worm", 2),
new Monster("Black Widow",6)};
Random chooser;
int chosenmonster=(chooser.nextInt()*5);
//Start
//while (Battle.wonloss==true) {
// Battle.battle();
}
}
You'd need to pass the monsters into the Battle object somehow (or into another object that you pass into the Battle object). You could pass it as an argument to a method, but in an Object Oriented world, if the monsters really belong to a battle, you could pass them in the constructor and make them available in all the methods of the Battle class.
Example:
public class Battle {
private Monster[] monsters;
private boolean wonloss;
public Battle(Monster[] monsters) {
this.monsters = monsters;
}
public boolean isWonloss() {
return wonloss;
}
public void battle() {
// Do something with monsters,
// and then check if there is any life left in the monsters
int totalHp = 0;
for (Monster monster : monsters) {
totalHp += monster.hp;
}
if (totalHp == 0) {
wonloss = false;
}
}
}
The "battle" part of your main method would then look like:
// Start
Battle battle = new Battle(monsterid);
while (battle.isWonloss()) {
battle.battle();
}