I'm trying to put together a game, However, i'm not sure how to tackle the reset function. I have made it so that the game resets, this works, however, on game restart, the label that is supposed to display how many games the player has played does not change from 0. Heres what I have done so far.
The display and positioning of labels...
private int noGamesPlayed;
private JLabel gamesPlayed = new JLabel("Games Played = " + noGamesPlayed);
getContentPane().add(gamesPlayed);
gamesPlayed.setBounds(60,60+gridsize*boardsize,130,30);
The reset function...
public void reset(){
game.this.setVisible(false);
game.this.dispose();
new game();
updateGamesPlayed();
}
The function that is suppose to update the games played...
public void updateGamesPlayed() {
noGamesPlayed ++;
gamesPlayed.setText("" + noGamesPlayed + " Games Played");
}
Help Appreciated.
Change the noOfGamesPlayed variable to static. That field does not belong to the object, but to the class itself. Then, change the updateGamesPlayed to a static method, this way all game objects will see the same numberOfGamesPlayed count. Like that:
private static int noGamesPlayed = 0;
public static void updateGamesPlayed() {
noGamesPlayed ++;
}
Then, on the reset method, create a new game after updating the number of games played.
public void reset(){
game.this.setVisible(false);
game.this.dispose();
updateGamesPlayed();
new game();
}
You can also make it "automatic" by incrementing the noGamesPlayed on the game constructor. That way you don't need to call updateGamesPlayed.
You're creating a completely new game object, one that has its own noGamesPlayed variable and JTextField, and likely this method call is not changing the gamesPlayed JTextField in the newly displayed GUI
gamesPlayed.setText("" + noGamesPlayed + " Games Played");
but rather is updating the JTextField of the GUI that has been disposed of. Note that your reset method looks to be recursive.
One solution is to call the updateGamesPlayed(...) method of the newly created game object (note that the class should be renamed Game), and pass in the correct number as a parameter.
Myself, I'd go about resetting my game in a completely different way, by not creating a new window, but instead by updating the key model variables (the non-GUI variables and classes that determine the state of your program) and then using those variables to reset the current display.
Related
I am working on a simple game and have my main method inside my GUI class and have managed to get rid of all my issues with JTextfields not updating from my game loop that way except for one which coincidentally is the only one that is being fed a static double variable instead of raw strings. I can't seem to find out why online or by tinkering and finally broke down and decided to ask my first stackoverflow question.
public class BlackJackWindow extends JFrame
{
static double betAmount = 0;
static double money = 100; //The offending variable
static int playerAction = 0;`
Here is the kind of situation I am using it in that seems to do nothing when called.
public static void main(String[] args)
{
BlackJackWindow gui = new BlackJackWindow();
//Initializing main deck
Deck theDeck = new Deck();
theDeck.newDeck();
theDeck.shuffle();
//Dealing hands
Deck playerHand = new Deck();
Deck dealerHand = new Deck();
money = 100.00;
while(money > 0)
{
gui.moneyField = new JTextField("Money : " + money); //This line
seems to never occur on my GUI, what am I doing wrong?
gui.moneyField.validate();
Any help would be greatly appreciated!
Just creating the JTextField object and assigning it to a variable does not place it into the GUI, and in fact I'd recommend against trying to create a GUI in this way. Note that this has nothing to do with the static money field and all to do with creating a GUI in the wrong way.
What you probably want to do is to get the currently displayed JTextField and setting its text with the value held by money, but hard to say given the small amount of code you've posted.
Also this has nothing to do with scope and again all to do with references. You may be assuming that setting a field, here the gui.moneyField will change the JTextField displayed in the gui GUI, and that's not how references work.
Note that this answer is incomplete because your question and code is incomplete, in particular, we do not see how you create your GUI or how your variables relate to the problem at hand, it's all a mystery to us. For a better answer, please post a better and more complete question, one with a valid MCVE program post.
So not:
gui.moneyField = new JTextField("Money : " + money); //This line
but rather
gui.setMoneyText("Money : " + money);
where the method body within the GUI class could be something like:
public void setMoneyText(String text) {
moneyField.setText(text);
}
Also the while loop doesn't belong in event-driven GUI programs, but that's the subject of another answer to another question.
this is a problem that I've been really struggling with
I need to create a game for some University coursework. The game is basically a 4x4 grid. When i click a button, the player should move randomly within 1 square of it's location.
There's enemy spaceships that are generated randomly over the grid, and if the player lands on the spaceship, it destroys it. if there's two enemy ships on the same sqaure and the player lands on that square, the player is destroyed.
I've created a GIU using gridlayout and the button that I need to move the player, but I'm having problems trying to figure out how to actually use the grid. I've created an element class to create objects for the grid (ie, a list of enemy ships), but I don't know how to use this class with my gridlayout. I know I also have to redraw the grid after each move to reflect the changes, but I don't know if I would need to create a custom redraw method for this.
Any push in the correct direction so I can get my program actually doing something would be really helpful.
Some time ago I created a card game that also operated based on a GridLayout. Below is some of the code that was used to drive major events:
CardPanel extends JPanel {
public CardPanel() {
setLayout(gridLayout);
placeCards(N);
chatBoxText = new JTextArea(5, 30);
}
public void placeCards(int numCards) {
for (int i = 0; i < numCards; i++) {
Card card = deck.distributeCard();
String cardImageName = card.getImageName();
JLabel jLabel = makeImage(cardImageName);
cardSet.add(new GraphicCard(card, jLabel));
add(jLabel);
jLabel.addMouseListener(this);
}
if (GameLogic.noSetsOnBoard(cardSet)) {
gridLayout.setRows(gridLayout.getRows() + 1);
placeCards(3);
}
}
public void updateCard(Integer location) {
Card card = deck.distributeCard();
String cardImageName = card.getImageName();
JLabel jLabel = makeImage(cardImageName);
cardSet.set(location, new GraphicCard(card, jLabel));
jLabel.addMouseListener(this);
}
}
The CardPanel here is an object that represents the GridLayout (you see the constructor) as well as some of those helper methods.
Further on, on particular actions, I have the following code:
cardPanel.removeAll();
// Some other logic here
for (GraphicCard card: cardSet) {
cardPanel.add(card.getJLabel());
}
cardPanel.revalidate();
cardPanel.repaint();
In short, yes, it is custom, but it is not difficult. There are better ways to do it than the above such that you do not need to empty the entire panel in order to refresh it, the logic I have omitted above merited this particular solution.
The approach I used kept track of a CardPanel object which was an abstraction that contained not only the information that each box represented (in my case a card with some values), but also the graphic element to be rendered.
This was some time ago, so I don't recall the exact details but hopefully this is helpful.
I am currently making a TicTacToe program for an assignment in college. I have my board laid out with 3x3 JTextFields, each one has an action listener attached. What I need to do is create another class which will check for errors (eg a user will put a number or a letter that is NOT x or o) they should get a dialog box stating the error and the JTextField they tried to enter will return to blank. How would I go about implementing the error checking, through try - catch - finally method?
Another question, I have a GameGUI class, I also want to have a GameLogic class. How do I check from GameLogic if the game has been won? In my GameLogic I will have something like
if j1, j2 and j3 are all x or o then display dialog box "x player wins".
I will try to answer the question regarding a general board game. Your object oriented thinking of splitting into different classes is correct. What I do generally is that I have the GameLogic containing my logic and validations for the game as well as determining whether the game is over or not and so on.
The GameGUI class would then have an instance variable of the type GameLogic that's initialized on creating an object of type GameGUI. In my way of thinking, I would have the GameLogic representing the board state with 2D Array of chars. The GameGUI would be just there to relay input from the user to the GameLogic which determines if the game is over. The GameLogic should throw an Exception of the type that you want to clarify and then the GameGUI should try to update the board with the input text from the user in the JText fields, catch the error from the GameLogic (if any) and then repaint the GUI that's displayed to the user based on the input it got. I will give a sample below to clarify my point although I won't provide the actual implementation for the TicTacToe game, you can easily do it on your own.
public class GameLogic {
....
char[][]board;
public GameLogic() {
//initialize the board representation for game
}
public boolean gameOver() {
//determine if the game is over by checking the board 2D array
// 3 xs or os in a row, column, or diagonal should determine the game is over or if there are no more moves
}
public void move(char character, int x, int y) {
//update a certain position with a character should throw an Exception if the character is invalid or if the the character is valid but it's not the character that the user owns player1 plays with x for example but puts o.
//should also have the logic for the turns
}
...
}
public class GameGUI {
.....
GameLogic engine;
public GameGUI() {
engine = new GameLogic();
}
public void actionPerformed(ActionEvent e) {
// here you would get the co-ordinates of the clicked JTextButton
// then call the method move on the engine instance
try {
engine.move(character, x, y);
} catch(Exception e) {
//display the validation for the error that happened
}
//repaint the representation from the engine to be displayed on the GUI Frame that you are using
}
...
}
One more thing is that I would have declared the JTextFields as 2D Array of JTextFields and not as individual instance variables to mirror the representation in the GameLogic class. You can also avoid the validations all together if you use JButton class instead of JTextField and that the user gets the character he is playing with on the clicked button if it is his turn and the button is not already used before.
I'm searching on the internet for hours and i cannot find the right answer that works for me.
So.. I made a game called 'seabattle'
After playing that game the console comes with the question to play again.
System.out.println("Well done! " + whosturn.getName() + ". A ship down!" );
System.out.println("Hurraaaaaayyyyy, All boats down!!");
System.out.println("Do you want to play this game again? (y/n) ");
input = scanner.next().toLowerCase();
if(input == "y"){
System.out.println("The game should start again now..");
System.out.println("Butttttttt, I don't know how to...");
}
else{
System.out.println("Thank you for player Battleships!");
System.out.println("See you next time ;)");
}
}
else{
FiredPosition.setDisplayValue('*');
System.out.println("Good job, you hit a ship!");
switchTurn();
}
If the user types y in console. The game should start again.
I read something about Main(args) or something like that.. That didn't work for me because this is another class.
I hope you guys can help me?
Ciaoo
If your main class SeaBattle is currently as this:
public class SeaBattle {
public static void main(String[] args) {
...
}
}
you could change it the following way:
public class SeaBattle {
private static String[] args;
public static void run() {
//do the same than main() previously
}
public static void main(String[] args) {
SeaBattle.args = args;
run();
}
}
Then to relaunch the game,
SeaBattle.run();
A simple answer is: Whatever you do to start the game in the first place, do it again when you detect the 'y'.
However, a more in depth answer involves the use of an object to store and update the game state, it is not fully clear from your description whether you are currently doing this. So if it is a battleships type game the object may contain a 2d array for the game area, and perhaps a variable to store whose turn it is. This object would have an 'initialise' method where you randomly select where the ships are in the game area, set the value for whose turn it is, etc.
Your main method would interact with this object, so it would call the game object's initialise method, and after each turn it would call another method (e.g. 'isGameFinished') to check whether the game is over. The isGameFinished method would check if all of the ships have been destroyed and return true if so. If it returns true, then the user would be prompted for a new game. If they enter 'y', then you can either create a completely new object of the game state or just call the game state's initialise method again. You will then have a new game state to begin a new game with.
Hey guys I've come with 2 problems, both being Java Swing related. I am developing a card game in Java. I use arreays lists of type to hold the values of each card and I have a main Play() method that calls updates to the GUI using invokeLater and a Singleton approach to my GUI class.
The first question is fairly simple. I create the cards on the GUI using JLabels like so; attaching relevent listeners and adding them to the appropriate panel, in this case, the 'Human Hand Panel':
for (int i = 0; i < (HumanHand.size()); i++)
{
Card card = HumanHand.get(i);
BufferedImage cardImage = null;
try {
cardImage = ImageIO.read(new File("card/" + card + ".jpg"));
} catch (IOException e) {
e.printStackTrace();
}
JLabel picLabel = new JLabel(new ImageIcon( cardImage ));
picLabel.addMouseListener((MouseListener) me);
HumanHandDisplay.add(picLabel);
}
//HumanHandDisplay.validate();
HumanHandDisplay.updateUI();
The problem I'm having is that when the human hand is more than 7 cards or so, it creates a larger panel area and starts a new row of cards beneath. What I would like to do is, when the hand reaches a certain size, the cards start to overlap eachother (like you would hold cards in your hand). I've messed about with .validate() but gotten nowhere. Any help you can give here would be most welcome.
My second question is about using a Swing Worker to return the Human player's card selection. I have read a little bit about Swing workers but I'm unsure as to the best way to implement one in my own game. At present, using the console I have a scanner than takes the input of an int as the choice (the place of the specific card in the ArrayList). I would like this int to be selected by clicking on the card in the players hand. At the moment I use:
String name = "" + i;
picLabel.setName(name);
to set the names of the Card JLabels to the int in the for loop creating them (as shown^^), and I use:
public void mouseClicked(MouseEvent e) {
String name = ((JLabel)e.getSource()).getName();
System.out.println("Working " + name);
selection = Integer.parseInt(name);
}
To return that int when one of the cards is clicked. Here is what I've been using to call the GUI methods from Play() aswell:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
GUI.getInstance().UpdateHand();
}
});
My question is, how can I get the Play method to call a method in the GUI class, which sets up the hand with the appropriate listeners (lets call it GUIPlayerSelection() for now) then wait for the player to click a card, which then returns the int to my Play() method in my main class that represents the card selected. I'm unsure as how to use invoke and wait, as in, if I use invoke and wait, will it just wait for the cards to be set up, or will it wait for the mouseClicked() method to finish aswell? Or will I have to do something else to make sure it waits for the mouse to be clicked after the hand set-up? And how then will I return that int? I've been told to use a swing worker but if someone could explain how I can implement that in this case that would be awesome.
Thank-you in advance.
For your first question, are you having an issue getting the frame to repaint or with the layout of the cards?
If the latter, then you may want to have a look at Java Layout Managers, it describes how the content pane inside your JFrame organizes the components added to it.
If none of those will work for you (and I don't think they will with that you describe), you can use the setBounds method to manually align your JLabels.