为BlackJack创建AI

我正在尝试制作一个BlackJack游戏!我已经成功实现了玩家互动!然而,我决定提升难度,加入一些AI,这样我就可以与AI对战,进行一场真正的较量,可以这么说。

我的主要问题是,我已经坐在这儿思考了大约一个小时左右,考虑AI是如何工作的,以及我如何能使用它,但我还没有想出任何可行的方法。所以我想问问大家是否有任何建议,或者能指导我一个方向。

我还没有任何关于AI的代码,因为我不知道如何开始或如何操作AI。这就是为什么我希望能得到一些指导。

现在我将发布我认为所有相关的类。我没有包含Game类。Game类只是用于验证和检查卡牌以及所有那些神奇的东西。

Card类:

public class Card{private int rank, suit;private String[] suitNames = new String[]{ "H", "C", "S", "D" };private String[] rankNumber = new String[]{ "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" };private int[] points = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10};Card(int suitIndex, int rankIndex){    rank = rankIndex;    suit = suitIndex;}public @Override String toString(){    return rankNumber[rank]+suitNames[suit]; }public int getRank(){    return rank;}public int getSuit(){    return suit;}public String getSuitName(){    return suitNames[suit];}public String getRankName(){    return rankNumber[rank];}public int getPoints(){     return points[rank];}public ImageIcon ImageOfCard() throws Exception{    ImageIcon icon = new ImageIcon("/StandardDeck/GameCards/"+getRankName() + getSuitName()+".png");    return icon;}}

BlackJack类(包含所有功能的游戏类)是的,我确实使用了Java GUI来开发它。

