【问题标题】:get bool from other method to end while loop从其他方法获取 bool 以结束 while 循环
【发布时间】:2011-10-20 12:56:35
【问题描述】:

我很难从 EndLoop() 获取 bool done 值并将其移动到 Start() 方法以结束我的 while 循环。我做错了什么?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {


        public static void Main(string[] args)
        {
            Start("r");
        }

        public static string Start(string move)
        {

            Console.Write("Welcome to the Shotgun App\nEnter s for single player and m for multiplayer: ");
            string gameType = Console.ReadLine();

            if (gameType == "s")
            {

                Console.Write("Single Player Controls:\n r = reload\n s = shield\n f = fire\nYou start with 1 ammo\nReady to play?");
                Console.ReadLine();

                int ammo = 1;
                int geniusAmmo = 1;
                string geniusMove = "";
                bool done = false;
                while (!done)
                {
                    Console.Write("\nEnter your move: ");
                    move = Console.ReadLine();


                    switch (move)
                    {
                        case "r":
                            Console.Write("\nYou have reloaded, press enter for Genius\n");

                            ammo++;
                            Console.Write("Your ammo is " + ammo);

                            Console.ReadLine();
                            Genius(geniusMove, move, geniusAmmo, done);


                            break;
                        case "s":
                            Console.Write("\nYou have shielded, press enter for Genius\n");

                            Console.Write("Your ammo is " + ammo);

                            Console.ReadLine();
                            Genius(geniusMove, move, geniusAmmo, done);


                            break;
                        case "f":
                            if (ammo != 0)
                            {
                                Console.Write("\nYou have fired, press enter for Genius\n");

                                ammo--;
                                Console.Write("Your ammo is " + ammo);

                                Console.ReadLine();

                                Genius(geniusMove, move, geniusAmmo, done);

                            }
                            else
                            {
                                Console.Write("You don't have enough ammo, try again");
                                done = false;
                            }
                            break;
                        default:
                            Console.Write("\nInvalid move, try again\n");
                            done = false;
                            break;
                    }

                    Console.ReadLine();

                }
                return move;
            }
            else
            {
                return move;
            }
        }

        public static string Genius(string geniusMove, string move, int geniusAmmo, bool done)
        {
            Random RandomNumber = new Random();
            int x = RandomNumber.Next(0,3);
            if (x == 0)
            {
                geniusMove = "f";
                geniusAmmo--;
                Console.Write("Genius had decided to fire.\nGenius ammo is " + geniusAmmo + "\n");
                TestMoves(move, geniusMove);
            }
            else if (x == 1)
            {
                geniusMove = "r";
                geniusAmmo++;
                Console.Write("Genius had decided to reload.\nGenius ammo is " + geniusAmmo + "\n");
                TestMoves(move, geniusMove);
            }
            else if (x == 2)
            {
                geniusMove = "s";  
                Console.Write("Genius had decided to shield.\nGenius ammo is " + geniusAmmo + "\n");
                TestMoves(move, geniusMove);
            }

            return geniusMove;

        }


        public static void TestMoves(string move, string geniusMove)
        {
            bool done = false;
            if (move == "s" && geniusMove == "f")
            {
                Console.Write("Nice shield, no one has died yet");
                EndLoop(move, geniusMove, done);


            }
            else if (move == "f" && geniusMove == "f")
            {
                Console.Write("You both died!  Good game!");
                EndLoop(move, geniusMove, done);


            }
            else if (move == "r" && geniusMove == "f")
            {
                Console.Write("No shield!?  You died!  Good game!");
                EndLoop(move, geniusMove, done);


            }
            else if (move == "f" && geniusMove == "s")
            {
                Console.Write("Genius is too good, no one has died yet");
                EndLoop(move, geniusMove, done);


            }
            else if (move == "f" && geniusMove != "s")
            {
                Console.Write("Genius let his guard down!  Good game!");
                EndLoop(move, geniusMove, done);


            }
            else if (move != "f" && geniusMove != "f")
            {
                Console.Write("Keep playing it safe.");
                EndLoop(move, geniusMove, done);


            }
            else
            {
                EndLoop(move, geniusMove, done);

            }

        }

        public static bool EndLoop(string move, string geniusMove, bool done)
        {

            if (move == "s" && geniusMove == "f")
            {
                done = false;
                Console.Write(move + geniusMove + done);
                return done;
            }
            else if (move == "s" && geniusMove == "r")
            {
                done = false;
                Console.Write(move + geniusMove + done);
                return done;
            }
            else if (move == "s" && geniusMove == "s")
            {
                done = false;
                Console.Write(move + geniusMove + done);
                return done;
            }
            else if (move == "r" && geniusMove == "f")
            {
                done = true;
                Console.Write(move + geniusMove + done);
                return done;
            }
            else if (move == "r" && geniusMove == "r")
            {
                done = false;
                Console.Write(move + geniusMove + done);
                return done;
            }
            else if (move == "r" && geniusMove == "s")
            {
                done = false;
                Console.Write(move + geniusMove + done);
                return done;
            }
            else if (move == "f" && geniusMove == "f")
            {
                done = true;
                Console.Write(move + geniusMove + done);
                return done;
            }
            else if (move == "f" && geniusMove == "r")
            {
                done = true;
                Console.Write(move + geniusMove + done);
                return done;
            }
            else if (move == "f" && geniusMove == "s")
            {
                done = false;
                Console.Write(move + geniusMove + done);
                return done;
            }
            else
            {
                done = false;
                Console.Write(move + geniusMove + done);
                return done;
            }
        }
    }
}

