【问题标题】:How to progress my Five Dice game如何推进我的五个骰子游戏
【发布时间】:2016-01-16 17:16:34
【问题描述】:

我正在学习编程,尤其是从 C# 开始,我一直在尝试骰子游戏以变得更加熟悉并提高自己。我现在正在尝试在 Windows 窗体中创建一个基本游戏,其中两名玩家掷 5 个骰子并记录他们的得分。

规则:

  • 从 5 个骰子开始

  • 如果出现 1 或 4,则玩家不得分,并且这些骰子被移除。否则将所有骰子加到总数中

  • 继续使用剩余的骰子,直到没有剩余的骰子

到目前为止,我有一个 Image 数组,它将我所有的骰子图像存储在我的资源中,还有一个可以掷骰子的按钮。我特别需要帮助的是能够移除惩罚骰子(将那个特定的骰子设置回空白)并允许玩家继续滚动剩余的骰子,直到没有剩余。

目前我不确定我可以在哪里进一步做到这一点,也许我咬得比我能咀嚼的多。我喜欢编码,任何帮助将不胜感激。

这是界面的图像:

public partial class Form1 : Form
{

    Image[] diceImages;
    int[] dice;
    int[] diceResults;
    Random random;

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        diceImages = new Image[7];
        diceImages[0] = Properties.Resources.blank;
        diceImages[1] = Properties.Resources.one;
        diceImages[2] = Properties.Resources.two;
        diceImages[3] = Properties.Resources.three;
        diceImages[4] = Properties.Resources.four;
        diceImages[5] = Properties.Resources.five;
        diceImages[6] = Properties.Resources.six;

        dice = new int[5] { 0, 0, 0, 0, 0 };

        random = new Random();

        diceResults = new int[6] { 0, 0, 0, 0, 0, 0 };

    }

    private void btn_rollDice_Click(object sender, EventArgs e)
    {
        RollDice();

        GetResults();

        ResetResults();
    }

    private void RollDice()
    { 
        for (int i = 0; i < dice.Length; i++)
        {
            dice[i] = random.Next(1, 7);

            switch (dice[i])
            { 
                case 1:
                    diceResults[0]++;
                    break;
                case 2:
                    diceResults[1]++;
                    break;
                case 3:
                    diceResults[2]++;
                    break;
                case 4:
                    diceResults[3]++;
                    break;
                case 5:
                    diceResults[4]++;
                    break;
                case 6:
                    diceResults[5]++;
                    break;

            }

        }

        lbl_dice1.Image = diceImages[dice[0]];
        lbl_dice2.Image = diceImages[dice[1]];
        lbl_dice3.Image = diceImages[dice[2]];
        lbl_dice4.Image = diceImages[dice[3]];
        lbl_dice5.Image = diceImages[dice[4]];
    }

    private void GetResults()
    {
        bool oneRoll = false, fourRoll = false;

        for (int i = 0; i < diceResults.Length; i++)
        {
            if (diceResults[i] == 1 && diceResults[i] == 4)
            {
                oneRoll = true;
                fourRoll = true;
            }
        }
    }

    private void ResetResults()
    {

    }

}

【问题讨论】:

  • 那么问题是什么?
  • @CodeCaster 抱歉,如果玩家掷出 1 或 4,我需要帮助将骰子图像重置为空白骰子。但是,允许他们继续滚动剩余的骰子,直到他们没有剩余的骰子。
  • @CodeCaster 例如。掷出 1 = 1, 3, 3, 4, 5。玩家不得分,骰子 1 和骰子 4 被移除,留下 3 个骰子。掷 2 = 5, 6, 3。玩家得 14 分并继续掷骰直到没有骰子。导致其他玩家轮流。
  • 我会将 diceResults 设为列表对象。这将适用于您当前的代码: diceResults = diceResults.Where(x => (x != 1) && (x != 4)).ToArray();
  • @jdweng 我试试看。干杯

标签: c# arrays loops dice


【解决方案1】:

您发布的代码至少有几个与您的描述不符的奇怪之处:

  • 代码只是增加数组中的一个元素(diceResults),当滚动给定骰子值时(即元素对应于骰子值,而不是die 在游戏中的顺序)。根据您的描述,我希望代码只是将骰子值添加到单个 sum 变量中。
  • 在您的GetResults() 方法中,您的代码将diceResults 中的各个元素值与2 和5 的值进行比较。换句话说,对于每个可能的骰子值,如果该值出现两次或五次,则设置两个标志。奇怪的原因有很多,但最大、最明显的一个原因是单个变量(即元素 diceResults[i])从不同时具有两个不同的值。 IE。正如if 语句所要求的那样,该数组元素永远不会同时是2 和5。