public class BlackJack extends JFrame {Game game;Deck deck;Card cards;Player player;Dealer dealer;JLabel[] playerCardSlots;JLabel[] dealerCardSlots;public BlackJack() {    String name = JOptionPane.showInputDialog(null, "Enter your name");    deck = new Deck(4);    game = new Game();    player = new Player(name);    dealer = new Dealer(deck);    initComponents();    SetButtons(false);    playerCardSlots = new JLabel[]{Player1Card1, Player1Card2, Player1Card3, Player1Card4, Player1Card5};    dealerCardSlots = new JLabel[]{DealerCard1, DealerCard2, DealerCard3, DealerCard4, DealerCard5};}@SuppressWarnings("unchecked")// <editor-fold defaultstate="collapsed" desc="Generated Code">                          private void initComponents() {    Player1Card1 = new javax.swing.JLabel();    Player1Card2 = new javax.swing.JLabel();    Player1Card3 = new javax.swing.JLabel();    Player1Card4 = new javax.swing.JLabel();    Player1Card5 = new javax.swing.JLabel();    Player1Name = new javax.swing.JLabel();    HitButton = new javax.swing.JButton();    StandButton = new javax.swing.JButton();    PointsLabel = new javax.swing.JLabel();    DealButton = new javax.swing.JButton();    DealerCard1 = new javax.swing.JLabel();    DealerCard2 = new javax.swing.JLabel();    DealerCard3 = new javax.swing.JLabel();    DealerCard4 = new javax.swing.JLabel();    DealerCard5 = new javax.swing.JLabel();    DealerPointsLabel = new javax.swing.JLabel();    DealerLabel = new javax.swing.JLabel();    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);    Player1Name.setText("Player 1 Name");    HitButton.setText("Hit");    HitButton.addActionListener(new java.awt.event.ActionListener() {        public void actionPerformed(java.awt.event.ActionEvent evt) {            HitButtonActionPerformed(evt);        }    });    StandButton.setText("Stand");    StandButton.addActionListener(new java.awt.event.ActionListener() {        public void actionPerformed(java.awt.event.ActionEvent evt) {            StandButtonActionPerformed(evt);        }    });    PointsLabel.setText("points");    DealButton.setText("Deal");    DealButton.addActionListener(new java.awt.event.ActionListener() {        public void actionPerformed(java.awt.event.ActionEvent evt) {            DealButtonActionPerformed(evt);        }    });    DealerPointsLabel.setText("points");    DealerLabel.setText("Dealer");    org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());    getContentPane().setLayout(layout);    layout.setHorizontalGroup(        layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)        .add(layout.createSequentialGroup()            .add(54, 54, 54)            .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)                .add(layout.createSequentialGroup()                    .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)                        .add(layout.createSequentialGroup()                            .add(76, 76, 76)                            .add(Player1Name)                            .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))                        .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()                            .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 104, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)                            .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)                                .add(DealerPointsLabel)                                .add(PointsLabel))                            .add(128, 128, 128)))                    .add(DealButton))                .add(layout.createSequentialGroup()                    .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)                        .add(org.jdesktop.layout.GroupLayout.LEADING, layout.createSequentialGroup()                            .add(Player1Card1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 40, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)                            .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)                            .add(Player1Card2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 40, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)                            .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)                            .add(Player1Card3, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 40, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)                            .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)                            .add(Player1Card4, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 40, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)                            .add(12, 12, 12)                            .add(Player1Card5, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 40, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))                        .add(org.jdesktop.layout.GroupLayout.LEADING, layout.createSequentialGroup()                            .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)                                .add(DealerLabel)                                .add(layout.createSequentialGroup()                                    .add(DealerCard1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 40, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)                                    .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)                                    .add(DealerCard2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 40, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)                                    .add(12, 12, 12)                                    .add(DealerCard3, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 40, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))                            .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)                            .add(DealerCard4, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 40, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)                            .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)                            .add(DealerCard5, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 40, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))                    .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)                    .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)                        .add(HitButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)                        .add(StandButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 75, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))))            .addContainerGap())    );    layout.setVerticalGroup(        layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)        .add(layout.createSequentialGroup()            .add(13, 13, 13)            .add(DealerLabel)            .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)            .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)                .add(HitButton)                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)                    .add(DealerCard1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 60, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)                    .add(DealerCard2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 60, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)                    .add(DealerCard3, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 60, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)                    .add(DealerCard4, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 60, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)                    .add(DealerCard5, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 60, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))            .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)            .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)                .add(StandButton)                .add(DealerPointsLabel))            .add(4, 4, 4)            .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)                .add(PointsLabel)                .add(DealButton))            .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)            .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)                .add(Player1Card1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 60, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)                .add(Player1Card2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 60, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)                .add(Player1Card3, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 60, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)                .add(Player1Card4, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 60, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)                .add(Player1Card5, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 60, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))            .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)            .add(Player1Name)            .addContainerGap(29, Short.MAX_VALUE))    );    pack();}// </editor-fold>                        private void HitButtonActionPerformed(java.awt.event.ActionEvent evt) {                                              PlayerHit();}                                         private void StandButtonActionPerformed(java.awt.event.ActionEvent evt) {                                                PlayerStand();}                                           private void DealButtonActionPerformed(java.awt.event.ActionEvent evt) {                                               ResetGame();}                                          public void SetName(){    Player1Name.setText(player.getName());}public void DealCards(){    player.AddCard(deck.DrawCard());    dealer.AddCard(deck.DrawCard());    player.AddCard(deck.DrawCard());    dealer.AddCard(deck.DrawCard());    ShowCards(player, player.CountCards());    ShowCards(dealer, 1);    SetButtons(true);}public void DealerHit(){    dealer.AddCard(deck.DrawCard());}public void DealerStand(){    dealer.PlayerStand();}public void PlayerHit(){    player.AddCard(deck.DrawCard());    ShowCards(player, player.CountCards());}public void PlayerStand(){    player.PlayerStand();    SetButtons(false);    dealer.PlayerTurn();}public void ShowCards(Player person, int cards){    if(!person.getName().equals("Dealer")){        for(int i = 0; i < cards; i++){            playerCardSlots[i].setText(person.getCard(i).toString());        }        int points = game.CardTotal(person);        if(game.PlayerBust(points)){            PointsLabel.setText("BUST!");            SetButtons(false);        }        else{            PointsLabel.setText(points+"");        }        if(game.CardDraw(person)){            PointsLabel.setText("5 Card Draw!");            SetButtons(false);        }    }    else{        for(int i = 0; i < cards; i++){            dealerCardSlots[i].setText(person.getCard(i).toString());        }        int points = game.CardTotal(person, cards);        if(game.PlayerBust(points)){            DealerPointsLabel.setText("BUST!");            SetButtons(false);        }        else{            DealerPointsLabel.setText(points+"");        }        if(game.CardDraw(person)){            DealerPointsLabel.setText("5 Card Draw!");            SetButtons(false);        }        if(points >= 17){        }    }}public void SetButtons(boolean enabled){        HitButton.setEnabled(enabled);        StandButton.setEnabled(enabled);}public void ResetGame(){    for(JLabel label : playerCardSlots){        label.setText("");    }    for(JLabel label : dealerCardSlots){        label.setText("");    }    player.ClearCards();    dealer.ClearCards();    deck = new Deck(4);    DealCards();    SetName();    player.PlayerTurn();    dealer.PlayerStand();}// <editor-fold defaultstate="collapsed" desc="Variables">// Variables declaration - do not modify                     private javax.swing.JButton DealButton;private javax.swing.JLabel DealerCard1;private javax.swing.JLabel DealerCard2;private javax.swing.JLabel DealerCard3;private javax.swing.JLabel DealerCard4;private javax.swing.JLabel DealerCard5;private javax.swing.JLabel DealerLabel;private javax.swing.JLabel DealerPointsLabel;private javax.swing.JButton HitButton;private javax.swing.JLabel Player1Card1;private javax.swing.JLabel Player1Card2;private javax.swing.JLabel Player1Card3;private javax.swing.JLabel Player1Card4;private javax.swing.JLabel Player1Card5;private javax.swing.JLabel Player1Name;private javax.swing.JLabel PointsLabel;private javax.swing.JButton StandButton;// End of variables declaration                   //</editor-fold>}

Player类:

