我有一个java二十一点应用程序。如何使它成为服务器客户端?

时间:2014-11-30 15:44:05

标签: java multithreading swing class client-server

我有一个非常简单的二十一点应用程序,但我必须使它成为客户端 - 服务器,我不知道如何。我会非常感激任何帮助。

所以,这是主要的类游戏

package game;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Game extends JFrame implements ActionListener {

    private Deck deck;
    public Player player = new Player("player");
    public Player dealer = new Player("dealer");

    int dealerCount = 0;
    int playerCount = 0;

    private JButton jbtnHit = new JButton("Hit");
    private JButton jbtnStay = new JButton("Stay");
    private JButton jbtnDeal = new JButton("Deal");

    private JLabel jlblStatus = new JLabel(" ", JLabel.CENTER);
    private JLabel jlblDealerCount = new JLabel(" ", JLabel.CENTER);
    private JLabel jlblPlayerCount = new JLabel(" ", JLabel.CENTER);

    JPanel playerPanel = new JPanel();
    JPanel dealerPanel = new JPanel();
    JPanel buttonsPanel = new JPanel();
    JPanel statusPanel = new JPanel();
    JPanel countPanel = new JPanel();

    Game() {
        JFrame gameFrame = new JFrame("BlackJack");
        gameFrame.setIconImage(Toolkit.getDefaultToolkit().getImage("cards/10.png"));
        gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        buttonsPanel.add(jbtnHit);
        buttonsPanel.add(jbtnStay);
        buttonsPanel.add(jbtnDeal);
        statusPanel.add(jlblStatus);
        countPanel.add(jlblDealerCount);
        countPanel.add(jlblPlayerCount);

        jbtnHit.addActionListener(this);
        jbtnStay.addActionListener(this);
        jbtnDeal.addActionListener(this);

        jbtnHit.setEnabled(false);
        jbtnStay.setEnabled(false);

        dealerPanel.setBackground(Color.GREEN);
        playerPanel.setBackground(Color.GREEN);
        buttonsPanel.setBackground(Color.GREEN);
        statusPanel.setBackground(Color.GREEN);
        countPanel.setBackground(Color.GREEN);

        gameFrame.setLayout(new BorderLayout());
        gameFrame.add(dealerPanel, BorderLayout.NORTH);
        gameFrame.add(playerPanel, BorderLayout.CENTER);
        gameFrame.add(buttonsPanel, BorderLayout.SOUTH);
        gameFrame.add(statusPanel, BorderLayout.WEST);
        gameFrame.add(countPanel, BorderLayout.EAST);
        gameFrame.repaint();
        gameFrame.setSize(500, 350);
        gameFrame.setVisible(true);
    }

    private void hitPlayer() {
        Card newCard = player.dealTo(deck.dealFrom());
        playerPanel.add(new JLabel(new ImageIcon("cards/" + newCard.toString())));
        playerPanel.updateUI();
    }

    private void hitDealerDown() {
        Card newCard = dealer.dealTo(deck.dealFrom());
        dealerPanel.add(new JLabel(new ImageIcon("cards/b2fv.png")));
        dealerPanel.updateUI();
    }

    private void hitDealer() {
        Card newCard = dealer.dealTo(deck.dealFrom());
        dealerPanel.add(new JLabel(new ImageIcon("cards/" + newCard.toString())));
        dealerPanel.updateUI();
    }

    private void deal() {
        playerPanel.removeAll();
        dealerPanel.removeAll();
        playerPanel.updateUI();
        dealerPanel.updateUI();
        player.reset();
        dealer.reset();
        if (deck == null || deck.size() < 15) {
            deck = new Deck();
            deck.shuffle();
            jlblStatus.setText("Shuffling");
        }
        hitPlayer();
        hitDealerDown();
        hitPlayer();
        hitDealer();
    }

    private void checkWinner() {
        dealerPanel.removeAll();

        for (int i = 0; i < dealer.inHand(); i++) {
            dealerPanel.add(new JLabel(new ImageIcon("cards/" + dealer.cards[i].toString())));
        }
        if (player.value() > 21) {
            jlblStatus.setText("Player Busts");
            dealerCount++;
        } else if (dealer.value() > 21) {
            jlblStatus.setText("Dealer Busts");
            playerCount++;
        } else if (dealer.value() == player.value()) {
            jlblStatus.setText("Push");
        } else if (dealer.value() < player.value()) {
            jlblStatus.setText("Player Wins");
            playerCount++;
        } else {
            jlblStatus.setText("Dealer Wins");
            dealerCount++;
        }
        jlblDealerCount.setText(dealerCount+" :");
        jlblPlayerCount.setText(""+playerCount);
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == jbtnHit) {
            hitPlayer();
            if (player.value() > 21) {
                checkWinner();
                jbtnHit.setEnabled(false);
                jbtnStay.setEnabled(false);
                jbtnDeal.setEnabled(true);
            }
        }

        if (e.getSource() == jbtnStay) {
            while (dealer.value() < 17 || player.value() > dealer.value()) {
                hitDealer();
            }
            checkWinner();
            jbtnHit.setEnabled(false);
            jbtnStay.setEnabled(false);
            jbtnDeal.setEnabled(true);
        }

        if (e.getSource() == jbtnDeal) {
            deal();
            jlblStatus.setText(" ");
            jbtnHit.setEnabled(true);
            jbtnStay.setEnabled(true);
            jbtnDeal.setEnabled(false);
        }
    }

    public static void main(String[] args) {
        new Game();
    }
}

