【问题标题】:Any advice on how to fix this Stack Overflow error? Java有关如何解决此 Stack Overflow 错误的任何建议?爪哇
【发布时间】:2016-12-28 02:17:47
【问题描述】:

在空闲时间开发一个简单的自动生成战争游戏时,我遇到了“StackOverFlow”错误。

这是我发生错误的 Deck 类: 它发生在我的 compare() 方法中。任何关于我可以做些什么来避免这个错误的见解都是被接受的,因为我正在努力理解可以做些什么来解决这个问题,并且除了我的课程没有很好地递归之外,我对这个错误甚至意味着什么知之甚少。谢谢!

import java.util.*;
import java.math.*;
public class Deck
{
    private int num = 0;
    private int cardnum2 = 0;
    private int cardnum = 0;
    private int decrease = 0;
    private int rnd = 0;
    private int winner = 0;
    private String suit = " ";
    private int suitNum = 0;
    private int val = 1;
    private String name = "";
    private ArrayList<Card> Deck = new ArrayList<Card>();
    private Card[] cardCheck = new Card[51];
    private ArrayList<Card> play1 = new ArrayList<Card>();
    private ArrayList<Card> play2 = new ArrayList<Card>();
    public Deck()
    {
        createDeck();
    }
    public void createDeck()
    {
        for(int i = 0; i < 4; i++)
        {
            val = 1;
            suit = " ";
            name = " ";
            suitNum++;
            System.out.println();
            System.out.println();
            for(int z  = 0; z < 13; z++)
            {
                if(suitNum == 1)
                {
                    suit = "Hearts";
                }
                if(suitNum == 2)
                {
                    suit = "Diamonds";
                }
                if(suitNum == 3)
                {
                    suit = "Spades";
                }
                if(suitNum == 4)
                {
                    suit = "Clubs";
                }
                if(val == 1)
                {
                    name = "Ace";
                }
                else if(val == 11)
                {
                    name = "Jack";
                }
                else if(val == 12)
                {
                    name = "Queen";
                }
                else if(val == 13)
                {
                    name = "King";
                }
                else {
                    name = "";
                }
                Card myCards = new Card(val, suit, name);
                Deck.add(myCards);
                System.out.print(myCards + "   ");
                val++;
            }
        }
    }
        public void Deal()
        {
            int size = 52 / 2;
            for(int i = 0; i < size; i++)
            {
                    Random();
                    for(int z = 0; z < cardCheck.length; z++)
                    {
                        if(cardCheck[i] == null)
                        {
                            cardCheck[i] = Deck.get(rnd);
                            play1.add(cardCheck[i]);
                            System.out.println(play1);
                        }
                        else
                        {
                            Random();
                        }
                    } 
            }
            System.out.println();
            System.out.println();
            for(int i = 0; i < size; i++){
                Deck.remove(play1.get(i));
            }
                for(int i = 0; i < size; i++){
                    play2.add(Deck.get(i));
            }
            for(int i = 0; i < size; i++)

            {
                System.out.println(play2.get(i));
            }   
    }
    public void Random()
    {
        rnd = (int)(Math.random() * 52) - decrease;
    }

    public void flip()
    {
        if(play1.indexOf(cardnum) >= play1.size() || play2.indexOf(cardnum2) >= play2.size())
        {
        cardnum = (int)(Math.random() * play1.size());
        System.out.println(play1.get(cardnum));
        cardnum2 = (int)(Math.random() * play2.size());
        System.out.println(play2.get(cardnum2));
      }
     }
     public void compare()
     {
        System.out.println("War!!!\n");
        if(play1.get(cardnum).getNum() > play2.get(cardnum2).getNum())
        {
            System.out.println();
            winner = 1;
            System.out.println(play1.get(cardnum) + " vs " + play2.get(cardnum2));
            play1.add(play2.get(cardnum2));
            play2.remove(cardnum2);
            System.out.println("Player 1 took the cards!");
            System.out.println();
            printDecks();
        }
        if(play1.get(cardnum).getNum() < play2.get(cardnum2).getNum())
        {
            System.out.println();
            winner = 2;
            System.out.println(play1.get(cardnum) + " vs " + play2.get(cardnum2));
            play2.add(play1.get(cardnum));
            play1.remove(cardnum);
            System.out.println("Player 2 took the cards!");
            System.out.println();
            printDecks();
           }
        if(play1.get(cardnum).getNum() == play2.get(cardnum2).getNum())
        {
            System.out.println();
            System.out.println(play1.get(cardnum) + " vs " + play2.get(cardnum2));
            System.out.println("War!!");
            winner = 0;
            flip();
            flip();
            flip();
            compare();
            System.out.println();
            printDecks();
         }
        }