鉴于这些问题,我更倾向于关注原始规范,而不是在试图理解代码的实际预期行为方面过于信任代码。 :)

似乎基本问题是如何最好地从游戏中移除骰子。使用列表来跟踪骰子的建议(在上面的 cmets 中)当然是可行的。在这种方法中,将遍历列表以设置每个元素,如果给定元素的滚动出现为 1 或 4,请在继续之前删除该元素。

完成此操作后,只需再次遍历列表以设置骰子值图像,对超出列表长度的任何骰子使用“空白”图像。

但是有一种更简单的方法,根据您的陈述“将特定的那个设置回空白”,这似乎意味着每个空白骰子应该出现在它所在的相同位置滚动,似乎更简单的方法可能更适合您。

具体来说,掷骰子后,只需扫描dice 数组并将任何1 和4 值重置为0,并将此0 值用作特殊的“哨兵”值来指示那个骰子现在是空白的。

请注意,无论您如何执行此操作(使用列表或仅将值设置为 0),还有一个问题是是否向用户显示实际的 1 和 4 滚动,或立即设置那些卷到一个空白模具上。我将假设前者,但以另一种方式实现它会很容易。 (一如既往,好的代码的开始是好的规范……现在,你的规范对细节有点轻,因此含糊不清)。

采用这种方法,您的代码可能看起来更像这样:

public partial class Form1 : Form
{
    #region Declaration
    Image[] diceImages;
    Label[] labels;
    int[] dice;
    int diceTotal;
    bool checkOnesAndFours;
    Random random;
    #endregion

    #region Initialiazation;
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        // Initializing an array this way eliminates the chance of having
        // a typo in the array index for the assignment.
        diceImages = new Image[]
        {
            Properties.Resources.blank,
            Properties.Resources.one,
            Properties.Resources.two,
            Properties.Resources.three,
            Properties.Resources.four,
            Properties.Resources.five,
            Properties.Resources.six
        };

        // Arrays are always initialized with the elements having their default
        // values, so there's no need to specify `0` values for `int` arrays explicitly
        dice = new int[5];

        random = new Random();

        diceTotal = 0;

        // For the purposes of setting the dice images, it will be helpful
        // to keep the control references in an array. This is both convenient
        // and, again, helps guard against typographical errors
        labels = new Label[]
        {
            lbl_dice1,
            lbl_dice2,
            lbl_dice3,
            lbl_dice4,
            lbl_dice5
        };
    }

    #endregion

    #region Private Methods

    private void btn_rollDice_Click(object sender, EventArgs e)
    {
        RollDice();
    }

    private void RollDice()
    {
        bool rolledOneOrFour = false;
        int rollTotal = 0;

        for (int i = 0; i < dice.Length; i++)
        {
            if (checkOnesAndFours)
            {
                // First, clear any 1 or 4 from the previous roll
                if (dice[i] == 1 || dice[i] == 4)
                {
                    dice[i] = 0;
                }

                // Then, ignore any blank die
                if (dice[i] == 0)
                {
                    continue;
                }
            }

            dice[i] = random.Next(1, 7);
            if (dice[i] == 1 || dice[i] == 4)
            {
                rolledOneOrFour = true;
            }
            rollTotal += dice[i];
        }

        if (!rolledOneOrFour)
        {
            diceTotal += rollTotal;
        }

        checkOnesAndFours = true;

        for (int i = 0; i < labels.Length; i++)
        {
            labels[i].Image = diceImages[dice[i]];
        }
    }

    #endregion
}

注意:当1 或4 出现时,我并不完全清楚你的意思。从字面上看,我理解它的意思是,如果 any die 显示 1 或 4 滚动,那么 none 的骰子计数卷。上面的代码是在这种理解下实现的。

我突然想到,您可能的意思是,只有显示 1 或 4 的骰子不计入该掷骰,并且该掷骰的其他骰子仍包括在内。更改上述内容以适应该替代规范并不难。

注意:您还会注意到,为了解决当前的问题,我对代码进行了技术上不需要的其他更改。我在代码本身中添加了 cmets,试图解释我为什么做出这些更改,以及为什么我觉得它们会使代码变得更好。


只是为了笑,这是一个使用列表的版本:

public partial class Form1 : Form
{
    #region Declaration
    Image[] diceImages;
    Label[] labels;
    List<int> dice;
    int diceTotal;
    bool checkOnesAndFours;
    Random random;
    #endregion

    #region Initialiazation;
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        // Initializing an array this way eliminates the chance of having
        // a typo in the array index for the assignment.
        diceImages = new Image[]
        {
            Properties.Resources.blank,
            Properties.Resources.one,
            Properties.Resources.two,
            Properties.Resources.three,
            Properties.Resources.four,
            Properties.Resources.five,
            Properties.Resources.six
        };

        // Lists must be initialized explicitly with their initial values, as by default
        // they are initially empty.
        dice = new List<int>(Enumerable.Repeat(0, 5));

        random = new Random();

        diceTotal = 0;

        // For the purposes of setting the dice images, it will be helpful
        // to keep the control references in an array. This is both convenient
        // and, again, helps guard against typographical errors
        labels = new Label[]
        {
            lbl_dice1,
            lbl_dice2,
            lbl_dice3,
            lbl_dice4,
            lbl_dice5
        };
    }

    #endregion

    #region Private Methods

    private void btn_rollDice_Click(object sender, EventArgs e)
    {
        RollDice();
    }

    private void RollDice()
    {
        bool rolledOneOrFour = false;
        int rollTotal = 0;

        for (int i = 0; i < dice.Count; i++)
        {
            // Clear any 1 or 4 from the previous roll
            if (checkOnesAndFours && (dice[i] == 1 || dice[i] == 4))
            {
                // Remove this die from play
                dice.RemoveAt(i);

                // The next list element to examine is now at the current i value
                // and the for loop is going to increment i when the continue
                // is executed, so decrement i in anticipation of that
                // so that the loop moves on to the correct next element
                i--;

                continue;
            }

            dice[i] = random.Next(1, 7);
            if (dice[i] == 1 || dice[i] == 4)
            {
                rolledOneOrFour = true;
            }
            rollTotal += dice[i];
        }

        if (!rolledOneOrFour)
        {
            diceTotal += rollTotal;
        }

        checkOnesAndFours = true;

        for (int i = 0; i < labels.Length; i++)
        {
            labels[i].Image = i < dice.Count ? diceImages[dice[i]] : diceImages[0];
        }
    }

    #endregion
}


最后,请注意,以上都没有解决代码的其他几个问题:

  • 在游戏开始时初始化骰子标签。
  • 游戏结束后重置整个游戏(即没有剩余的骰子)。

我将这两个项目留给读者作为练习(当然,如果您遇到这些特定问题的问题,您可以随时在 Stack Overflow 上发布另一个问题,具体询问每个问题)。

【讨论】:

  • 感谢您的帮助,如果我的问题不清楚,我们深表歉意。关于 2 和 5,我试图想出常见的数字,从而在掷出该数字时惩罚玩家。我发现 2 和 5 很常见,所以我改用了 1 和 4(在提问之前我忘记在代码中更改)。如果出现 1 或 4,那么是的,该掷骰子数都没有。我没有遇到过使用列表,我很欣赏有其他不同的方式来实现这一点。
  • 这部分代码在这里:diceImages = new Image[] { Properties.Resources.blank; Properties.Resources.one;属性.资源.二;属性.资源.三;属性.资源.四;属性.资源.五;属性.资源.六; };这些都应该有逗号而不是分号是吗?
  • "所以我改用 1 和 4" -- 使用 2/5 还是 1/4 无关紧要;关键是您要检查的值是特定骰子面出现了多少次,而不是哪个 骰子面出现了。请注意,在滚动单个 6 面骰子时,或使用 Random.Next(1, 7) 方法调用时,每个数字都有同样出现的可能性。 2/5 并不比 1/4 更常见或更少。
  • 是的,需要逗号而不是分号;未能提供a good, minimal, complete code example 的缺点之一是答案通常只是输入到浏览器中,甚至没有任何编译,更不用说测试了。 :)
  • 好的,谢谢。我已经完成了您的回答(数组设置)彼得,现在当我单击“滚动”按钮时,什么也没有发生(骰子图像不会改变)但没有错误。我正在使用RollDice 方法,我看不到任何可以阻止它更改骰子图像的东西。
猜你喜欢
  • 2014-02-12
  • 2012-02-29
  • 2021-12-14
  • 2015-08-25
  • 2015-12-24
  • 1970-01-01
  • 2014-03-16
相关资源
最近更新 更多