Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C 21点-发给玩家和cpu的同一张牌?_C#_.net_Blackjack - Fatal编程技术网

C# C 21点-发给玩家和cpu的同一张牌?

C# C 21点-发给玩家和cpu的同一张牌?,c#,.net,blackjack,C#,.net,Blackjack,我正在做一个没有明显原因的小黑杰克游戏,我遇到了一个问题,我不知道哪里出了问题,我唯一能想象的是,“新卡”方法被调用了两次,太快了 问题是它给两个玩家的牌是相同的:/ 这是我的密码 谢谢 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text;

我正在做一个没有明显原因的小黑杰克游戏,我遇到了一个问题,我不知道哪里出了问题,我唯一能想象的是,“新卡”方法被调用了两次,太快了

问题是它给两个玩家的牌是相同的:/

这是我的密码

谢谢

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace BlackJack_Reworked
{
    public partial class BlackJack : Form
    {
        public BlackJack()
        {
            InitializeComponent();
        }
        class myVars
        {
            public static int cardsDrawn = 0;

            public static int playerX = 230;
            public static int playerY = 160;

            public static int cpuX = 230;
            public static int cpuY = 60;

            public static int playerCardValue = 0;
            public static int cpuCardValue = 0;
        }
        private PictureBox[] card = new PictureBox[100];
        private void makeCard(string pickedCard, int x)
        {
            card[myVars.cardsDrawn] = new PictureBox();

            if (x == 0)
            {
                card[myVars.cardsDrawn].Location = new Point(myVars.playerX, myVars.playerY);
                myVars.playerX += 15;
            }
            if (x == 1)
            {
                card[myVars.cardsDrawn].Location = new Point(myVars.cpuX, myVars.cpuY);
                myVars.cpuX += 15;
            }

            card[myVars.cardsDrawn].Image = (Image)Properties.Resources.ResourceManager.GetObject(pickedCard);
            card[myVars.cardsDrawn].Size = new Size(72, 96);
            card[myVars.cardsDrawn].Parent = this;
            card[myVars.cardsDrawn].BringToFront();
            card[myVars.cardsDrawn].Update();

            myVars.cardsDrawn++;

            checkScores(false);
        }
        private void newCard(int x)
        {
            Random cardPicker = new Random();

            int cardChoice = cardPicker.Next(1, 13);
            int houseChoice = cardPicker.Next(1, 4);

            string house = null;

            switch (houseChoice)
            {
                case 1:
                    house = "Hearts";
                    break;
                case 2:
                    house = "Diamonds";
                    break;
                case 3:
                    house = "Spades";
                    break;
                case 4:
                    house = "Clubs";
                    break;
            }

            if (x == 0)
            {
                makeCard(house + Convert.ToString(cardChoice), 0);
                myVars.playerCardValue += cardChoice;
            }
            if (x == 1)
            {
                makeCard(house + Convert.ToString(cardChoice), 1);
                myVars.cpuCardValue += cardChoice;
            }
        }
        private bool feelingLucky()
        {
            Random Dice = new Random();
            if (myVars.cpuCardValue >= 20) { return false; }
            if (myVars.cpuCardValue <= 16) { return true; }
            if (myVars.cpuCardValue >= 17 && myVars.cpuCardValue <= 18) if (Dice.Next(1, 5) == 1) { return true; }
            if (myVars.cpuCardValue == 19) if (Dice.Next(1, 10) == 1) { return true; }
            return false;
        }
        private void updateHandValues()
        {
            lblPlayerHand.Text = "Player: " + myVars.playerCardValue.ToString();
            lblCPUhand.Text = "CPU: " + myVars.cpuCardValue.ToString();
        }
        private void checkScores(bool stand)
        {
            if (stand == true)
            {
                if (myVars.playerCardValue <= 21 && myVars.playerCardValue > myVars.cpuCardValue)
                {
                    MessageBox.Show("Win!");
                    btnNewGame.Visible = true;
                }
                else if (myVars.cpuCardValue <= 21 && myVars.cpuCardValue > myVars.playerCardValue)
                {
                    btnNewGame.Visible = true;
                    MessageBox.Show("Lose!");
                }
           }
            else
            {
                if (myVars.playerCardValue > 21)
                {
                    MessageBox.Show("Bust!");
                    btnNewGame.Visible = true;
                }
                if (myVars.cpuCardValue > 21)
                {
                    MessageBox.Show("Win!");
                    btnNewGame.Visible = true;
                }
            }
        }
        private void newGame()
        {
            for(int x = 0; x < myVars.cardsDrawn; x++) { card[x].Dispose(); }

            myVars.cpuCardValue = 0;
            myVars.playerCardValue = 0;
            myVars.cpuX = 230;
            myVars.playerX = 230;

            btnNewGame.Visible = false;

            newCard(0); newCard(1);
        }
        private void btnNewGame_Click(object sender, EventArgs e)
        {
            newGame();
        }
        private void btnHit_Click(object sender, EventArgs e)
        {
            newCard(0); newCard(1);
            updateHandValues();
        }
        private void btnStand_Click(object sender, EventArgs e)
        {
            if (feelingLucky() == true) newCard(1);
            else checkScores(true);
        }
    }
}
在下面这些好心人的帮助下,编辑我新的工作版本的代码,以防有人发现它有用,谢谢大家