这是类卡

package game;

 class Card {

    private int cardNumber;
    private int rank;
    private String front;

    Card(int cardNumber, int rank, String front) {
        this.cardNumber = cardNumber;
        this.rank = rank;
        this.front = front;
    }

    public boolean isAce() {
        return rank == 0;
    }

    public int rank() {
        if (rank == 0) {
            return 1;
        }
        if (rank >= 9) {
            return 10;
        }
        return rank + 1;
    }

    public String toString() {
        return this.front;
    }
}

这是类Deck

package game;

public class Deck {

    final static int DECK_SIZE = 52;
    private Card[] cards;
    private int N = 0;

    public Deck() {
        cards = new Card[DECK_SIZE];
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 13; j++) {
                cards[N] = new Card(N, j, i + "" + j + ".png");
                N++;
            }
        }
    }

    public Card dealFrom() {
        return cards[--N];
    }

    public boolean isEmpty() {
        return (N == 0);
    }

    public int size() {
        return N;
    }

    public void shuffle() {
        for (int i = 0; i < N; i++) {
            int r = (int) (Math.random() * i);
            Card swap = cards[i];
            cards[i] = cards[r];
            cards[r] = swap;
        }
    }
}

这是类播放器

package game;

public class Player {

    final static int MAX_CARDS = 52;
    public Card[] cards = new Card[MAX_CARDS];
    private int N = 0;
    private String name;

    public Player(String name) {
        this.name = name;
    }

    public int inHand() {
        return N;
    }

    public Card dealTo(Card c) {
        cards[N++] = c;
        return c;
    }

    public void reset() {
        N = 0;
    }

    public int value() {
        int val = 0;
        boolean hasAce = false;
        for (int i = 0; i < N; i++) {
            val = val + cards[i].rank();
            if (cards[i].isAce()) {
                hasAce = true;
            }
        }
        if (hasAce && (val <= 11)) {
            val = val + 10;
        }
        return val;
    }
}

我需要有关如何进行此游戏客户端 - 服务器和多线程的任何信息和示例。 这应该是使用套接字的网络应用程序。

2 个答案:

答案 0 :(得分:1)

当您编写联网应用程序时,您必须首先确定游戏用户之间共享的数据。对于二十一点,要分享的数据(AKA是“游戏状态”)非常简单:

  1. 轮到它的玩家
  2. 仍然在牌组中的牌
  3. 每位玩家在牌桌上的牌
  4. 每个玩家有多少钱
  5. 一旦计划好所有这些,您就可以创建表示游戏状态的对象。例如:

    public class GameState {
        public enum Suit { HEARTS, DIAMONDS, CLUBS, SPADES }
        public enum Rank { ONE, TWO, THREE, FOUR, FIVE, SIX ... ACE }
        public static class Card {
           Suit suit;
           Rank rank;
        }
        public static class Deck {
           List<Card> cards; // Cards remaining in the deck
        }
        public static class Player {
           // Cards on the table for a player
           List<Card> cards;
           Integer id;
           Double money;
        }
        HashMap<Integer, Player> players;
        Integer activePlayerId;
    }
    

    接下来,我们需要一种机制来在所有玩家之间同步这种状态。对于像二十一点这样的游戏来说,这样做的一种方法是在每个玩家回合后同步整个状态。也就是说,在每个回合结束时,通过网络将整个游戏状态发送给所有玩家。要发送游戏状态,最简单的方法是让中央服务器进程保留最新状态的副本。中央服务器定期向玩家发送游戏状态,以使其保持同步。

    现在,我们需要一个客户端可以用来与服务器通信的协议。在游戏开始时,客户端连接,然后等待服务器启动游戏。之后,客户端和服务器以锁定的方式进行通信,几乎就像他们正在进行对话一样。这是一个例子:

    Client 1: Connect 
    Server: OK 
    Client 2: Connect 
    Server: OK 
    Server: Start game 
    Server: Sync <send the initial game state> 
    Server: Place bids
    Client 1: Bid 50
    Client 2: Bid 100
    Server: Client 1's turn
    Client 1: Stay
    Server: Sync <send new game state>
    Server: Client 2's turn
    Client 2: Hit 
    Server: Sync <send new game state> 
    ...
    

    等。直到比赛结束。要在客户端和服务器之间发送数据和协议对话,您可以使用套接字。我不会在这里介绍,因为在Interwebs上有很多关于使用套接字的教程,like this one.

    祝你好运,玩得开心!

答案 1 :(得分:0)

您需要将实现分成至少三层:ui层,服务层和数据层。客户端处理ui层,服务请求,服务器应答请求,并与db通信。

您可以将服务器托管在容器或云中,例如GAE。

客户端通常会通过HTTP通过get或post进行通信。

相关问题