    public void playW()
    {
        while(play1.size() > 0 || play2.size() > 0)
        {
            flip();
            compare();
        }
    }
    public void printDecks()
    {
        for(int i = 0; i < play1.size(); i++)
        {   
            System.out.print(play1.get(i) + " ");
        }
        System.out.println();
        for(int i = 0; i < play2.size(); i++)
        {   
            System.out.print(play2.get(i) + " ");
        }
        System.out.println();
        System.out.println("Player 1 has: " + play1.size() + " cards");
        System.out.println("Player 2 has: " + play2.size() + " cards");
    }
}

【问题讨论】:

  • 是的,不要调用compare() within compare() 方法。另外你为什么要给一个类,Deck,一个同名的字段,Deck ArrayList?这会让我们所有人以及未来的你感到困惑。
  • 话虽如此,您的整个程序结构都被破坏了,因为您不加选择地将用户界面与您的关键结构类混合在一起。重新编写此代码,然后将用户界面移出 Deck。
  • @HovercraftFullOfEels 对不起这些名字......我是java新手,已经养成了一些我需要改掉的坏习惯:/所以你会建议我写一个单独的方法,以防万一一场战争并在那里使用我的 compare() 方法?谢谢,这是我第一个完全独立的项目,我没有计划好,但至少这是一次学习经历:)
  • @HovercraftFullOfEels 我是否需要将用户界面移动到我的驱动程序中?谢谢!
  • 比较方法应该做一件事:比较两个实体,不管它们是什么,不多也不少。通常它们被写成返回一个 int,+1 或正值表示第一个大于第二个,-1 或负值表示相反,0 表示它们比较相同。它不会获得用户交互,也不会改变任何东西的状态作为副作用。是的,用户界面应该是驱动程序的一部分,如果简单的话,或者是一个单独的类或连接在驱动程序类中的一组类。

标签: java arrays memory-management stack-overflow


【解决方案1】:

这更像是一条评论,但它变得太长了。

关于这段代码有很多话要说。使用 switch case 而不是一系列 if。或者至少使用 if else。如果您在内部使用案例,那么 for 循环的意义何在?如果您随后为自己增加一个 suitNum 变量,那么“i”变量是什么?不要在方法中使用大写字母。只有上课。为什么 Random 编辑变量并返回 void? random() 返回你想要的结果会更合乎逻辑,这样你就可以摆脱无用的变量 'rnd'

还有很多话要说,但这是一个好的开始。关于您的错误,简而言之,堆栈溢出意味着您的程序使用了太多内存。这在包含无限递归循环的代码中尤其常见。这里,无限递归是由于compare方法内部调用了compare方法...

【讨论】:

    【解决方案2】:

    除了我的班级没有很好地递归之外,对这个错误甚至意味着什么知之甚少。

    是的,您的代码有递归,而且很容易找到。您知道问题出在 compare 方法内部,因此您所要做的就是在该方法中查找 compare() 并找出方法调用本身的位置。

    解决方案是不调用自身内部的方法,为什么要这样做呢?

    您遇到问题的部分原因是您的班级结构被破坏了。 Deck 类是应该代表一副纸牌的结构和行为的类,不多不少,它应该有public void shuffle()public Card Deal() 等方法。它不应该有任何直接与用户交互的代码,并且该代码应该放在其他地方,可能在您的驱动程序或游戏类中,甚至完全作为单独的类。

    我猜你还想有一个 Hand 类,一个持有玩家手的类,也许在这个类内部,有一个比较当前手与另一手的比较方法,作为传入的参数。

    您还需要一个 Game 类应该有一个游戏循环来控制游戏,当有赢家或平局时结束,持有 Deck,持有 1 个或多个 Player 对象...

    例如,

    public enum Suit {
        CLUBS, DIAMONDS, HEARTS, SPADES
    }
    

    public enum Value {
        //.... 
    }    
    

    public class Card {
        private Suit suit;
        private Value value;
    
        // TODO: constructor, methods including equals, hashCode
    }
    

    public class Deck {
        private List<Card> cards = new ArrayList<>();
    
        public Card deal() {
            return cards.remove(0);
        }
    
        public void shuffle() {
            Collection.shuffle(cards);
        }
    
        //....
    
    }
    

    class Player {
        // either use a List in each Player or create a class called hand
        private List<Card> hand;
        private int cash;
        private String name;
        private Game game;
    
        // TODO: constructor
        // TODO: methods including receiveCard(Card c), List<Card> showHand(),...
    }
    

    public class Game {
        private Player p1;
        private Player p2;
        private Deck deck;
        private int moneyPot;
    

    【讨论】:

    • 谢谢!我感到有些沮丧,但我认为我可以重新开始并快速跟上进度。良好的学习曲线,我认为这将激发我继续改进的动力。
    • 有一个超出你能力的项目是最好的进步方式。不要犹豫,向其他开发人员展示你的代码,以帮助你改正你的坏习惯。祝你好运。
    猜你喜欢
    • 2017-08-09
    • 2020-07-24
    • 2013-07-13
    • 2015-09-12
    • 2020-12-12
    • 2013-07-25
    • 2022-08-09
    • 2020-07-17
    • 1970-01-01
    相关资源
    最近更新 更多