下面是您需要添加到项目资源中的卡片图片文件,以使此代码正常工作

我知道我的逻辑可能不太好,但我觉得我已经从这个小项目中学到了东西,希望其他人也能,现在,是时候想出一些新的东西了。。谢谢你


您正在新卡方法中声明一个新随机数

如果该方法被调用两次,并且调用速度非常快,那么根据时间自动生成的种子将非常接近,它们将生成几乎相同的数字


最好的做法是在方法之外创建random的实例,并在每次调用中传递random,这样每次调用都不会得到相同的数字。

random。下一个方法从当前时间戳和以前生成的称为“种子”的数字生成随机数。当您每次创建新的随机对象时,它都会使用相同的种子进行初始化。在您的情况下,时间戳和种子不会更改为随机的“下一个”方法

如果对所有操作使用单个随机对象,则每次调用“下一步”时,种子都会更改

第二:你需要跟踪哪些牌已经被抽出来了,所以我已经创建了一个鞋子列表。我会移除已经使用过的卡片,就像真正的桌子一样

注意:当你的牌数为20时,创建一个新鞋

 List<string> aShoe = new List<string>(); //shoe contains 4 to 8 decks. Depending upon blackjack version.
 int numberOfDeckPerShoe = 4;

private void CreateNewDeck()
 {
     for(int i =0;i <numberOfDeckPerShoe;i++)
 for(int j=0;j<52;j++)
 {
            int cardFace = (j%13)+1;
        int cardSuite = (j/13) + 1;

        string Suite = null;

        switch (cardSuite)
        {
        case 1:
            Suite = "Hearts";
            break;
        case 2:
            Suite = "Diamonds";
            break;
        case 3:
            Suite = "Spades";
            break;
        case 4:
            Suite = "Clubs";
            break;
        }
        aShoe.add(Suite + Convert.ToString(cardFace));
 }

 }

 Random cardPicker = new Random(); //This is change

 private void newCard(int x)
    {
        int cardChoice = 0;
        int houseChoice = 0;
    string cardDrawn = "";

    int cardToDraow = cardPicker.Next(0,aShoe.length);

    cardDrawn = card aShoe[cardToDraow];
    card.removeAt(cardToDraow);

        if (x == 0)
        {
            makeCard(cardDrawn, 0);
            myVars.playerCardValue += cardChoice;
        }
        if (x == 1)
        {
            makeCard(cardDrawn, 1);
            myVars.cpuCardValue += cardChoice;
        }
    }

如果你是按照单牌规则玩,你必须使用随机值源的“包”或“不替换”模型。最初,用所有52张可能的卡片填满袋子。然后每次迭代,从袋子里剩下的东西中随机挑选一张卡片,从袋子里取出。当袋子空了,再装满它

