80930


Java swingを使用して、神経衰弱を作成しています。  
以下のソースコードにて、ゲームクリア後のリスタート時に、カードをシャッフルして再表示したいのですが`Collections.shuffle(cards);`を使用してもシャッフルされていませんでした。  
※ゲーム起動時はシャッフルされているのは確認しております。

[code]

        // Restart時にカードを裏面にする
    public void Restart_cards() {
        Collections.shuffle(cards);
        
        for(int i = 0; i < cards.size(); i++) {
            cards.get(i).setOpen(flg);
        }
    
    }
    
[/code]

また、以下を追加してみたのですがリスタートを行ってもシャッフルされませんでした。

[code]

    for(CardLabel card_shuffle : cards) {
            add(card_shuffle);
        }
    
[/code]

お手数ですが、その他記載方法等をご教示いただけますと幸いです。

**CardList.java**

[code]

    package pair_matching;
    
    import java.awt.Dimension;
    import java.awt.GridLayout;
    import java.util.ArrayList;
    import java.util.Collections;
    
    import javax.swing.ImageIcon;
    import javax.swing.JButton;
    import javax.swing.JPanel;
    
    public class CardList extends JPanel{
        private GameDate gameDate = new GameDate();
        JButton reset_btn;
        
        // ラベルをリストにする -> リストの各ラベルにImageIconをセット -> リストをコレクションシャッフル
        boolean flg = false;
        
        final int club = 0;
        final int diamond = 1;
        final int heart = 2;
        final int spade = 3;
        
        /* カード画像 */
        // 裏面
        ImageIcon card_back = new ImageIcon("image/card_back.png");
        // 表面
        ImageIcon[][] card_array = new ImageIcon[4][13];
        String filename;
        
        // jの数値
        int[] number = {
            1,2,3,4,5,6,7,8,9,10,11,12,13,
            1,2,3,4,5,6,7,8,9,10,11,12,13,
            1,2,3,4,5,6,7,8,9,10,11,12,13,
            1,2,3,4,5,6,7,8,9,10,11,12,13
        };
        
        // カードをリスト化
        ArrayList<CardLabel> cards = new ArrayList<>();
        
        public CardList() {
            setPreferredSize(new Dimension(1150, 600));
            setLayout(new GridLayout(4, 13));
            Start_card_list();
        }
        
        public void Start_card_list() {
            // Card_image
            for(int i = 0; i < card_array.length; i++) {
                for(int j = 0; j < card_array[i].length; j++) {
                    filename = "image/card";
                    switch(i) {
                    case club:
                        filename = filename + "_club_";
                        break;
                    case diamond:
                        filename = filename + "_diamond_";
                        break;
                    case heart:
                        filename = filename + "_heart_";
                        break;
                    case spade:
                        filename = filename + "_spade_";
                        break;
                    }
                    // ファイル名に数字を足す -> 拡張子を足す
                    filename = String.format(filename + "%02d", j+1);
                    filename = filename + ".png";
                    card_array[i][j] = new ImageIcon(filename);
                    CardLabel tmp_label = new CardLabel(card_array[i][j],card_back,number[j]);
                    // tmp_labelを押下したら、ひっくり返るのはtmp_label
                    tmp_label.addMouseListener(new Cardclick_Listener(tmp_label, gameDate, this));
                    add(tmp_label);
                    cards.add(tmp_label);
                }
            }
            Collections.shuffle(cards);
            // カードのシャッフル
            for(CardLabel card_shuffle : cards) {
                add(card_shuffle);
            }
        }
        
        // Restart時にカードを裏面にする
        public void Restart_cards() {
            Collections.shuffle(cards);
            
            for(int i = 0; i < cards.size(); i++) {
                cards.get(i).setOpen(flg);
            }
    
        }
    }
    
    
[/code]

**Cardclick_Listener.java**

