3

我正在尝试制作二十一点游戏!我在玩家互动方面很成功!然而,我决定加强它,做一些人工智能,这样我就可以和人工智能对战,可以说有更多的战斗。

不过,我的主要问题是,我已经在这里坐了大约一个小时左右,思考人工智能是如何工作的以及我如何使用它,但我一直无法想到任何可行的方法。所以我想知道是否有人有任何想法,或者能够指导我一个方向。

我没有任何启动 AI 的代码,因为我想不出如何启动或使用它。这就是为什么我希望有某种方向。

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

班级卡:

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

4 回答 4

4

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

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

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

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

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

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

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

继续稍微修改套牌,并尝试了解剩余卡片分布中的小偏差如何影响预期。您应该使用这种理解来调整游戏的赌注。因此,该策略不是击中/站立动作,而是基于鞋子中剩余牌组的分配偏差的资金管理。继续根据“基本策略”做出决定!

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

更进一步:
当你找到了一个很好的方法来估计游戏的期望时,给定鞋柜中的剩余牌(和“基本“策略”),它足够快,你也许可以实现强化学习算法用于资金管理。

... 或者您可以坚持简单的计划:积极预期 => 高风险。负面预期 => 低风险。

祝你学习顺利,
-Øystein

于 2012-10-18T11:25:16.900 回答
0

您将需要创建一个启发式函数,对 AI 玩家可以做出的所有可能动作进行评分。这个启发式函数会获取玩家可以访问的所有可用数据,分数越高,移动越好。它应该考虑获得所需特定牌的概率,与庄家爆牌等。然后人工智能应该简单地选择最好的移动,即具有最大启发式分数的移动。

于 2012-10-17T18:40:55.597 回答
0

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

所以这很简单 if {cards} then {action} 算法

于 2012-10-17T18:47:48.123 回答
0

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

另一件要考虑的事情是,在二十一点中,您还需要加入概率(也许还有算牌!)。

于 2012-10-19T10:47:22.593 回答