希望能够改变Java的职业/专业。我已经阅读了无数次
,如果您想学习一种新语言,则需要编写代码,然后再编写更多的代码,最后编写更多的代码。所以我写了一些代码!
我喜欢扑克,所以我写了一个小的Texas Hold'em程序。以下是其功能概述:
向用户询问玩家人数
创建牌组
随机播放
切牌
玩家处理卡洞
烧卡
转牌
烧卡
转身
烧卡
河卡
>将纸牌打印到控制台以显示使用了随机纸牌
打印“棋盘”
打印烧录卡
打印机玩家卡
评估每个玩家的手牌值(皇家同花顺,满屋等等。)
有6个.java文件(请参阅下面的链接)。我使用了一个接口,创建了自己的比较器,甚至实现了一些try / catch块(尽管我仍在学习如何正确使用它们)。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class TexasHoldEm {
public static void main(String[] args) throws Exception {
// variables
Deck holdemDeck = new Deck();
int numPlayers = 0;
int cardCounter = 0;
int burnCounter = 0;
int boardCounter = 0;
Board board = new Board();
// initializations
numPlayers = getNumberOfPlayers();
Player[] player = new Player[numPlayers];
/* 3 shuffles just like in real life. */
for(int i=0;i<3;i++){
holdemDeck.shuffle();
}
// Cut Deck
holdemDeck.cutDeck();
// Initialize players
for (int i=0;i<numPlayers;i++){
player[i] = new Player();
}
// Main processing
// Deal hole cards to players
for (int i=0;i<2;i++){
for (int j=0;j<numPlayers;j++){
player[j].setCard(holdemDeck.getCard(cardCounter++), i);
}
}
// Start dealing board
// Burn one card before flop
board.setBurnCard(holdemDeck.getCard(cardCounter++), burnCounter++);
// deal flop
for (int i=0; i<3;i++){
board.setBoardCard(holdemDeck.getCard(cardCounter++), boardCounter++);
}
// Burn one card before turn
board.setBurnCard(holdemDeck.getCard(cardCounter++), burnCounter++);
// deal turn
board.setBoardCard(holdemDeck.getCard(cardCounter++), boardCounter++);
// Burn one card before river
board.setBurnCard(holdemDeck.getCard(cardCounter++), burnCounter++);
// deal river
board.setBoardCard(holdemDeck.getCard(cardCounter++), boardCounter++);
//------------------------
// end dealing board
//------------------------
System.out.println("The hand is complete...\n");
// print deck
holdemDeck.printDeck();
//print board
board.printBoard();
// print player cards
System.out.println("The player cards are the following:\n");
for (int i=0;i<numPlayers;i++){
player[i].printPlayerCards(i);
}
// print burn cards
board.printBurnCards();
//------------------------
// Begin hand comparison
//------------------------
for (int i=0;i<numPlayers;i++){
HandEval handToEval = new HandEval();
// populate with player cards
for (int j=0;j<player[i].holeCardsSize();j++){
handToEval.addCard(player[i].getCard(j),j);
}
//populate with board cards
for (int j=player[i].holeCardsSize();j<(player[i].holeCardsSize()+board.boardSize());j++){
handToEval.addCard(board.getBoardCard(j-player[i].holeCardsSize()),j);
}
System.out.println("Player " + (i+1) + " hand value: " + handToEval.evaluateHand());
}
}
protected static int getNumberOfPlayers() throws Exception{
int intPlayers = 0;
String userInput = "";
// Get number of players from user.
System.out.println("Enter number of players (1-9):");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
userInput = br.readLine();
} catch (IOException ioe) {
System.out.println("Error: IO error trying to read input!");
System.exit(1);
}
// convert user input to an integer
try {
intPlayers = Integer.parseInt(userInput);
} catch (NumberFormatException nfe) {
System.out.println("Error: Input provided is not a valid Integer!");
System.exit(1);
}
if ((intPlayers<1) || (intPlayers>9)){
throw new Exception("Error: Number of players must be an integer between 1 and 9");
}
return intPlayers;
}
}
播放器。 java
public class Player {
private Card[] holeCards = new Card[2];
//constructor
public Player(){
}
public Player(Card card1, Card card2){
holeCards[0] = card1;
holeCards[1] = card2;
}
//methods
protected void setCard(Card card, int cardNum){
holeCards[cardNum] = card;
}
protected Card getCard(int cardNum){
return holeCards[cardNum];
}
protected int holeCardsSize(){
return holeCards.length;
}
protected void printPlayerCards(int playerNumber){
System.out.println("Player " + (playerNumber+1) + " hole cards:");
for (int i=0;i<2;i++){
System.out.println(holeCards[i].printCard());
}
System.out.println("\n");
}
}
HandEval.java
import java.util.Arrays;
public class HandEval {
private Card[] availableCards = new Card[7];
private final static short ONE = 1;
private final static short TWO = 2;
private final static short THREE = 3;
private final static short FOUR = 4;
// Constructor
public HandEval(){
}
//methods
protected void addCard(Card card, int i){
availableCards[i] = card;
}
protected Card getCard(int i){
return availableCards[i];
}
protected int numCards(){
return availableCards.length;
}
protected void sortByRank(){
Arrays.sort(availableCards, new rankComparator());
}
protected void sortBySuit(){
Arrays.sort(availableCards, new suitComparator());
}
protected void sortBySuitThenRank(){
Arrays.sort(availableCards, new suitComparator());
Arrays.sort(availableCards, new rankComparator());
}
protected void sortByRankThenSuit(){
Arrays.sort(availableCards, new rankComparator());
Arrays.sort(availableCards, new suitComparator());
}
protected String evaluateHand(){
String handResult = new String();
short[] rankCounter = new short[13];
short[] suitCounter = new short[4];
// initializations
for (int i=0;i<rankCounter.length;i++){
rankCounter[i] =0;
}
for (int i=4;i<suitCounter.length;i++){
suitCounter[i] = 0;
}
// Loop through sorted cards and total ranks
for(int i=0; i<availableCards.length;i++){
rankCounter[ availableCards[i].getRank() ]++;
suitCounter[ availableCards[i].getSuit() ]++;
}
//sort cards for evaluation
this.sortByRankThenSuit();
// hands are already sorted by rank and suit for royal and straight flush checks.
// check for royal flush
handResult = evaluateRoyal(rankCounter, suitCounter);
// check for straight flush
if (handResult == null || handResult.length() == 0){
handResult = evaluateStraightFlush(rankCounter, suitCounter);
}
// check for four of a kind
if (handResult == null || handResult.length() == 0){
handResult = evaluateFourOfAKind(rankCounter);
}
// check for full house
if (handResult == null || handResult.length() == 0){
handResult = evaluateFullHouse(rankCounter);
}
// check for flush
if (handResult == null || handResult.length() == 0){
handResult = evaluateFlush(rankCounter, suitCounter);
}
// check for straight
if (handResult == null || handResult.length() == 0){
// re-sort by rank, up to this point we had sorted by rank and suit
// but a straight is suit independent.
this.sortByRank();
handResult = evaluateStraight(rankCounter);
}
// check for three of a kind
if (handResult == null || handResult.length() == 0){
handResult = evaluateThreeOfAKind(rankCounter);
}
// check for two pair
if (handResult == null || handResult.length() == 0){
handResult = evaluateTwoPair(rankCounter);
}
// check for one pair
if (handResult == null || handResult.length() == 0){
handResult = evaluateOnePair(rankCounter);
}
// check for highCard
if (handResult == null || handResult.length() == 0){
handResult = evaluateHighCard(rankCounter);
}
return handResult;
}
private String evaluateRoyal(short[] rankCounter, short[] suitCounter){
String result = "";
// Check for Royal Flush (10 - Ace of the same suit).
// check if there are 5 of one suit, if not royal is impossible
if ((rankCounter[9] >= 1 && /* 10 */
rankCounter[10] >= 1 && /* Jack */
rankCounter[11] >= 1 && /* Queen */
rankCounter[12] >= 1 && /* King */
rankCounter[0] >= 1) /* Ace */
&& (suitCounter[0] > 4 || suitCounter[1] > 4 ||
suitCounter[2] > 4 || suitCounter[3] > 4)){
// min. requirements for a royal flush have been met,
// now loop through records for an ace and check subsequent cards.
// Loop through the aces first since they are the first card to
// appear in the sorted array of 7 cards.
royalSearch:
for (int i=0;i<3;i++){
// Check if first card is the ace.
// Ace must be in position 0, 1 or 2
if (availableCards[i].getRank() == 0){
// because the ace could be the first card in the array
// but the remaining 4 cards could start at position 1,
// 2 or 3 loop through checking each possibility.
for (int j=1;j<4-i;j++){
if ((availableCards[i+j].getRank() == 9 &&
availableCards[i+j+1].getRank() == 10 &&
availableCards[i+j+2].getRank() == 11 &&
availableCards[i+j+3].getRank() == 12)
&&
(availableCards[i].getSuit() == availableCards[i+j].getSuit() &&
availableCards[i].getSuit() == availableCards[i+j+1].getSuit() &&
availableCards[i].getSuit() == availableCards[i+j+2].getSuit() &&
availableCards[i].getSuit() == availableCards[i+j+3].getSuit())){
// Found royal flush, break and return.
result = "Royal Flush!! Suit: " + Card.suitAsString(availableCards[i].getSuit());
break royalSearch;
}
}
}
}
}
return result;
}
// Straight flush is 5 consecutive cards of the same suit.
private String evaluateStraightFlush(short[] rankCounter, short[] suitCounter){
String result = "";
if (suitCounter[0] > 4 || suitCounter[1] > 4 ||
suitCounter[2] > 4 || suitCounter[3] > 4){
// min. requirements for a straight flush have been met.
// Loop through available cards looking for 5 consecutive cards of the same suit,
// start in reverse to get the highest value straight flush
for (int i=availableCards.length-1;i>3;i--){
if ((availableCards[i].getRank()-ONE == availableCards[i-ONE].getRank() &&
availableCards[i].getRank()-TWO == availableCards[i-TWO].getRank() &&
availableCards[i].getRank()-THREE == availableCards[i-THREE].getRank() &&
availableCards[i].getRank()-FOUR == availableCards[i-FOUR].getRank())
&&
(availableCards[i].getSuit() == availableCards[i-ONE].getSuit() &&
availableCards[i].getSuit() == availableCards[i-TWO].getSuit() &&
availableCards[i].getSuit() == availableCards[i-THREE].getSuit() &&
availableCards[i].getSuit() == availableCards[i-FOUR].getSuit())){
// Found royal flush, break and return.
result = "Straight Flush!! " + Card.rankAsString(availableCards[i].getRank()) + " high of " + Card.suitAsString(availableCards[i].getSuit());
break;
}
}
}
return result;
}
// Four of a kind is 4 cards with the same rank: 2-2-2-2, 3-3-3-3, etc...
private String evaluateFourOfAKind(short[] rankCounter){
String result = "";
for (int i=0;i<rankCounter.length;i++){
if (rankCounter[i] == FOUR){
result = "Four of a Kind, " + Card.rankAsString(i) +"'s";
break;
}
}
return result;
}
// Full house is having 3 of a kind of one rank, and two of a kind of
// a second rank. EX: J-J-J-3-3
private String evaluateFullHouse(short[] rankCounter){
String result = "";
short threeOfKindRank = -1;
short twoOfKindRank = -1;
for (int i=rankCounter.length;i>0;i--){
if ((threeOfKindRank < (short)0) || (twoOfKindRank < (short)0)){
if ((rankCounter[i-ONE]) > 2){
threeOfKindRank = (short) (i-ONE);
}
else if ((rankCounter[i-ONE]) > 1){
twoOfKindRank = (short)(i-ONE);
}
}
else
{
break;
}
}
if ((threeOfKindRank >= (short)0) && (twoOfKindRank >= (short)0)){
result = "Full House: " + Card.rankAsString(threeOfKindRank) + "'s full of " + Card.rankAsString(twoOfKindRank) + "'s";
}
return result;
}
// Flush is 5 cards of the same suit.
private String evaluateFlush(short[] rankCounter, short[] suitCounter){
String result = "";
// verify at least 1 suit has 5 cards or more.
if (suitCounter[0] > 4 || suitCounter[1] > 4 ||
suitCounter[2] > 4 || suitCounter[3] > 4){
for (int i=availableCards.length-1;i>3;i--){
if (availableCards[i].getSuit() == availableCards[i-ONE].getSuit() &&
availableCards[i].getSuit() == availableCards[i-TWO].getSuit() &&
availableCards[i].getSuit() == availableCards[i-THREE].getSuit() &&
availableCards[i].getSuit() == availableCards[i-FOUR].getSuit()){
// Found royal flush, break and return.
result = "Flush!! " + Card.rankAsString(availableCards[i].getRank()) + " high of " + Card.suitAsString(availableCards[i].getSuit());
break;
}
}
}
return result;
}
// Straight is 5 consecutive cards, regardless of suit.
private String evaluateStraight(short[] rankCounter){
String result = "";
// loop through rank array to check for 5 consecutive
// index with a value greater than zero
for (int i=rankCounter.length;i>4;i--){
if ((rankCounter[i-1] > 0) &&
(rankCounter[i-2] > 0) &&
(rankCounter[i-3] > 0) &&
(rankCounter[i-4] > 0) &&
(rankCounter[i-5] > 0)){
result = "Straight " + Card.rankAsString(i-1) + " high";
break;
}
}
return result;
}
// Three of a kind is 3 cards of the same rank.
private String evaluateThreeOfAKind(short[] rankCounter){
String result = "";
// loop through rank array to check for 5 consecutive
// index with a value greater than zero
for (int i=rankCounter.length;i>0;i--){
if (rankCounter[i-1] > 2){
result = "Three of a Kind " + Card.rankAsString(i-1) + "'s";
break;
}
}
return result;
}
// Two pair is having 2 cards of the same rank, and two
// different cards of the same rank. EX: 3-3-7-7-A
private String evaluateTwoPair(short[] rankCounter){
String result = "";
short firstPairRank = -1;
short secondPairRank = -1;
for (int i=rankCounter.length;i>0;i--){
if ((firstPairRank < (short)0) || (secondPairRank < (short)0)){
if (((rankCounter[i-ONE]) > 1) && (firstPairRank < (short)0)){
firstPairRank = (short) (i-ONE);
}
else if ((rankCounter[i-ONE]) > 1){
secondPairRank = (short)(i-ONE);
}
}
else
{
// two pair found, break loop.
break;
}
}
// populate output
if ((firstPairRank >= (short)0) && (secondPairRank >= (short)0)){
if (secondPairRank == (short)0){
// Aces serve as top rank but are at the bottom of the rank array
// swap places so aces show first as highest pair
result = "Two Pair: " + Card.rankAsString(secondPairRank) + "'s and " + Card.rankAsString(firstPairRank) + "'s";
}
else
{
result = "Two Pair: " + Card.rankAsString(firstPairRank) + "'s and " + Card.rankAsString(secondPairRank) + "'s";
}
}
return result;
}
// One is is two cards of the same rank.
private String evaluateOnePair(short[] rankCounter){
String result = "";
for (int i=rankCounter.length;i>0;i--){
if((rankCounter[i-ONE]) > 1){
result = "One Pair: " + Card.rankAsString(i-ONE) + "'s";
break;
}
}
return result;
}
// high card is the highest card out of the 7 possible cards to be used.
private String evaluateHighCard(short[] rankCounter){
String result = "";
for (int i=rankCounter.length;i>0;i--){
if((rankCounter[i-ONE]) > 0){
result = "High Card: " + Card.rankAsString(i-ONE);
break;
}
}
return result;
}
}
Deck.java
import java.util.Random;
public class Deck{
private Card[] cards = new Card[52];
//Constructor
public Deck(){
int i = 0;
for (short j=0; j<4; j++){
for (short k=0; k<13;k++){
cards[i++] = new Card(k, j);
}
}
}
// Print entire deck in order
protected void printDeck(){
for(int i=0; i<cards.length;i++){
System.out.println(i+1 + ": " + cards[i].printCard());
}
System.out.println("\n");
}
// Find card in deck in a linear fashion
// Use this method if deck is shuffled/random
protected int findCard(Card card){
for (int i=0;i<52;i++){
if (Card.sameCard(cards[i], card)){
return i;
}
}
return -1;
}
//return specified card from deck
protected Card getCard(int cardNum){
return cards[cardNum];
}
protected void shuffle(){
int length = cards.length;
Random random = new Random();
//random.nextInt();
for (int i=0;i<length;i++){
int change = i + random.nextInt(length-i);
swapCards(i, change);
}
}
protected void cutDeck(){
Deck tempDeck = new Deck();
Random random = new Random();
int cutNum = random.nextInt(52);
for (int i=0;i<cutNum;i++){
tempDeck.cards[i] = this.cards[52-cutNum+i];
}
for (int j=0;j<52-cutNum;j++){
tempDeck.cards[j+cutNum] = this.cards[j];
}
this.cards = tempDeck.cards;
}
// Swap cards in array to 'shuffle' the deck.
private void swapCards(int i, int change){
Card temp = cards[i];
cards[i] = cards[change];
cards[change] = temp;
}
}
Card.java
import java.util.*;
public class Card{
private short rank, suit;
private static String[] ranks = {"Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"};
private static String[] suits = {"Diamonds", "Clubs", "Hearts", "Spades"};
//Constructor
public Card(short rank, short suit){
this.rank = rank;
this.suit = suit;
}
// Getter and Setters
public short getSuit(){
return suit;
}
public short getRank(){
return rank;
}
protected void setSuit(short suit){
this.suit = suit;
}
protected void setRank(short rank){
this.rank = rank;
}
// methods
public static String rankAsString(int __rank){
return ranks[__rank];
}
public static String suitAsString(int __suit){
return suits[__suit];
}
public @Override String toString(){
return rank + " of " + suit;
}
// Print card to string
protected String printCard(){
return ranks[rank] + " of " + suits[suit];
}
// Determine if two cards are the same (Ace of Diamonds == Ace of Diamonds)
public static boolean sameCard(Card card1, Card card2){
return (card1.rank == card2.rank && card1.suit == card2.suit);
}
}
class rankComparator implements Comparator<Object>{
public int compare(Object card1, Object card2) throws ClassCastException{
// verify two Card objects are passed in
if (!((card1 instanceof Card) && (card2 instanceof Card))){
throw new ClassCastException("A Card object was expeected. Parameter 1 class: " + card1.getClass()
+ " Parameter 2 class: " + card2.getClass());
}
short rank1 = ((Card)card1).getRank();
short rank2 = ((Card)card2).getRank();
return rank1 - rank2;
}
}
class suitComparator implements Comparator<Object>{
public int compare(Object card1, Object card2) throws ClassCastException{
// verify two Card objects are passed in
if (!((card1 instanceof Card) && (card2 instanceof Card))){
throw new ClassCastException("A Card object was expeected. Parameter 1 class: " + card1.getClass()
+ " Parameter 2 class: " + card2.getClass());
}
short suit1 = ((Card)card1).getSuit();
short suit2 = ((Card)card2).getSuit();
return suit1 - suit2;
}
}
Board.java
public class Board {
private Card[] board = new Card[5];
private Card[] burnCards = new Card[3];
//constructor
public Board(){
}
//methods
protected void setBoardCard(Card card, int cardNum){
this.board[cardNum] = card;
}
protected Card getBoardCard(int cardNum){
return this.board[cardNum];
}
protected void setBurnCard(Card card, int cardNum){
this.burnCards[cardNum] = card;
}
protected Card getBurnCard(int cardNum){
return this.burnCards[cardNum];
}
protected int boardSize(){
return board.length;
}
protected void printBoard(){
System.out.println("The board contains the following cards:");
for(int i =0; i<board.length;i++){
System.out.println(i+1 + ": " + getBoardCard(i).printCard());
}
System.out.println("\n");
}
protected void printBurnCards(){
System.out.println("The burn cards are:");
for(int i =0; i<burnCards.length;i++){
System.out.println(i+1 + ": " + getBurnCard(i).printCard());
}
System.out.println("\n");
}
}
#1 楼
让我们从最基本的Card
类开始。而不是使用通配符。import java.util.*;
将等级和西服存储为
short
无疑是一个有效的选择,因为它很可能最快,最有效的方法,但是如果您想学习Java的特定知识,则可能需要研究枚举。public class Card{
private short rank, suit;
IMHO卡是不可变对象的主要示例。没有理由需要更改牌的等级或花色,所以我会丢掉二传手。
protected void setSuit(short suit){
this.suit = suit;
}
protected void setRank(short rank){
this.rank = rank;
}
在Java变量名中使用下划线非常不寻常,尤其是两个前缀。我会简单地命名参数
rank
和suit
,尤其是因为它们是类(静态)方法而不是实例方法,因此与字段没有混淆。如果这些实际上必须是类方法,而不应该是实例方法。如果您还有其他需要独立于
short
类将Card
转换为相应名称的类,则可以。但就您的情况而言,我会说并非如此,应该尽量掩盖事实,即西装和军衔已尽可能实现为short
。public static String rankAsString(int __rank){
return ranks[__rank];
}
public static String suitAsString(int __suit){
return suits[__suit];
}
Java社区对此问题感到困惑,是否应该纯粹出于调试原因而重写
toString()
方法,还是应在“业务逻辑”中使用它。在这个“简单”的应用程序中,我认为您无需区分这两种用途,因此我将删除printCard()
,而仅使用toString()
。BTW,习惯上在方法修饰符之前有注释。
public @Override String toString(){
return rank + " of " + suit;
}
// Print card to string
protected String printCard(){
return ranks[rank] + " of " + suits[suit];
}
除了实现自己的方法外,重写
equals()
(或至少使其成为实例方法)可能是一个好主意。如果像我之前建议的那样使Card
不可变,则它简化了比较参考以查看参考是否相同的实现,因为每个可能的卡只能有一个实例。 public static boolean sameCard(Card card1, Card card2){
return (card1.rank == card2.rank && card1.suit == card2.suit);
}
(尽管比较等级和西服可能会更安全。)
编辑1:
首先是关于枚举的快速题外话。枚举有一个序数和一个
compareTo
方法,使您可以对它们进行排序。您还可以为它们分配属性,并根据这些属性创建自己的顺序。官方语言指南提供了一些示例,这些示例适用于西装和等级枚举,以及使用行星作为示例扩展具有您自己的属性的枚举:http: //download.oracle.com/javase/1.5.0/docs/guide/language/enums.html
何时/如果我获得手排名(我还没看过)我也许可以提出一些建议,以通过枚举来实现它。
接下来是
Comparator
。我对它们没有太多经验,所以我只能提出一些一般性建议:类应始终以Java中的大写字母开头。
您应该扩展它们从
Comparator<Card>
而不是Comparator<Object>
开始,因为您只需要彼此比较卡,而不需要与其他任何对象进行比较。一般而言(尤其是德州扑克)。西装永远不会有通常仅在某些“元”上下文(例如,随机确定按钮的位置)中才需要的手排序,而当前不适用于您的程序。但是,如果您保留它,则应该更正西装的顺序,因为官方排名是(从最低到最高)“俱乐部”,“钻石”,“心脏”和“黑桃”。接下来是董事会。首先,我想说的是,我不确定在现实世界的扑克应用程序中是否会使用这样的Board类。但是,从我的头顶上,我想不出其他方法来做这件事,并且在实践中,这是完全可以的。
我唯一要改变的是,而不是通过索引显式设置每张卡使用
setBoardCard(Card card, int cardNum)
时,我将让Board类本身在内部跟踪索引,而仅使用addBoardCard(Card card)
,因为您不应该“返回”并更改板卡(刻录卡的同上)。 编辑2:
关于分类服:好的,这很有意义。我还没看过手工评估。但是,更多的是将这种排序分组,因此也许有另一种(更好的)方式来做到这一点。我必须考虑一下。
跟踪索引:您当然可以使用
Collection
(或更具体地说,是List
)来执行此操作(它会更像“类似于Java” ”,但如果您的主板上有固定的最大卡数,则阵列就可以了。我会这样:@Override public boolean equals(Object that) {
return this == that;
}
接下来是
Deck
:首先,我建议静态地仅创建一个
Random
对象,而不是为shuffle
和cutDeck
的每个调用都创建一个。真正的问题是创建一个新的临时
Deck
对象,用于切割牌组,这可能会很快出错,因为它包含不必要的第二组卡片,如果有错误,您很容易会得到重复的卡片,而只需使用一个新的数组即可。使用System.arraycopy可以简化从一个阵列到另一个阵列的复制。编辑3:
创建新的
Deck
不仅会创建一个新的数组,还会创建一个填充的数组用新的ca rds,您不需要。只需一个数组就足够了:public class Board { //abbreviated
private Card[] board = new Card[5];
private Card[] burnCards = new Card[3];
private int boardIndex = 0;
private int burnCardIndex = 0;
//methods
protected void addBoardCard(Card card){
this.board[boardIndex++] = card;
}
protected void addBurnCard(Card card){
this.burnCards[burnCardIndex++] = card;
}
}
编辑4:
关于
Player
没什么好说的,除了我删除了setCard
只是使用构造函数将卡分配给玩家以使对象不可变。或至少像addCard
中那样实现Board
方法。主类:
在
getNumberOfPlayers
中,您的错误处理有些不一致。一方面,您写给System.out
(可能更好地使用System.err
),另一方面,您引发异常。在较大的项目中,将其“包装”到您自己的Exception类中可能是有意义的:protected void cutDeck(){
Card[] temp = new Card[52];
Random random = new Random();
int cutNum = random.nextInt(52);
System.arraycopy(this.cards, 0, temp, 52-cutNum, cutNum);
System.arraycopy(this.cards, cutNum, temp, 0, 52-cutNum);
this.cards = temp;
}
被捕获的
IOException
和无效范围都应该抛出相同的错误(或相关)自定义异常。不要仅仅抛出一个简单的getNumberOfPlayers
,因为它对需要抓住它的其他人毫无意义。示例:try {
userInput = br.readLine();
} catch (IOException ioe) {
throw new HoldemIOException(ioe);
}
请注意,在引起原因的
NumberFormatException
和Exception
中,如果需要进一步的处理,将它们作为新异常的参数传递。 > IOException
和NumberFormatException
都可以从基本的HoldemIOException
扩展而来,后者又扩展了HoldemUserException
。一个简单的“空”扩展,例如try {
intPlayers = Integer.parseInt(userInput);
} catch (NumberFormatException nfe) {
throw new HoldemUserException("Error: Not an integer entered for number of players", nfe);
}
if ((intPlayers<1) || (intPlayers>9)){
throw new HoldemUserException("Error: Number of players must be an integer between 1 and 9");
}
,这三种情况就足够了。一个自我抛出的错误)只是在最后完全未处理掉。在合理的位置(在您的情况下)在
HoldemException
处捕获所有已知的异常:class HoldemException extends Exception {}
我仅添加了
Exception
循环,以显示如何处理这两种类型例外情况有所不同。为用户添加一个退出循环的适当方法将是明智的。处理卡:
在这里,我们还有另一个计数器(
getNumberOfPlayers
)来跟踪平台的“位置”。同样,最好让do while
类跟踪已发行的卡。您应该考虑将Deck实现为实际的“堆栈”或“队列”-无关紧要,因为您没有添加任何项目。 Java提供了可以使用的cardCounter
接口。考虑一下,您还可以对Deck
和Queue
使用相同的接口(尽管在这种情况下,您需要将烧录卡分离为自己的对象)。这样可以简化对Player
,Board
和player.add(deck.remove());
的处理。编辑5:
好吧,很可能是最终编辑。
我已经开始研究人工评估,但我认为我不能为此写太多。您已经基于当前Card对象以非常有程序性的方式实现了它,如果您的目标是以更Java的方式实现它,则可能需要重新编写Card对象并首先创建一个合适的“ Hand”对象(最有可能基于
board.add(deck.remove());
),然后根据该结果重新编写评估。扑克手评估是一个非常复杂的主题,尤其是当考虑到7张纸牌中的5张时。将取决于您是否要专注于“ Java良好实践”或“速度”。如果您真的有兴趣扩大此范围,那么您可能首先应该阅读该主题-关于Stack Overflow的几个问题,以及网上可能有无数的文章-然后重新发布一个新的问题,重点是手工评估。如果有时间,我会很高兴看到这一天。
只有一件事:一个,两个,三个和四个常数是什么?即使对于程序方法,这些似乎也完全不合适,应该很可能在使用它们的地方被适当的循环所代替。
最后,祝您玩得开心,好运爪哇土地冒险!
评论
\ $ \ begingroup \ $
@RoToRa:谢谢,我将尝试将我的回复发布为个人评论。 RE:导入我将java.util。*更改为java.util.Comparator
\ $ \ endgroup \ $
–user2733
2011年3月22日22:00
\ $ \ begingroup \ $
RE枚举:我本来确实拥有像枚举一样的等级和花色,但是当我开始思考需要如何按等级和花色对我的牌进行排序时,我将它们切换为空值,所以我不知道枚举是否会导致HandEval.class的排序问题,但是我知道在一定程度上可以解决问题,而且我不想走得太远,以至于如果以后不得不切换它,将需要大量的重构。
\ $ \ endgroup \ $
–user2733
2011-3-22在22:02
\ $ \ begingroup \ $
RE:按西装排序。由于皇家同花顺,我发现我在西装和排名上都需要比较器。例如,如果我有7h-8h-8s-9h-9c-10h-Jh。我需要一种对这些心进行排序的方法,以便可以检查连续的7 8 9 10 J心,如果仅按等级对心进行评估,则评估将失败。一件西装没有比其他西装具有更高的优先级,只是使估价容易。
\ $ \ endgroup \ $
–user2733
11 Mar 23 '11 at 13:12
\ $ \ begingroup \ $
在内部重新跟踪索引-您是否有标准的方法?是Collection
- 的吗?如果您有资源或执行此操作的标准方式,我会很感兴趣。再次感谢。
\ $ \ endgroup \ $
–user2733
2011年3月23日下午13:13
\ $ \ begingroup \ $
Re:内部索引,我真的很喜欢这个想法。今天,我将尝试实现该功能,并对洗牌和裁切套牌使用统一的Random对象。我不明白您只为cutDeck创建另一个数组的意思,创建临时甲板确实会创建另一个要使用的数组吗?
\ $ \ endgroup \ $
–user2733
2011-3-24在13:58
#2 楼
请考虑将TexasHoldem类及其所有逻辑(玩家,计数器,...的数量)与初始化方式分开。您的主类将进入
TexasHoldemProgram
类,该类实例化TexasHoldem
类,并且设置例如在main中输入的玩家数量。这种做法称为“模型视图控制器”模式。通过将游戏的逻辑与交互的逻辑分开,您以后可以使用完全不同的GUI重用该类。您可能也应该将其应用于代码的其他部分,但我尚未对其进行全面研究。如果我发现其他答案中未提及的其他值得提及的内容。探索Java祝您好运!
评论
\ $ \ begingroup \ $
我对60,000英尺高度的MVC有所了解,但是我不确定我如何在这里实现它。我是否将创建另一个类,其唯一目的是创建TexasHoldem对象?如果您能解释一下,我实际上非常感兴趣,一旦我掌握了逻辑部分,我确实想为该程序实现一个用户界面。因此,我现在可以奠定的任何基础都将使我以后更轻松地工作。
\ $ \ endgroup \ $
–user2733
2011年3月23日20:19在
\ $ \ begingroup \ $
我从您的代码中注意到,您确实了解如何分离代码。 MVC更进一步,将模型从“控制器”的视图中分离出来。我可以在这里写一个广泛的答案,但是其他人已经在我之前做过(最好添加一下)。我建议您总体上熟悉设计模式,因为MVC是复合模式。我极力推荐Head First设计模式。这是一本非常有趣且有用的文章。如果您已经知道策略和观察者模式,则可以直接进入MVC。
\ $ \ endgroup \ $
–史蒂文·杰里斯(Steven Jeuris)
2011年3月23日在20:45
评论
请根据常见问题解答,在帖子中包含要查看的代码的主要部分。谢谢@Mark Loeser:好的,我真的希望整个程序都在研究,发布会非常冗长,所以我认为将代码发布到pastebin会更好。我将修改我的帖子。
顺便说一句,我不想劝阻您学习Java,但是如果您的Hold'em示例是您计划进行的编程的典型示例,那么您可能会对功能语言感兴趣。以Scala为例,它基本上是具有功能特性的Java。
@RoToRa:我想学习Java,我只是想不出要编写学习它的程序。从Internet上进行教程很快就会变得陈旧,并且不允许我以自己感兴趣的水平解决问题。我过去的经验是在C中工作,所以这可能就是为什么我以这种方式编写程序的原因。我还希望有一些代码示例,因此在面试时,我会向他们展示一些东西,因为我还没有任何使用该语言的经验。
众所周知,扑克很难与OOP一起使用。大酒杯的效果更好。此外,本教程站点还提供了许多有关扑克方面的Java练习,这些练习是更复杂练习的基础。您还将学习GUI,IO,线程,ADT和泛型,它们比IMHO的级别更高。我认为这是相当不错的东西:)