请注意,当从有n个剩余物品的袋子中随机挑选卡片时,您的随机值(作为袋子中物品的索引)不得大于n-1(假设标记从0到n-1)

然而,也有21点游戏的模型,其中多个牌组被混合在一起;许多赌场都是这样玩的。来自维基百科:

在赌场21点赌桌上,庄家从半圆形赌桌后面面对五到七个牌位。在一到八张标准的52张牌组之间被洗牌在一起

在上述模型中,同一张牌肯定有可能连续发两次;然而,根据混合在一起的牌的数量,这种情况只能发生有限的次数


如果我正确理解了您的代码,您目前正在模拟一个21点游戏鞋,它有无限多个牌组混在一起。

一张牌应该是一个具有套装和价值属性的单一对象,其中一副牌应该混在一起,而不是随机挑选的牌和套装/价值分开!您不断创建新的随机实例。不要那样做。每个类甚至每个线程只创建一个。请参阅-另外,您不应该随机生成一张卡,而应该创建一个完整的卡组ICCollection,并从卡组中随机选择和移除一张卡。您需要跟踪使用过的卡,以便您的新卡方法可以从未使用的卡中选择卡,而不是从所有卡中选择卡。其可能的重复问题不是随机数是如何生成的。即使将随机数移动到全局范围,问题仍会偶尔持续,因为没有任何东西可以阻止随机数连续两次生成相同的数字。这只是问题的一小部分。最重要的是要控制选择的任何值都不超过4张/每副牌中每根鞋杆有一张牌。他说这个方法很快被调用了两次。在方法内部,他创建了一个新的随机变量。如果未提供种子,则从时间开始生成种子。现在,两个方法调用很快就会产生两个几乎相同的种子,因此会生成两个相同的数字。使用一个随机实例不会阻止同一张卡被分发两次。谢谢!!!现在,我正在将随机数传递到该方法中,它正在按预期工作,对于其他指出我需要一种方法来管理哪些卡可以分发或不分发的人,也谢谢!我简直不敢相信,我现在忙得不可开交,所以我是一只快乐的兔子:这不会有帮助:你不能不受限制地反复挑选一个随机数,让它模仿一副牌cards@Plutonix,谢谢你的接球。我已编辑我的答案。正在检查卡片是否已读取
如果你这样抽牌,每抽一张牌,你的表现就会越来越差。这里可能不明显,但在实际应用程序中,它可能会极大地影响性能。使用队列,或者至少在您抽牌时手动从列表中删除卡片,将是一种方法。@JoeEnos,您是对的。我们应该创建一个卡片列表,然后从中取出卡片。@JoeEnos,我的逻辑正确,请勾选。
 List<string> aShoe = new List<string>(); //shoe contains 4 to 8 decks. Depending upon blackjack version.
 int numberOfDeckPerShoe = 4;

private void CreateNewDeck()
 {
     for(int i =0;i <numberOfDeckPerShoe;i++)
 for(int j=0;j<52;j++)
 {
            int cardFace = (j%13)+1;
        int cardSuite = (j/13) + 1;

        string Suite = null;

        switch (cardSuite)
        {
        case 1:
            Suite = "Hearts";
            break;
        case 2:
            Suite = "Diamonds";
            break;
        case 3:
            Suite = "Spades";
            break;
        case 4:
            Suite = "Clubs";
            break;
        }
        aShoe.add(Suite + Convert.ToString(cardFace));
 }

 }

 Random cardPicker = new Random(); //This is change

 private void newCard(int x)
    {
        int cardChoice = 0;
        int houseChoice = 0;
    string cardDrawn = "";

    int cardToDraow = cardPicker.Next(0,aShoe.length);

    cardDrawn = card aShoe[cardToDraow];
    card.removeAt(cardToDraow);

        if (x == 0)
        {
            makeCard(cardDrawn, 0);
            myVars.playerCardValue += cardChoice;
        }
        if (x == 1)
        {
            makeCard(cardDrawn, 1);
            myVars.cpuCardValue += cardChoice;
        }
    }