【问题讨论】:

  • 为什么要在循环中返回完成?设置它应该足够了
  • 还是不行……
  • 在 EndLoop() 的参数中完成的 bool 应定义为 'ref bool done' 以使更改在调用方法中生效。

标签: c# while-loop boolean


【解决方案1】:

我知道我没有直接回答您的问题,但我想我会尝试为您提供另一种实现游戏的方法,使用对象和 LINQ,并尝试使代码更加模块化。真的是为了利益。

这里是:

void Main()
{
    var moves = new Dictionary<string, Move>()
    {
        { "r", new Move(1, "Reloaded") },
        { "s", new Move(0, "Shielded") },
        { "f", new Move(-1, "Fired") },
    };

    var messages = new Dictionary<string, string>()
    {
        { "Shielded-Fired", "Nice shield, no one has died yet" },
        { "Fired-Fired", "You both died!  Good game!" },
        { "Reloaded-Fired", "No shield!?  You died!  Good game!" },
        { "Shielded-Shielded", "Keep playing it safe." },
        { "Fired-Shielded", "Genius is too good, no one has died yet" },
        { "Reloaded-Shielded", "No-one fired" },
        { "Shielded-Reloaded", "No-one fired" },
        { "Fired-Reloaded", "Genius let his guard down!  Good game!" },
        { "Reloaded-Reloaded", "No-one fired" },
    };

    var isDone = new Dictionary<string, bool>()
    {
        { "Shielded-Fired", false },
        { "Fired-Fired", true },
        { "Reloaded-Fired", true },
        { "Shielded-Shielded", false },
        { "Fired-Shielded", false },
        { "Reloaded-Shielded", false },
        { "Shielded-Reloaded", false },
        { "Fired-Reloaded", true },
        { "Reloaded-Reloaded", false },
    };

    var rnd = new Random();
    var choices = new [] { "r", "s", "f", };

    var human = new Player("You", () => Console.ReadLine(), m => Console.WriteLine(m));
    var genius = new Player("Genius", () => choices[rnd.Next(0, 3)], m => { });

    var allMoves = GetPlayerMoves(moves, human).Zip(GetPlayerMoves(moves, genius), (h, g) =>
    {
        human.Play(h);
        genius.Play(g);
        var hg = String.Format("{0}-{1}", h.Name, g.Name);
        Console.WriteLine(messages[hg]);
        return isDone[hg];
    });

    foreach (var done in allMoves)
        if (done)
            break;
}

private static IEnumerable<Move> GetPlayerMoves(Dictionary<string, Move> moves, Player player)
{
    while (true)
    {
        player.WriteMessage("\nEnter your move: ");
        var choice = player.GetChoice();
        if (moves.ContainsKey(choice))
        {
            var move = moves[choice];
            if (move.Play(player.Ammo) < 0)
            {
                player.WriteMessage("\nYou don't have enough ammo, try again.\n");
            }
            else
            {
                yield return move;
            }
        }
        else
        {
            player.WriteMessage("\nInvalid move, try again.\n");
        }
    }
}

public class Player
{
    public Player(string name, Func<string> getChoice, Action<string> writeMessage)
    {
        this.Name = name;
        this.Ammo = 1;
        _getChoice = getChoice;
        _writeMessage = writeMessage;
    }

    private readonly Func<string> _getChoice;
    private readonly Action<string> _writeMessage;

    public string GetChoice()
    {
        return _getChoice();
    }

    public void WriteMessage(string message)
    {
        _writeMessage(message);
    }

    public string Name { get; private set; }
    public int Ammo { get; private set; }

    public void Play(Move move)
    {
        this.Ammo = move.Play(this.Ammo);
        Console.Write(String.Format("{0} {1} (ammo is {2}.)\n", this.Name, move.Name.ToLowerInvariant(), this.Ammo));
    }
}

public class Move
{
    public Move(int ammoChange, string name)
    {
        this.AmmoChange = ammoChange;
        this.Name = name;
    }

    public string Name { get; private set; }

    private int AmmoChange { get; set; }

    public int Play(int ammo)
    {
        return ammo + AmmoChange;
    }
}

【讨论】:

    【解决方案2】:

    在你的类的范围内声明static bool done = false; 并使用相同的而不是通过不同的方法传递state。如果您将状态传递给调用函数Start,您可以这样做。

    【讨论】:

      【解决方案3】:

      您有两个名为 done 的局部变量。它们是单独的变量,因此 Start 中的 done 与 TestMoves 中的 done 不同。而且和EndLoop中的参数都不一样。

      最佳实践是实际创建一个 Program 实例,并拥有像 done 这样的公共变量作为类成员。

      如果您希望所有内容都是静态的,那么您只需使用一个名为 done 的静态类变量,而不是所有的局部变量和参数。

      此代码还有很多其他问题 - 例如还有其他局部变量和/或参数可以更改其值,但该更改不会影响调用方法。在 if/else if/else 的每个分支中都有很多重复的代码,可以在最后移出单个调用。

      【讨论】:

        【解决方案4】:

        当您调用 EndLoop 时,您需要将 bool done 设为静态和全局,同时设置循环中 done 的值。

        class Program
        {
            static bool done = false;
            // rest of code
        }
        

        您还应该只检查您希望将 done 设置为 true 的条件并忽略其余条件(因为将其从 false 更改为 false 没有任何作用)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-07-27
          • 1970-01-01
          • 1970-01-01
          • 2014-04-20
          • 2014-10-31
          • 2019-03-15
          相关资源
          最近更新 更多