[code]

    package pair_matching;
    
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    
    import javax.swing.JOptionPane;
    
    public class Cardclick_Listener implements MouseListener{
        private CardLabel card_label;
        private GameDate gameDate;
        private CardList cardList;
        
        public Cardclick_Listener(CardLabel card_label, GameDate gameDate, CardList cardList) {
            this.card_label = card_label;
            this.gameDate = gameDate;
            this.cardList = cardList;
        }
        
        @Override
        public void mouseClicked(MouseEvent e) {
    
            boolean open = card_label.isOpen();
            int Pair = gameDate.getPairCount();
            
            // カードの表裏チェック
            if(open == true) {
                return; // 裏面にしない
            }else if(open == false){
                card_label.setOpen(true);
                if(gameDate.getCard_one() == null) {
                    // nullの場合：GameDateのCard_oneに格納
                    gameDate.setCard_one(card_label);
                    return;
                }else{
                    // null以外:GameDateのCard_twoに格納
                    gameDate.setCard_two(card_label);
                }
            }
        
            /* ペア成立 */
            if(gameDate.getCard_two().getNumber() == gameDate.getCard_one().getNumber()) {
                if(open == true) {
                    gameDate.setPairCount(Pair += 0); // 表のカードを押下した時に2がカウントされないようにする
                }else {
                    /* ゲームクリアの条件
                     * 52枚揃ったらクリア
                     * */
                    gameDate.setPairCount(Pair += 2); // 枚数のカウント
                    gameDate.setCard_one(null); // Card_oneをリセット
                    gameDate.setCard_two(null); // Card_twoをリセット
                    
                    if(Pair == 52) {
                        int option = JOptionPane.showConfirmDialog(null, "GAME CREA!!! 「はい」を押下でゲームを再開できます。", "GAME CREA", JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE);
                        if(option == JOptionPane.YES_OPTION) {
                            cardList.Restart_cards(); // カードを全て裏面にする
                            gameDate.setPairCount(0); // 枚数カウントのリセット
                        }else {
                            System.exit(0); // ゲーム終了
                        }
                    }
                }
                /* ペア不成立 */
            }else{
                /*
                 *cardListのrevers_btnを活性化させる処理を追加
                 *cardListのrevers_btnを押下した時の処理をrevers_button_clickに追加
                 * */
                
                int missmatch = JOptionPane.showConfirmDialog(null, "カードが一致しませんでした。", "カードの不一致", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE);
                if(missmatch == JOptionPane.OK_OPTION) {
                    gameDate.getCard_one().setOpen(false);
                    gameDate.getCard_two().setOpen(false);
                    gameDate.setCard_one(null); // Card_oneをリセット
                    gameDate.setCard_two(null); // Card_twoをリセット
                }else {
                    return;
                }
            }
        }
    
        @Override
        public void mousePressed(MouseEvent e) {
        }
        @Override
        public void mouseReleased(MouseEvent e) {
        }
        @Override
        public void mouseEntered(MouseEvent e) {
        }
        @Override
        public void mouseExited(MouseEvent e) {
        }
    
    }
    
    
[/code]


CC BY-SA 4.0
2021-08-19T08:27:12.377
80912
2021-08-20T01:33:00.890
2021-08-19T14:18:38.000
47246
47246
question
java swing
ゲームクリア後のリスタート時に、カードをシャッフルして再表示したい。


ご質問の中で追加されたコードのうち、前者は「カードを裏面にする」処理です。  
後者は「既にカード配置済みのパネルにカードを追加する処理」です。  
`ArrayList<CardLabel> cards`はゲーム内部の変数なので、CardListパネルの子要素(CardLabel)を
**クリアして再配布** しないとシャッフルが適用されません。

子要素をクリアするには[`removeAll`](https://docs.oracle.com/javase/jp/8/docs/api/java/awt/Container.html#removeAll--)を使用します。  
これはswingの特性ですが、単一メソッドの中で`removeAll`した後に`add`しても中身が書き換わりません。  
[パネルの中身を書き換える](http://bb-biz.com/java-desktop-
schedule-030/)ためには`removeAll`の後に`revalidate`と`repaint`を呼び出して子要素のクリアを反映させてください。

[code]

    // Restart時にカードを裏面にするだけでなく
    // Restart時にカードを再配布する
    public void Restart_cards() {
        // 裏面にする処理(これはこれで必要)
        for(int i = 0; i < cards.size(); i++) {
            cards.get(i).setOpen(false);
        }
        // 再配布する処理(Collections.shuffleした後に再配布しないとカードの位置は変わらない)
        // カードをすべて除去
        removeAll();
        // カードの除去をCardListに適用して再描画
        revalidate();
        repaint();    // 再描画をせずとも今回は問題ないけれどおまじない
        // シャッフル
        Collections.shuffle(cards);
        // 再配布
        for(CardLabel card_shuffle : cards) {
            add(card_shuffle);
        }
    }
    
[/code]


CC BY-SA 4.0
2021-08-20T01:33:00.890
80930
2021-08-20T01:33:00.890
9820
80912
answer