Я пытаюсь создать приложение для блэкджека со свингом, и у меня возникают трудности с добавлением новых карт, когда игрок нажимает кнопку удара. Я чувствую, что это как-то связано с тем, что JLabel не проверяется, но я понятия не имею, что это на самом деле означает или как исправить проблемы. Пожалуйста помоги...
Я действительно новичок в Java Swing, поэтому это может показаться очень интуитивным, но я надеюсь, что кто-нибудь объяснит любезно...
Ниже приведен код, который у меня есть в настоящее время, и он сдает по две карты как для дилера, так и для игрока без дублирования карт, но не может отображать новые сданные карты, даже если карта выбрана, как я вижу их на консоли...
import javax.swing.*;
import java.awt.*;
@SuppressWarnings("serial")
public class PlayerHand extends JPanel {
//declaring private vars
private JLabel cardPonTable[] = new JLabel[11];
private int cardP[] = new int[11];
private Image cardPImage[] = new Image[11];
private int cardOnTableCount = 0; //counter for number of cards on the table
public PlayerHand(boolean firstDeal){
setLayout(null);
/**
* Deals the first two cards for the player
*/
if (firstDeal == true) { //run this code if true
//playerHand config
setBackground(new Color(238, 238, 238));
setLayout(null);
JLabel playersHandLabel = new JLabel("Player's Hand"); //creates a label indicating the bottom half of the screen is the player's hand
//player's hand label config
playersHandLabel.setFont(new Font("Lucida Grande", Font.PLAIN, 25));
playersHandLabel.setHorizontalAlignment(SwingConstants.CENTER);
playersHandLabel.setBounds(192, 314, 200, 80);
add(playersHandLabel); //add player's hand label to the container
//creates JLabel for two of the player's card, set the positions, and add to the container
cardPonTable[0] = new JLabel("");
cardPonTable[0].setBounds(80, 6, 220, 320);
add(cardPonTable[0]);
cardPonTable[1] = new JLabel("");
cardPonTable[1].setBounds(340, 6, 220, 320);
add(cardPonTable[1]);
System.out.println("Player's cards"); //indicate that the following is the player's dealt card on the console
CardDeal.createDeck(); //create a deck
//deal two card for the player
cardP[0] = CardDeal.cardDeal();
cardP[1] = CardDeal.cardDeal();
//get the image from the src folder
cardPImage[0] = new ImageIcon (this.getClass().getResource(cardP[0]+".png")).getImage();
cardPImage[1] = new ImageIcon (this.getClass().getResource(cardP[1]+".png")).getImage();
cardPonTable[0].setIcon(new ImageIcon (cardPImage[0])); //set the JLabel of the card to the image chosen above
cardOnTableCount++; //increase the counter by one
cardPonTable[1].setIcon(new ImageIcon (cardPImage[1])); //set the JLabel of the card to the image chosen above
cardOnTableCount++; //increase the counter by one
}
/**
* Do not deal the first two cards (instance made)
*/
}
public void cardAdded() throws Exception {
//cardP1onTable.setBounds(cardP1onTable.getX()-50, cardP1onTable.getY(), (int)(WIDTH*0.7), (int)(HEIGHT*0.7));
//cardP2onTable.setBounds(cardP2onTable.getX()-50, cardP2onTable.getY(), (int)(WIDTH*0.7), (int)(HEIGHT*0.7));
PlayerHand newDealt = new PlayerHand(false); //creates an instance of playerHand method (send false as a parameter so that the method won't deal two cards again)
System.out.println("Player's card dealt");
newDealt.setLayout(null);
cardPonTable[cardOnTableCount] = new JLabel("");
cardPonTable[cardOnTableCount].setBounds(192, 6, 220, 320);
newDealt.add(cardPonTable[cardOnTableCount]);
cardP[cardOnTableCount] = CardDeal.cardDeal();
cardPImage[cardOnTableCount] = new ImageIcon (newDealt.getClass().getResource(cardP[cardOnTableCount]+".png")).getImage();
cardPonTable[cardOnTableCount].setIcon(new ImageIcon (cardPImage[cardOnTableCount]));
cardOnTableCount++;
}
}
Этот код ниже представляет собой JPanel, который позволяет игроку выбрать удар или остаться
import java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JPanel;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@SuppressWarnings("serial")
public class ChoiseBar extends JPanel{
private JButton hitButton;
private JButton stayButton;
public ChoiseBar() {
Dimension dim = getPreferredSize();
dim.height = 100;
setPreferredSize(new Dimension(1200, 100));
hitButton = new JButton("HIT");
hitButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
PlayerHand.cardAdded();
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
stayButton = new JButton("STAY");
setLayout(new GridLayout(0, 2, 0, 0));
add(hitButton);
add(stayButton);
}
}
Это класс MainFrame, в который добавлены PlayerHand, DealerHand и ChoiceBar.
import javax.swing.JFrame;
import java.awt.Color;
@SuppressWarnings("serial")
public class MainFrame extends JFrame{
//declaring private vars
private DealerHand dealerHand;
private PlayerHand playerHand;
private ChoiseBar choiseBar;
public MainFrame() {
super("TABLE"); //calling the "TABLE" method in BJ_APP
playerHand = new PlayerHand(true); //creates an instance of playerHand (firstDeal is true as it is the first deal)
//playerHand config
playerHand.setForeground(new Color(0, 0, 0));
playerHand.setBackground(new Color(238, 238, 238));
playerHand.setLocation(300, 625);
playerHand.setSize(600, 400);
dealerHand = new DealerHand(); //creates an instance of dealerHand
//playerHand config
dealerHand.setLocation(300, 31);
dealerHand.setSize(600, 429);
choiseBar = new ChoiseBar(); //creates an instance of choiseBar
//choiseBar config
choiseBar.setSize(800, 120);
choiseBar.setLocation(214, 472);
getContentPane().setLayout(null); //mainFrame uses absolute layout
//add these three containers to mainFrame
getContentPane().add(choiseBar);
getContentPane().add(playerHand);
getContentPane().add(dealerHand);
setSize(1200,1080); //set the size of mainFrame
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //the program will terminated when mainFrame is closed
this.setVisible(true); //set mainFrame visible
}
}
1) Не используйте статические переменные. Ваш код должен использовать переменные экземпляра. Еще лучше не использовать отдельные переменные, используйте массив, чтобы вы могли получить доступ к картам с помощью индекса, который упростит ваш код. 2) избавиться от статических методов. Опять же, вы добавляете пользовательские методы в класс, поэтому они не должны быть статическими. 3) Имена классов должны начинаться с заглавной буквы. 4) проверьте Макет перекрытия, который позволит вам легко добавлять карты отображения.
@ДжорджЗ. Спасибо за совет. Я не могу использовать абсолютный макет и проверять свои компоненты?
@camickr Спасибо за совет. Я внес несколько изменений в свой код, используя ваше предложение. Я соответствующим образом обновил приведенные выше коды, а также добавил еще один класс JPanel, который позволяет пользователю выбрать удар или остаться. Однако на 'PlayerHand.cardAdded();' , он говорит "не может сделать статическую ссылку на нестатический метод cardAdded() из типа PlayerHand" и предлагает мне изменить cardAdded() на static.
Когда вы создаете панель «PlayerHand», вам нужно сохранить ссылку на панель. Затем, когда вы создаете «ChoiceBar», вы передаете ссылку на PlayerHand в ChoiceBarl. Теперь ChoiceBar может вызывать любой метод на панели PlayerHand, используя эту ссылку.
@camickr Еще раз спасибо за отзыв. Что именно означает «сохранение ссылки»? Что мне нужно сделать конкретно? Я искал и искал пару веб-сайтов, но не смог найти ничего конкретного... Спасибо.