 public class Player{ private String playerName; private ArrayList<Card> playerCards = new ArrayList<Card>(); private boolean turn = false;Player(String name){    playerName = name;}public Card getCard(int index){    return playerCards.get(index);}public void AddCard(Card card){    playerCards.add(card);}public void ClearCards(){    playerCards.clear();}public int CountCards(){    return playerCards.size();}public String getName(){    return playerName;}public void PlayerStand(){    turn = false;}public void PlayerTurn(){    turn = true;}public boolean getTurn(){    return turn;}}

回答:

首先:从极客的角度来看,Blackjack确实很有趣。

正如有人评论的那样:银行使用固定的算法来执行所有操作。这些操作(通常?还是总是?你自己去发现。)仅依赖于银行的牌。首先实现这个。

对于玩家,你绝对应该实现Blackjack玩家所说的“基本策略”。我猜谷歌搜索会给你很多结果。

现在这是我会研究的内容
在实现了银行的固定策略和玩家的“基本策略”后,你可以开始进行蒙特卡洛模拟来找出游戏的期望值。尽量让MC模拟代码尽可能快,因为你可能想进行大量的MC模拟。

现在尝试稍微修改一下牌组。例如,尝试从牌组中移除所有的5。然后进行相同的MC模拟,看看这是否会改变期望值。你想玩没有5的BJ吗?

现在,再次修改牌组。尝试移除牌组中一半的10(即所有值为10的牌的一半)。这如何改变玩家的期望值?

现在再次修改牌组。尝试移除一半的非10值的牌。这如何影响期望值?

继续稍微修改牌组,尝试理解剩余牌分布中的微小偏差如何影响期望值。你应该利用这种理解来调整游戏的赌注。因此,策略不是要不要要牌/停止要牌的行动,而是基于鞋中剩余牌的分布偏差进行的资金管理。继续基于“基本策略”做出要牌/停止要牌的决定!

进一步的步骤:
也许你可以训练一个神经网络(或其他一些估计算法)来根据牌组中已知的剩余牌估计游戏的期望值?(你必须跟踪鞋中剩余的牌。)也许你甚至可以将MC模拟工具连接到训练算法中,为你提供一种强化学习算法。这实际上开始听起来像真正的极客乐趣!或者你可以让MC模拟器运行得足够快,以便即时得到期望值的良好答案。

更进一步的步骤:
当你找到一种好的方法来估计游戏的期望值,基于鞋中剩余的牌(和“基本策略”),并且速度足够快时,你可能能够为资金管理实现一个强化学习算法。

…或者你可以坚持简单的计划:正期望值 => 高赌注。负期望值 => 低赌注。

祝你研究顺利,
-Øystein

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注