背景
自学Java已有一周,决定开始做一个慕课里的小作业:简易扑克牌比大小
ps:我还真不会打牌…-_-||
游戏背景:两人每人随机发两张扑克牌(从同一副牌中),不考虑大、小王,每张牌包括花色(黑桃(Spade) > 红桃(Heart) > 梅花(Club) > 方片(Diamond))和大小(从小到大依次是:2-10,J,P,K,A),谁拥有最大的牌谁获胜,比较大小的规则是:点数相等比花色大小,否则比点数大小。
要求:需要做到输入两个选手的ID与姓名,给一副牌洗牌,分别发牌各两张,比较大小并输出。
涉及的知识点
- 面向对象程序设计、封装、继承、多态:将选手与扑克牌设计成类,实例化成对象;
- 输入输出;
- 数据结构 List 以及其自带的算法;
- 条件语句、循环结构;
- 异常处理:当输入的选手ID不是一个整数时,提示重新输入ID;
- 自定义比较大小规则:对接口类Comparable的compareTo()方法进行重写;
- 迭代器遍历容器:洗牌后逐个输出与初始状态对比;
源代码
第一个类 Card
package easypokergame;
import java.util.*;
public class Card implements Comparable<Card>{
static String[] Points;
static String[] FourSuits;
static{
Points=new String[]{"2","3","4","5","6","7","8","9","10","J","Q","K","A"};
FourSuits=new String[]{"方片","梅花","红桃","黑桃"};
}
public int PointsIndex;
public int FourSuitsIndex;
Card(int a,int b){
PointsIndex=a;
FourSuitsIndex=b;
}
public int getpoid(){
return this.PointsIndex;
}
public int getfrstid(){
return this.FourSuitsIndex;
}
static public void showcard(int a,int b){
if(a<0||a>=13||b<0||b>=4)
{
System.out.println("Input Error!\nPlease input again!");
Scanner inp=new Scanner(System.in);
showcard(inp.nextInt(),inp.nextInt());
}else{
System.out.print(Card.FourSuits[b]+Card.Points[a]);
}
}
public void show(){
System.out.println(Card.FourSuits[this.FourSuitsIndex]+Card.Points[this.PointsIndex]);
}
public void show2(){
System.out.print(Card.FourSuits[this.FourSuitsIndex]+Card.Points[this.PointsIndex]);
}
//重写比较大小的方法
@Override
public int compareTo(Card o) {
if(this.PointsIndex==o.getpoid()){
if(o.getfrstid()>this.FourSuitsIndex)
return 1;
else
return -1;
}else{
if(o.getpoid()>this.PointsIndex)
return 1;
else
return -1;
}
}
}
第二个类 Player
package easypokergame;
import java.util.*;
public class Player {
int id;
String name;
List<Card> Cards;
public Player(int id,String name){
this.id=id;
this.name=name;
Cards=new ArrayList();
}
public void AddCard(Card Acard){
Cards.add(Acard);
}
public int getid(){
return id;
}
public String getname(){
return name;
}
public List<Card> getcards(){
return this.Cards;
}
}
第三个类,即主类 EasyPokerGame
package easypokergame;
import java.util.*;
public class EasyPokerGame {
Player player1,player2;
List<Card> Cards;
//随机生成一副扑克牌
public void CreatePokerCards(){
System.out.println("-----------创建扑克牌-----------");
Cards=new ArrayList();
for(int i=0;i<13;i++)
for(int j=0;j<4;j++)
Cards.add(new Card(i,j));
System.out.println("-----------扑克牌创建成功!-----------");
System.out.print("初始化为 :[");
for(int i=0;i<4;i++)
for(int j=0;j<13;j++)
{
Card.showcard(j, i);
if(!(i==3&&j==12))
System.out.print(",");
else
System.out.println("]");
}
System.out.println("-----------开始洗牌-----------");
Collections.shuffle(Cards);
Iterator it=Cards.iterator();
System.out.print("洗牌后为 :[");
while(it.hasNext()){
Card cd=(Card)it.next();
cd.show2();
if(!it.hasNext())
System.out.println("]");
else
System.out.print(",");
}
System.out.println("-----------洗牌结束!-----------");
}
//输入玩家信息
public void CreatePlayers(){
System.out.println("-----------创建玩家...-----------");
Scanner input=new Scanner(System.in);
int id=0;
String name="default";
for(int i=0;i<2;i++){
try{
System.out.println("请输入第"+(i+1)+"位玩家的ID和姓名:");
System.out.println("输入ID:");
id=input.nextInt();
System.out.println("输入姓名:");
name=input.next();
if(i==0)
player1=new Player(id,name);
if(i==1)
player2=new Player(id,name);
}catch(InputMismatchException e){
System.out.println("请输入整数类型的ID!");
input.next();
i--;
continue;
}
}
System.out.println("------欢迎玩家:"+player1.getname());
System.out.println("------欢迎玩家:"+player2.getname());
}
//发牌
public void DistributeCards(){
System.out.println("-----------开始发牌...-----------");
for(int i=0;i<4;){
player1.AddCard(Cards.get(i));
System.out.println("------玩家:"+player1.getname()+"-拿牌");
i++;
player2.AddCard(Cards.get(i));
System.out.println("------玩家:"+player2.getname()+"-拿牌");
i++;
}
System.out.println("-----------发牌结束!-----------");
}
//两个玩家取出最大手牌相比较
public void Compare(){
System.out.println("-----------开始游戏...-----------");
Collections.sort(player1.getcards());
System.out.print("玩家:"+player1.getname()+"最大的手牌为:");
player1.getcards().get(0).show();
Collections.sort(player2.getcards());
System.out.print("玩家:"+player2.getname()+"最大的手牌为:");
player2.getcards().get(0).show();
int pointindex1=player1.getcards().get(0).getpoid();
int pointindex2=player2.getcards().get(0).getpoid();
int suitindex1=player1.getcards().get(0).getfrstid();
int suitindex2=player2.getcards().get(0).getfrstid();
if((pointindex1==pointindex2&&suitindex1>suitindex2)||pointindex1>pointindex2)//点数相等比花色大小 否则比点数大小
System.out.println("-----------玩家:"+player1.getname()+"获胜!-----------");
else
System.out.println("-----------玩家:"+player2.getname()+"获胜!-----------");
System.out.println("玩家各自的手牌为:");
System.out.print(player1.getname()+":[");
player1.getcards().get(0).show2();
System.out.print(",");
player1.getcards().get(1).show2();
System.out.println("]");
System.out.print(player2.getname()+":[");
player2.getcards().get(0).show2();
System.out.print(",");
player2.getcards().get(1).show2();
System.out.println("]");
System.out.println("-----------游戏结束!-----------");
}
public static void main(String[] args) {
EasyPokerGame game=new EasyPokerGame();
game.CreatePokerCards();
game.CreatePlayers();
game.DistributeCards();
game.Compare();
}
}
代码执行结果
第一次:
输入第一位选手ID为:1,姓名为:Tom
输入第二位选手ID为:2,姓名为:Jack
结果如下:
run:
-----------创建扑克牌-----------
-----------扑克牌创建成功!-----------
初始化为 :[方片2,方片3,方片4,方片5,方片6,方片7,方片8,方片9,方片10,方片J,方片Q,方片K,方片A,梅花2,梅花3,梅花4,梅花5,梅花6,梅花7,梅花8,梅花9,梅花10,梅花J,梅花Q,梅花K,梅花A,红桃2,红桃3,红桃4,红桃5,红桃6,红桃7,红桃8,红桃9,红桃10,红桃J,红桃Q,红桃K,红桃A,黑桃2,黑桃3,黑桃4,黑桃5,黑桃6,黑桃7,黑桃8,黑桃9,黑桃10,黑桃J,黑桃Q,黑桃K,黑桃A]
-----------开始洗牌-----------
洗牌后为 :[方片A,梅花K,方片7,黑桃J,方片Q,梅花6,红桃2,黑桃2,黑桃10,红桃8,红桃7,方片9,黑桃K,梅花3,梅花J,梅花4,方片J,红桃10,黑桃A,黑桃8,梅花8,黑桃Q,红桃J,黑桃6,红桃4,黑桃7,方片10,红桃3,黑桃4,黑桃9,红桃Q,梅花9,红桃K,梅花Q,方片K,黑桃3,梅花10,红桃9,梅花7,梅花5,方片3,红桃5,黑桃5,梅花A,红桃A,梅花2,红桃6,方片5,方片4,方片6,方片2,方片8]
-----------洗牌结束!-----------
-----------创建玩家...-----------
请输入第1位玩家的ID和姓名:
输入ID:
1
输入姓名:
Tom
请输入第2位玩家的ID和姓名:
输入ID:
2
输入姓名:
Jack
------欢迎玩家:Tom
------欢迎玩家:Jack
-----------开始发牌...-----------
------玩家:Tom-拿牌
------玩家:Jack-拿牌
------玩家:Tom-拿牌
------玩家:Jack-拿牌
-----------发牌结束!-----------
-----------开始游戏...-----------
玩家:Tom最大的手牌为:方片A
玩家:Jack最大的手牌为:梅花K
-----------玩家:Tom获胜!-----------
玩家各自的手牌为:
Tom:[方片A,方片7]
Jack:[梅花K,黑桃J]
-----------游戏结束!-----------
成功构建 (总时间: 13 秒)
第二次(测试一下异常处理):
尝试输入第一位选手ID为:pig
提示错误
然后输入第一位选手正确ID为:666,姓名为Anny
输入第二位选手的ID为:2333,姓名为Mark
run:
-----------创建扑克牌-----------
-----------扑克牌创建成功!-----------
初始化为 :[方片2,方片3,方片4,方片5,方片6,方片7,方片8,方片9,方片10,方片J,方片Q,方片K,方片A,梅花2,梅花3,梅花4,梅花5,梅花6,梅花7,梅花8,梅花9,梅花10,梅花J,梅花Q,梅花K,梅花A,红桃2,红桃3,红桃4,红桃5,红桃6,红桃7,红桃8,红桃9,红桃10,红桃J,红桃Q,红桃K,红桃A,黑桃2,黑桃3,黑桃4,黑桃5,黑桃6,黑桃7,黑桃8,黑桃9,黑桃10,黑桃J,黑桃Q,黑桃K,黑桃A]
-----------开始洗牌-----------
洗牌后为 :[黑桃4,方片4,方片8,黑桃3,梅花6,红桃K,梅花J,方片5,梅花7,梅花Q,红桃J,梅花K,红桃7,红桃A,方片J,方片6,黑桃7,红桃5,黑桃Q,红桃8,方片A,梅花10,红桃4,梅花2,红桃Q,梅花9,梅花8,方片3,黑桃5,黑桃A,方片2,方片K,梅花3,红桃10,方片Q,梅花4,黑桃8,黑桃6,黑桃10,红桃2,黑桃2,红桃6,红桃3,红桃9,方片9,方片7,方片10,黑桃K,梅花5,梅花A,黑桃J,黑桃9]
-----------洗牌结束!-----------
-----------创建玩家...-----------
请输入第1位玩家的ID和姓名:
输入ID:
pig
请输入整数类型的ID!
请输入第1位玩家的ID和姓名:
输入ID:
666
输入姓名:
Anny
请输入第2位玩家的ID和姓名:
输入ID:
2333
输入姓名:
Mark
------欢迎玩家:Anny
------欢迎玩家:Mark
-----------开始发牌...-----------
------玩家:Anny-拿牌
------玩家:Mark-拿牌
------玩家:Anny-拿牌
------玩家:Mark-拿牌
-----------发牌结束!-----------
-----------开始游戏...-----------
玩家:Anny最大的手牌为:方片8
玩家:Mark最大的手牌为:方片4
-----------玩家:Anny获胜!-----------
玩家各自的手牌为:
Anny:[方片8,黑桃4]
Mark:[方片4,黑桃3]
-----------游戏结束!-----------
成功构建 (总时间: 16 秒)
注意事项
- 当异常处理放在循环结构内部,有时候会出问题,陷入死循环。通过查资料得知,这是由于Scanner接受键盘输入信息的机制所造成的后果:
Scanner在接受键盘输入时,在内存中会有一段专门用来接收键盘输入的信息。键盘信息输入内存以后与你定义的接收输入的类型匹配,如果不匹配会抛出异常,但是键盘输入的信息会停留在内存当中,当下次需要输入时直接读取该内存存在的值,继续抛出异常,导致无限循环。
解决方案详见 这篇博客
java 输入流异常处理并重新输入,无限循环抛异常问题处理_liudliu1992的博客
link.
我采用的方法是在捕获异常后,增加一句Scanner的对象.next(),以清空上一次输入所占用的内存
}catch(InputMismatchException e){
System.out.println("请输入整数类型的ID!");
input.next();
i--;
continue;
}
- 使用迭代器,取出容器内元素拷贝构造另一个同类元素时:
Iterator it=Cards.iterator();
System.out.print("洗牌后为 :[");
while(it.hasNext()){
Card cd=(Card)it.next();
cd.show2();
if(!it.hasNext())
System.out.println("]");
else
System.out.print(",");
}
第一句代码必须使用强制类型转换,原因在于,不用泛型类声明Iterator的话,从List容器所取出的元素统一是Object类型的,所以需要使用强制类型转换
而若使用泛型类,则不需要强制类型转换:
Iterator<Card> it=Cards.iterator();
System.out.print("洗牌后为 :[");
while(it.hasNext()){
Card cd=it.next();
cd.show2();
if(!it.hasNext())
System.out.println("]");
else
System.out.print(",");
}
结尾碎碎念
作为Java小白,我还有很多需要学习的(๑• . •๑)
第一次发blog,也不知道自己有没有错误和纰漏呀!!
希望代码没事/双手合十,希望人没事2333…
欢迎大佬们来交♂流或是批评指正 !!