What exactly does "keeping a reference" mean?
Ты делаешь это все время:
hitButton = new JButton("HIT");
Выше вы создаете экземпляр JButton и сохраняете ссылку на него.
Затем в своем коде вы изменяете свойство кнопки, используя:
hitButton.addActionListener(new ActionListener() ...
Ваши пользовательские панели ничем не отличаются. Вы создаете собственный класс с методами, которые хотите выполнить.
Итак, где-то в вашем коде вам нужна логика, например:
PlayHand playHandPanel = new PlayHand();
ChoiceBar choiceBarPanel = new ChoiceBar( playHandPanel );
frame.add( playHandPanel );
frame.add( choiceBar );
Затем в конструкторе вашего ChoiceBar вы сохраняете ссылку на «playHandPanel» как переменную экземпляра в своем классе. А затем в ActionListener для кнопки теперь можно вызывать метод cardAdded().
Большое спасибо еще раз за добрый ответ. Я до сих пор не уверен, куда я должен добавить эти 4 строки кода... В класс ChoiceBar или мне нужно создать еще один класс, содержащий только этот код? >PlayHand playHandPanel = new PlayHand(); ChoiceBar selectionBarPanel = новый ChoiceBar(playHandPanel); frame.add(playHandPanel); frame.add(выборбар); Спасибо,
Я не знаю, как вы структурировали свой код, но где-то вам нужно создать панели и добавить их в свой фрейм.
Я добавил код MainFrame, куда добавляются все панели. Является ли MainFrame классом, в который мне нужно добавить четыре кода, которые вы упомянули выше?
Не вызывать метод
validate(). Вам нужно будет создать методrevalidate(). Оба эти метода ничего не делают, если вы не используете LayoutManager (setLayout(null)). Я предлагаю вам начать сначала, используя LayoutManager.