目录
原题呈现
题意分析
简单的概括本游戏:
实现功能:
代码实现
参与者类
发牌器类
判断机制game类
Main运行类
运行结果
总结
人称Black Jack,21点!
"21点"纸牌游戏是一种古老的扑克牌游戏,游戏规则是参与者设法使自己的牌达到总分21,而不超过这个数值(<=21)。扑克牌的分值取他们的面值,A充当1分,J、Q、和K分别是11、12和13分
庄家和玩家,在开局时各有两张牌,玩家可以看到自己的牌及总分,而庄家有一张牌暂时隐藏的。接下来,若玩家愿意,玩家可以再拿一张牌(经过多次阅读相关游戏规则,现实中每位玩家是可以无限要牌的,但基于本题的,玩家只能再拿一张更为合理,即每位玩家和庄家最多三张牌),如果玩家的总分超过了21分,即引爆,那么玩家就输了。在玩家拿了额外的牌后,庄家将显示隐藏的牌。只有庄家的总分小于等于21,那么他就必须拿牌,如果庄家引爆了,那么玩家将获胜。否则将玩家和庄家的总分的作比较,如果玩家的总分大于庄家的总分,则玩家获胜。若总分相同,则玩家与庄家打成平局。
要求:利用链表实现洗牌、发牌、计算总分、显示扑克的花色和面值
(由于实际的21点游戏规则和本题有所出入,此处限制参与人数:庄家1名,玩家(闲家)1名)
总体来讲,我们需要用程序实现以下几个功能:
功能:获取牌,分数,身份
package 数据结构;
import java.util.ArrayList;
/**
* 玩家
*/
public class Player {
//玩家手中牌
private ArrayList cardList=new ArrayList<>();
//分数
private int mark=0;
//身份
private String identity;
public Player() {
}
public Player(String identity) {
this.identity = identity;
}
//获取身份名称
public String getIdentity() {
return identity;
}
public void setIdentity(String identity) {
this.identity = identity;
}
//获取分数
public int getMark() {
return mark;
}
//设置分数
public void setMark(int mark) {
this.mark = mark;
}
//获取玩家手牌
public ArrayList getCardList() {
return cardList;
}
//玩家拿牌
public void setCard(String card){
cardList.add(card);
}
}
功能:生产牌,记录牌,提供对应卡牌的分值表
package 数据结构;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Random;
/**
* 发牌器
*/
public class Dealer {
//总牌
private ArrayList getCardList = new ArrayList<>();
//已经发放的牌
private LinkedList terminal = new LinkedList<>();
//分值本
private HashMap map = new HashMap();
//洗牌
public void ini() {
String[] color = {"红心", "黑桃", "梅花", "方块"};
String[] number = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};
for (int i = 0; i < color.length; i++) {
for (int i1 = 0; i1 < number.length; i1++) {
getCardList.add(color[i] + number[i1]);
map.put(color[i] + number[i1], i1 + 1);
}
}
}
//获取一个随机的卡牌
public String getCard() {
Random random = new Random();
String card = getCardList.get(random.nextInt(getCardList.size()));
while (terminal.contains(card)) card = getCardList.get(random.nextInt(getCardList.size()));
terminal.add(card);
return card;
}
//获取分值本
public HashMap getMap() {
return map;
}
}
功能:判定参与者是否引爆,存储参与者对象
package 数据结构;
import java.util.ArrayList;
import java.util.HashMap;
public class Game {
private ArrayList plays = new ArrayList();
private Dealer dealer = new Dealer();
public Game(Dealer dealer) {
this.dealer = dealer;
}
//判断参与者是否引爆
public boolean isDead(Player player) {
return player.getMark() > 21 ? true : false;
}
//获取参与者的分数
public int getMark(Player player) {
int mark = 0;
HashMap map = dealer.getMap();
for (String card : player.getCardList()) {
mark += map.get(card);
}
return mark;
}
//历遍显示参与者的牌
public void show(Player player) {
for (String s : player.getCardList()) {
System.out.print(s + " ");
}
}
//获取参与者对象集合
public ArrayList getPlays() {
return plays;
}
public void judge() {
if (isDead(getPlays().get(0)) && !isDead(getPlays().get(1))) {//若庄家引爆,玩家未引爆
printMark();
System.out.println(getPlays().get(0).getIdentity() + "已引爆," + getPlays().get(1).getIdentity() + "获胜");
System.out.println();
} else if (!isDead(getPlays().get(0)) && isDead(getPlays().get(1))) {//若庄家未引爆,玩家引爆
printMark();
System.out.println(getPlays().get(1).getIdentity() + "已引爆," + getPlays().get(0).getIdentity() + "获胜");
System.out.println();
} else if (isDead(getPlays().get(0)) && isDead(getPlays().get(1))) {//若两者均引爆
printMark();
System.out.println(getPlays().get(1).getIdentity() + "和" + getPlays().get(0).getIdentity() + "均已引爆,平局");
System.out.println();
} else {//两者均未引爆
if (getPlays().get(0).getMark() > getPlays().get(1).getMark()) {
printMark();
System.out.println(getPlays().get(0).getIdentity() + "赢得了胜利");
System.out.println();
} else if (getPlays().get(0).getMark() < getPlays().get(1).getMark()) {
printMark();
System.out.println(getPlays().get(1).getIdentity() + "赢得了胜利");
System.out.println();
} else {
printMark();
System.out.println("平局");
System.out.println();
}
}
}
public void printMark() {
System.out.print(getPlays().get(0).getIdentity() + "手牌为:");
show(getPlays().get(0));
System.out.print(" " + getPlays().get(0).getIdentity()+"得分为:" + getPlays().get(0).getMark());
System.out.println();
System.out.print(getPlays().get(1).getIdentity() + "手牌为:");
show(getPlays().get(1));
System.out.print(" " + getPlays().get(1).getIdentity() + "得分为:" + getPlays().get(1).getMark());
System.out.println();
}
}
功能:整合代码,实现逻辑运行
package 数据结构;
import java.io.*;
public class Main {
static StreamTokenizer r;
static PrintWriter pr;
static BufferedReader re;
static Dealer dealer;;//初始化发牌器
static Game game;
static {
r = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
pr = new PrintWriter(new OutputStreamWriter(System.out));
re = new BufferedReader(new InputStreamReader(System.in));
}
public static void main(String[] args) throws IOException {
System.out.println("-------------21点游戏正式开始-------------");
int round = 0;
while (true) {
//初始化
dealer=new Dealer();
dealer.ini();
game=new Game(dealer);
pr.println(" (第" + ++round + "回合) ");
pr.flush();
//初始化发牌器
dealer.ini();
//初始化参与者(两位:一名庄家,一名玩家)
Player player1 = new Player("庄家");
Player player2 = new Player("玩家");
game.getPlays().add(player1);
game.getPlays().add(player2);
//玩家发牌
for (int i = 0; i < game.getPlays().size(); i++) {
for (int i1 = 0; i1 < 2; i1++) {
game.getPlays().get(i).setCard(dealer.getCard());
}
//存储玩家的分数
game.getPlays().get(i).setMark(game.getMark(game.getPlays().get(i)));
}
//进行牌的展示,并计算得分
for (int i = 0; i < game.getPlays().size(); i++) {
int cord = 0;
pr.print(game.getPlays().get(i).getIdentity() + ":");
pr.flush();
game.show(game.getPlays().get(i));
System.out.println();
}
//发牌后进行拿牌阶段
pr.println("请玩家选择是否继续摸牌(输入0不摸牌,否则再拿一张牌)");
pr.flush();
String status = re.readLine();
if (status.equals("0")) {//若玩家不拿牌
pr.println("玩家选择不拿牌");
pr.flush();
pr.println("请庄家选择是否继续摸牌(输入0不摸牌,输入1再拿一张牌)");
pr.flush();
String status1 = re.readLine();
if (status1.equals("0")) {//若庄家也不拿牌
game.judge();
} else {//若庄家拿牌
String card = dealer.getCard();
pr.println("庄家选择再拿一张:"+card);
pr.flush();
game.getPlays().get(0).getCardList().add(card);
game.getPlays().get(0).setMark(game.getMark(game.getPlays().get(0)));
game.judge();
}
} else {//若玩家拿牌
String card1 = dealer.getCard();
pr.println("玩家选择再拿一张牌:"+card1);
pr.flush();
game.getPlays().get(1).getCardList().add(card1);
game.getPlays().get(1).setMark(game.getMark(game.getPlays().get(1)));
String card2 = dealer.getCard();
pr.println("庄家选择再拿一张牌:"+card2);
pr.flush();
game.getPlays().get(0).getCardList().add(card2);
game.getPlays().get(0).setMark(game.getMark(game.getPlays().get(0)));
game.judge();
}
}
}
}
再本题中我们是采用面向对象的思想来解决本题的,对应本题而言采用这种思想可能反而加大了我们的代码量,但从长远的角度,这样写有助于我们后期的维护,减少了代码间的耦合:比如,若我们再升级下游戏的玩法,给参与者加上钱数,那么对于我们程序的改动将会很友好