当我递归调用它时,为啥我的函数返回以前的值而不是新的值?

Posted

技术标签:

【中文标题】当我递归调用它时,为啥我的函数返回以前的值而不是新的值?【英文标题】:Why does my function return the previous values and not the new ones when I call it recursively?当我递归调用它时,为什么我的函数返回以前的值而不是新的值? 【发布时间】:2015-03-03 15:26:22 【问题描述】:

我要编写一个启动 2 个玩家的程序,将相同的 Dealer 实例传递给每个玩家。在为每位玩家发完 7 张牌后,每位牌手应将自己的牌张列表打印到一个文本文件中,该文件的名称为玩家编号。

现在,在多米诺骨牌游戏中,两个玩家不能拥有相同的牌,即(玩家 1:2,4 AND 玩家 2:4,2)。

我使用了一个 2D 布尔标志数组来检查这一点,但是每当我打印出列表时,我发现 2 个或更多玩家拥有相同的牌。另外,请注意,我必须使用线程来代表玩家。

这是我的 Player 的运行方法。每个玩家应该得到 7 张牌。

public synchronized void run() 

try 
    try (PrintWriter writer = new PrintWriter("Player " + player + ".txt")) 
        for (int i = 0; i < 7; i++) 
            Random r = new Random();
            int a = r.nextInt(6);
            int b = r.nextInt(6);
            System.out.println("Player " + player + " is requesting a tile");
            DominoTiles dealt = dealer.deal(a, b);
            tiles[i] = dealt;

            writer.println("Requesting Player " + player + ": ");
            writer.println("Side 1 = " + tiles[i].getSide1() + " Side 2 = " + tiles[i].getSide2());

        
     catch (InterruptedException ex) 
        Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex);
    

 catch (FileNotFoundException ex) 
    Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex);



这是我的经销商的交易方法。如果它进入 if 块,我将返回该函数,如果它进入 else if 块,则再次调用它。问题是,我返回使函数进入 else if 块的值!

 public synchronized DominoTiles deal(int a, int b) throws FileNotFoundException, InterruptedException 
DominoTiles dealt = new DominoTiles(a, b);
System.out.println("Dealer is dealing");

if ((count < 28 && check[a][b] == false)) 
    System.out.println("Checking " + a + " " + b + ": " + check[a][b]);

    System.out.println(a + " " + b + " has been dealt");

    check[a][b] = true;
    check[b][a] = true;
    System.out.println("Checking now : " + check[a][b]);
    count++;
    System.out.println("Count = " + count);

 else if ((count < 28 && (check[a][b] == true || check[b][a] == true)) || (check[b][a] == true)) 
    System.out.println("I tried to deal the same again!" + a + " " + b + " and it was " + check[a][b] + " " + check[b][a
            ]);
    int c = r.nextInt(7);
    int d = r.nextInt(7);
    deal(c, d);
 else 
    System.out.println("All tiles have been dealt");
    System.exit(0);


return dealt;


【问题讨论】:

如果您可以制作这个可执行文件,我们将更容易找出问题所在。执行时更容易阅读代码 可执行文件是指显示输出吗? 你为什么要递归,而不仅仅是循环?调用System.exit(0) 的方法通常是个坏主意。改为抛出异常... 反正你的方法不好。你不应该试图解决这个问题——让它死掉。为每个可能的图块创建一个List,然后通过将其从列表中删除来从该列表中随机绘制一个图块。这是可能的,因为您可以使用的图块数量非常有限。 这是一种更好的算法。 shuffled = Collections.shuffle(range_of_numbers) player_1_random_1 = shuffled[0], player_1_random_2 = shuffled[1], player_2_random_1 = random.select(Collections.shuffle(shuffled.slice(2,n))), player_2_random_2 = random.select(Collections .shuffle(range_of_numbers_without_player_2_random_1));顺便说一句,这不是 java 代码......只是伪代码,但你明白了。不需要丑陋的循环或递归。 【参考方案1】:

这是因为您没有将递归调用 deal() 的结果分配给 dealt 变量。

修复:

public synchronized DominoTiles deal(int a, int b) throws  FileNotFoundException, InterruptedException 
    DominoTiles dealt = new DominoTiles(a, b);
    System.out.println("Dealer is dealing");

    if ((count < 28 && check[a][b] == false)) 
        System.out.println("Checking " + a + " " + b + ": " + check[a][b]);

        System.out.println(a + " " + b + " has been dealt");

        check[a][b] = true;
        check[b][a] = true;
        System.out.println("Checking now : " + check[a][b]);
        count++;
        System.out.println("Count = " + count);


     else if ((count < 28 && (check[a][b] == true || check[b][a] == true)) || (check[b][a] == true)) 
        System.out.println("I tried to deal the same again!" + a + " " + b + " and it was " + check[a][b] + " " + check[b][a
        ]);
        int c = r.nextInt(7);
        int d = r.nextInt(7);
        dealt = deal(c, d);
     else 
        System.out.println("All tiles have been dealt");
        System.exit(0);
    

    return dealt;


【讨论】:

【参考方案2】:

您需要将任何可以跨线程使用的变量标记为 volatile 以供初学者使用。

【讨论】:

方法是同步的——这不是问题 同步只使变量在进入和退出同步阶段时被“刷新”。根据样本,我没有看到足够好的可靠保证。可能是这样,但我们没有看到全貌。

以上是关于当我递归调用它时,为啥我的函数返回以前的值而不是新的值?的主要内容,如果未能解决你的问题,请参考以下文章

如何按显示的值而不是数据字段值对gridview列进行排序/过滤

为啥我的 Python 函数打印一个值但返回 None? [关闭]

UseState 总是显示以前的值[重复]

为啥 SQL 服务器在我的表中插入 0 值而不是使用函数的正确值

为啥这个递归函数返回正确的值? [复制]

我可以从我的控制器返回一个值而不是视图吗?