为BlackJack创建AI

时间:2012-10-17 18:35:24

标签: java artificial-intelligence blackjack

我正在尝试制作二十一点游戏!我成功与玩家互动!但是,我决定加强它并做一些AI,这样我就可以对抗AI,并且可以说更多的战斗。

我的主要问题是,我已经在这里待了大约一个小时左右,想着人工智能是如何工作的以及我如何使用它,而我却无法想到任何可行的方法。所以我想知道是否有人有任何想法,或者能指导我朝着这个方向发展。

我没有启动AI的任何代码,因为我无法想到如何启动或使用一个。这就是为什么我希望有某种方向。

现在我将发布我认为完全相关的课程。我确实遗漏了Game类。游戏类仅用于验证和检查卡片以及所有令人惊奇的东西。

班级卡:

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>
}

班主任:

 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;
}

}

4 个答案:

答案 0 :(得分:4)

首先:从极客的角度来看,二十一点确实很有趣。

正如有人评论的那样:银行对其所有行为使用固定算法。这些行为(通常是?或总是?找出你的自己。)只取决于银行手。首先实施。

对于玩家,您应该明确地实施二十一点玩家所谓的“基本策略”。我想谷歌搜索会给你很多点击量。

现在我要研究的是
实施银行固定策略和玩家“基本策略”后,您可以开始进行蒙特卡罗模拟以找到游戏的期望。尝试尽可能快地获取MC仿真代码,因为您可能想要进行大量的MC仿真。

现在尝试略微修改套牌。例如,尝试从甲板上移除所有5个。然后进行相同的MC模拟,看看这是否会改变预期。你想在没有5s的甲板上玩BJ吗?

现在,再次修改套牌。尝试删除套牌中所有10个中的一半(这是所有卡的一半,值为10)。这如何改变球员的期望?

现在再次修改套牌。尝试删除一半的非10值卡。这对预期有何影响?

继续对甲板进行一点修改,并尝试了解剩余卡分布中的小偏差如何影响预期。您应该使用这种理解来调整游戏的赌注。因此,策略不是热门/站立行动,而是基于鞋子剩余套牌中的分配偏差的资金管理。根据“基本策略”保持打击/站立决策!

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

更进一步的步骤:
当你找到一个很好的方法来估计游戏的期望时,考虑到鞋中剩余的牌(和“基本”策略“),这足够快,你可以实现一个强化学习算法来实现资金管理

......或者你可以坚持简单的计划:积极的期望=&gt;高赌注。否定期望=&gt;低赌注。

祝你学习顺利,
-Øystein

答案 1 :(得分:0)

您需要创建一个启发式函数,对A.I.的所有可能移动进行评分。玩家可以。此启发式函数接收玩家可访问的所有可用数据,分数越高,移动越好。它应该考虑获得所需特定卡的概率,与经销商破坏等的概率。然后A.I.应该只选择最佳移动,即具有最大启发式分数的移动。

答案 2 :(得分:0)

有一些二十一点系统(获胜约49%)。例如:http://www.docstoc.com/docs/79054261/Basic-Strategy-Chart---Easy-Money-Blackjack-System

如果{cards}然后{action} algorithm

,这很简单

答案 3 :(得分:0)

一般来说,你不应该(主要)依赖命令式语言来创建你的二十一点玩家,除非你只是把搜索作为主要(可能是唯一的)策略。相反,请查看Clips(生产规则)或Drools,以便快速创建原型。那里有一个初步的学习曲线。基本上,生产规则,逻辑编程,神经网络和遗传算法是将搜索结合在执行或学习阶段的通用方法。那么为什么要使用这些只是搜索?毕竟搜索算法非常强大。因为生产规则,逻辑编程,神经网络和遗传算法比仅应用搜索算法更强大,并使您能够专注于您的问题表示。

另一件需要考虑的事情是,在二十一点你也想要合并概率(也许是卡片计数!)。