【问题标题】:C# Random console math equation game: Converting string back to equation?C# 随机控制台数学方程式游戏:将字符串转换回方程式?
【发布时间】:2018-10-16 21:35:35
【问题描述】:

我目前正在自学 C#,并提出了一个程序想法如下:

  1. 程序生成随机数
  2. 程序生成随机数学运算符
  3. 程序生成随机数
  4. 询问用户随机生成问题的答案
  5. 用户输入答案
  6. 程序将生成问题的结果与用户输入进行比较
  7. 程序打印用户是否正确。

我遇到的问题是我只能以以下格式/数据类型打印方程式:

(示例)5 + 1 (数字,字符串运算符,数字)

或将上述数据类型组合成一个字符串

从那里的问题是,我无法弄清楚如何将所有这些转换为可以存储在变量中的数学方程,然后与用户的输入进行比较。

我确信我做的比它可能的更困难,但我一直在这个程序、论坛和大量帖子中,但无法将任何东西拼凑在一起。

在我学习 C# 的过程中,我将不胜感激任何对我的代码的见解以及我出错的地方!

public static void Main(string[] args)
{
    mathProblem();
    int userAnswer = Convert.ToInt32(Console.ReadLine());
}

public static void mathProblem()
{
    Random numberGenerator = new Random();
    Random operatorSelect = new Random();

    //Generates random number for 1st part of problem
    int number1 = numberGenerator.Next(1, 11);
    //Generates random number for 2nd part of problem
    int number2 = numberGenerator.Next(1, 11);
    //int to store/assign random operator
    int mathOperator = 0;
    //newOperator set to empty string that will change and store operator generated
    string newOperator = "";

    // gives value of 1-4
    mathOperator = operatorSelect.Next(5);
    switch (mathOperator)
    {
        case 1:
            newOperator = "+";
            break;
        case 2:
            newOperator = "-";
            break;
        case 3:
            newOperator = "*";
            break;
        case 4:
            newOperator = "/";
            break;
        default:
            newOperator = "+"; 
            break;
    }

    Convert.ToString(number1);
    Convert.ToString(number2);

    Console.WriteLine("What is " + number1 + " " + newOperator + " " + number2 + "?");
}

【问题讨论】:

  • 你不需要存储数学方程,你只需要执行方程并存储结果。除此之外,您的 switch 语句必须实际执行数学运算,而不仅仅是分配 newOperator 变量
  • 你有一个在所有级别的开发者中都非常常见的障碍,从初学者到专家:字符串幸福障碍。也就是说,您认为对于某些实际上不涉及 text 的任务来说,字符串是一种有用的数据类型。你正在做math,所以编写代码,将数学对象表示为mathematical objects,而不是text。试试这个:创建一个基类Expression 和两个派生类AdditionNumber。现在你知道如何表示 1 + 2 + 3 了吗?现在你可以在Expression 上实现一个方法Evaluate 吗?
  • 另外,从来没有像这样随机制作两个。使 one 随机并将其用于一切。当您在彼此之后创建两个随机数时它们都会产生完全相同的随机数序列,这根本不是您想要的。

标签: c# console-application


【解决方案1】:

算术运算是接受两个数字并返回第三个数字的函数。一般来说,它们可以表示为一个函数:

int AddOperation(int a, int b)
{
    return a + b;
}

此类函数的委托可以存储在类型为Func<int,int,int> 的变量中。

Func<int,int,int> functionPointer = AddOperation;

除了为AddOperation 声明整个方法之外,您还可以将其存储为使用lambda expression 声明的anonymous method

Func<int,int,int> functionPointer = (a,b) => a + b;

您可以存储一系列这些函数,例如,在字典中:

var operators = new Dictionary<string,Func<int,int,int>>
{
    { "+", (a,b) => a + b },
    { "-", (a,b) => a - b },
    { "*", (a,b) => a * b },
    { "/", (a,b) => a / b }
};

然后要执行一个操作,你查找函数:

