最近给大家分享一个在学习过程中比较有意义的面向对象的思想的控制台实现斗地主
要求大概就是有一个地主、两个农民,一副牌,谁先出完牌谁就获胜,简单的思路。
遇到这种面向对象的题目时首先需要分析一下,理清一下思路。
1、分析
首先我们需要一个人物类,人物类有一个集合装每个人的牌(农民17张,地主20张),有姓名(地主,或者农民),还有一个判断是否是地主的属性,人物还有出牌的方法
还要有一个游戏类,有一个集合装54张牌,有花色和大小两个属性,有发牌,洗牌,判断地主等方法
初步分析就大概这些东西,编写过程中遇到问题再慢慢修复
首先,写一个游戏类里面有花色和牌的大小
private static final String[] pokecard = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2", "小王", "大王"}; //牌的值
private static final String[] pokecolor = {"♠", "♥", "♣", "♦"}; //牌的花色
然后,构造一个54张牌的容器用来装牌
//生成一副牌的方法
public static ArrayList makePoke(){
//将牌装入集合中
ArrayList poke = new ArrayList<>();
for(int i=0;i<pokecard.length-2;i++){
for(int j=0;j<pokecolor.length;j++){
String s = pokecolor[j] + pokecard[i];
poke.add(s);
}
}
//大小王没有花色,单独装进集合中
poke.add(pokecard[pokecard.length-2]);
poke.add(pokecard[pokecard.length-1]);
return poke;
}
然后也要洗牌,用集合的shuffle方法打乱牌的顺序即可
private ArrayList xipai(ArrayList list){
Collections.shuffle(list);
return list;
}
写的详尽一点的话,可以写一个选地主的一个方法,随机挑选地主,如下:
public void xuandizhu(Person p1,Person p2, Person p3){
Random random = new Random();
int n=random.nextInt(3)+1;
if(n==1){
System.out.println(p1.getName()+"当选地主");
p1.setDiZhu(true);
}else if(n==2){
System.out.println(p2.getName()+"当选地主");
p2.setDiZhu(true);
}else if(n==3){
System.out.println(p3.getName()+"当选地主");
p3.setDiZhu(true);
}
}
然后进行发牌,写一个发牌的方法,里面传入三个人物,用每个集合单独装,地主的话最后三张牌给它即可
public void fapai(ArrayList list,Person p1,Person p2,Person p3){
ArrayList list1 = xipai(list);
xuandizhu(p1,p2,p3);
for(int i=0;i<list.size()-3;i+=3){
p1.getPoke().add(list1.get(i));
p2.getPoke().add(list1.get(i+1));
p3.getPoke().add(list1.get(i+2));
}
if(p1.isDiZhu()){
p1.getPoke().add(list1.get(list1.size()-3));
p1.getPoke().add(list1.get(list1.size()-2));
p1.getPoke().add(list1.get(list1.size()-1));
}
else if(p2.isDiZhu()){
p2.getPoke().add(list1.get(list1.size()-3));
p2.getPoke().add(list1.get(list1.size()-2));
p2.getPoke().add(list1.get(list1.size()-1));
}
else if(p3.isDiZhu()){
p3.getPoke().add(list1.get(list1.size()-3));
p3.getPoke().add(list1.get(list1.size()-2));
p3.getPoke().add(list1.get(list1.size()-1));
}
}
那么有一个问题就是,打乱了牌的顺序,如何能够正确的在控制台上显示牌呢?所以需要用到排序,那么在斗地主中,JQKA2这些牌是没办法通过自然排序的,所以我们这里自定义一个比较器
如下,我想到的是用asii码来比较
@Override
public int compare(String o1, String o2) {
char m = 0 ,n = 0;
if(o1.charAt(1) == '2'){
m = 'M';
}
else if(o1.charAt(1) == '1'){
m = ':';
}
else if(o1.charAt(1) == 'J'){
m = 'I';
}
else if(o1.charAt(1) == 'Q'){
m = 'J';
}
else if(o1.charAt(1) == 'A'){
m = 'L';
}
else if(o1.charAt(0) == '大'){
m = 'O';
}
else if(o1.charAt(0) == '小'){
m = 'N';
}
else{
m = o1.charAt(1);
}
if(o2.charAt(1) == '2'){
n = 'M';
}
else if(o2.charAt(1) == '1'){
n = ':';
}
else if(o2.charAt(1) == 'J'){
n = 'I';
}
else if(o2.charAt(1) == 'Q'){
n = 'J';
}
else if(o2.charAt(1) == 'A'){
n = 'L';
}
else if(o2.charAt(0) == '大'){
n = 'O';
}
else if(o2.charAt(0) == '小'){
n = 'N';
}
else{
n = o2.charAt(1);
}
return m - n;
}
那么游戏类就大致写好了,再来看看人物类
private String name;
private ArrayList poke=new ArrayList();
private boolean isDiZhu;
static Scanner sc=new Scanner(System.in);
public Person(String name, ArrayList poke) {
this.name = name;
this.poke = poke;
this.isDiZhu=false;
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ArrayList getPoke() {
return poke;
}
public void setPoke(ArrayList poke) {
this.poke = poke;
}
public boolean isDiZhu() {
return isDiZhu;
}
public void setDiZhu(boolean diZhu) {
isDiZhu = diZhu;
}
这是基本的属性的封装和构造方法
还有一个理牌的功能实现,即调用上面写好的比较器即可
public void lipai(ArrayList list){
Collections.sort(list,new Game());
}
那么进行到了关键性的一步,也是最难的地方,就是出牌的方法,我们出牌的时候首先要判断手里有没有这些牌,出完牌后还要从集合中移除这些牌,所以可以用一个临时集合来存储,如果删除牌张的数量和出牌的数量相等,那么就出牌成功,反之则失败。如果失败就返回之前的不变的集合,如果成功就返回临时的集合来改变原有的集合,大概就是这样的思路。
/**
* 出牌的方法
*/
public ArrayList sendPoke(ArrayList list){
System.out.println(this.getPoke());
ArrayList listTemp = new ArrayList<>();
for(int i=0;i<list.size();i++){
listTemp.add(list.get(i));
}
String str=sc.next();
String[] split = str.split("");
int i=0,n=0;
Iterator iterator = listTemp.iterator();
while(i<split.length){ //34567 3334
while (iterator.hasNext()){
String num = (String) iterator.next();
if(num.contains(split[i])){
iterator.remove();
n++;
break;
}
}
i++;
}
if(n==split.length){
this.setPoke(listTemp);
System.out.println("出牌成功");
}else {
System.out.println("出牌失败,没有这些牌");
}
return this.getPoke();
}
那么此时我们的一些小方法就写完了,来写测试类。构建对象,调用方法等可以封装到一个开始的方法里,并且判定,如果谁的牌出完了,谁就赢了。
public static void start(){
ArrayList list = Game.makePoke(); //54张牌的牌集合
ArrayList list1 = new ArrayList<>(); //p1集合
ArrayList list2 = new ArrayList<>(); //p2集合
ArrayList list3 = new ArrayList<>(); //p3集合
Person p1=new Person("zs",list1);
Person p2=new Person("ls",list2);
Person p3=new Person("ww",list3);
Game game=new Game();
game.fapai(list,p1,p2,p3);
p1.lipai(list1);
p2.lipai(list2);
p3.lipai(list3);
if (p1.isDiZhu()){
while (true){
System.out.print("地主出牌:");
p1.sendPoke(p1.getPoke());
if(p1.getPoke().size() == 0 ){
System.out.println("地主胜利");
break;
}
System.out.print("农民一出牌:");
p2.sendPoke(p2.getPoke());
if (p2.getPoke().size() == 0|| p3.getPoke().size() == 0){
System.out.println("农民胜利");
break;
}
System.out.print("农民二出牌:");
p3.sendPoke(p3.getPoke());
if (p2.getPoke().size() == 0|| p3.getPoke().size() == 0){
System.out.println("农民胜利");
break;
}
}
}
if (p2.isDiZhu()){
while (true){
System.out.print("地主出牌:");
p2.sendPoke(p2.getPoke());
if(p2.getPoke().size() == 0 ){
System.out.println("地主胜利");
break;
}
System.out.print("农民一出牌:");
p3.sendPoke(p3.getPoke());
if (p1.getPoke().size() == 0|| p3.getPoke().size() == 0){
System.out.println("农民胜利");
break;
}
System.out.print("农民二出牌:");
p1.sendPoke(p1.getPoke());
if (p1.getPoke().size() == 0|| p3.getPoke().size() == 0){
System.out.println("农民胜利");
break;
}
}
}
if (p3.isDiZhu()){
while (true){
System.out.print("地主出牌:");
p3.sendPoke(p3.getPoke());
if(p3.getPoke().size() == 0 ){
System.out.println("地主胜利");
break;
}
System.out.print("农民一出牌:");
p1.sendPoke(p1.getPoke());
if (p2.getPoke().size() == 0|| p1.getPoke().size() == 0){
System.out.println("农民胜利");
break;
}
System.out.print("农民二出牌:");
p2.sendPoke(p2.getPoke());
if (p2.getPoke().size() == 0|| p1.getPoke().size() == 0){
System.out.println("农民胜利");
break;
}
}
}
}
我这里还要分别判断谁是地主,地主先出牌。那么基本的方法就写完了,在main方法里直接调用开始的方法即可完成控制台实现斗地主。
效果如下
写的不是很好,但是对面向对象的思维性有很大的帮助!