var symbol = "+";
var operation = operators[symbol];

...并用它来计算结果:

var result = operation(arg1,arg2);

这是一个对数字 10 和 2 执行所有四个操作的示例:

public static void Main()
{
    var operators = new Dictionary<string,Func<int,int,int>>
    {
        { "+", (a,b) => a + b },
        { "-", (a,b) => a - b },
        { "*", (a,b) => a * b },
        { "/", (a,b) => a / b }
    };

    var arg1 = 10;
    var arg2 = 2;

    foreach (var symbol in operators.Keys)
    {
        var func = operators[symbol];
        var result = func(arg1,arg2);
        Console.WriteLine("{0}{1}{2}={3}", arg1, symbol, arg2, result);
    }
}

输出:

10+2=12
10-2=8
10*2=20
10/2=5

Link to working example on DotNetFiddle

【讨论】:

  • 如果这个游戏是为非程序员设计的,你可能需要使用印刷数学符号 + − × ÷。
  • 如果所有内容都是int,这里的除法运算可能会丢失信息...对于 C# 新手来说,这似乎有点高级
【解决方案2】:

我认为你的方向是错误的。为什么需要将运算符存储为字符串?为什么有所有这些单独的随机实例?归根结底,您需要随机生成一个数学问题,对吗?而且您必须确定用户是否得到正确的答案。

首先,使用单个 static Random 字段而不是局部变量:

private static Random rnd = new Random();

public static void GenerateRandomMathProblem()
{
    // code
}

See here 了解您为什么不想像以前那样使用多个 Random 变量。

还要考虑一个比 mathProblem() 更好的名称,使用更具描述性的名称( 一个数学问题?),同时使用正确的大小写 (PascalCase)。

第二个问题:您跟踪的变量。我认为你应该只关心这些变量:

int number1 = rnd.Next(1, 11);

int number2 = rnd.Next(1, 11);

// Store the answer, has to be a double since you have some division operation
double answer = 0;

// Store the question so you can ask the user
string question = string.Empty;

现在,您的开关盒必须执行双重任务。执行实际数学并将结果存储在answer 中并生成实际的字符串 问题并分配给question

// Case of '-'
case 1:
    answer = number1 - number2; //Gets the answer
    question = $"{number1} - {number2}"; //Syntax is called string interpolation, its a little cleaner than concatenation
    break;

我们已经生成了问题,因此我们不再需要数字变量,但请注意,您所做的 Convert 调用完全没有必要。 Console.WriteLine()自动在其参数上调用ToString()。 C# 中的每一件事都可以调用 .ToString(),因为它是 object 的成员,并且 C# 中的所有内容都继承自 System.Object

现在,最后当您提出问题时,您可以使用Console.WriteLine() 的“格式化”功能来让您的代码更简洁,而不是使用字符串连接:

// The {0} will be replaced with the value of 'question' in the console
Console.WriteLine("What is {0}?", question);

【讨论】:

  • 啊,这更有意义...知道我让事情变得比需要的复杂得多,所以非常感谢!我不知道使用字符串插值,也可以更好地清理事情。那么我假设将随机生成的问题与用户的答案进行比较,在用户输入他们的答案后,main 之外的另一个处理这个需求的函数在 main 内部调用?
  • 如果您要使用带有一组硬编码整数的 case 语句,我建议使用枚举。我宁愿看到 case 1 强制 maccettura 添加评论,而 case Operator.Minus 是不言自明的。
  • @Brian OP 是初学者。不想引入大量新概念或可能将它们移到它们在书籍/课程中的位置
  • @maccettura 没有这方面的书籍/课程,因为这只是为了我自己的学习,但衷心感谢您考虑到这一点
  • @maccettura 是的,来自网络开发学位我熟悉基本的编程概念/逻辑,但从简单的前端方面更是如此……热爱网络开发,但一直想精通编程。
猜你喜欢
  • 2018-06-04
  • 1970-01-01
  • 2017-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-16
  • 2014-10-17
相关资源
最近更新 更多