java写的麻将小游戏

过年回家在家打麻将,觉得蛮有趣的,就用java写了一个麻将小游戏(没有界面,只能在控制台玩)。
说明:

  • 使用语言:java(jdk1.7)
  • 开发工具:eclipse
  • 项目集成:maven

1 麻将说明

1.1 方位说明(请注意“人”这个玩家的位置)

java写的麻将小游戏_第1张图片

1.2 规则说明

  • 可以碰牌、杠牌
  • 不能吃牌
  • 有东西南北中发白
  • 有癞子
  • 可以自摸,可以放炮
  • 其余的麻将知识请自行百度

2 架构图

java写的麻将小游戏_第2张图片

3 工程结构图

java写的麻将小游戏_第3张图片

4 代码如下:

4.1关于麻将的bean:

  • (1) 麻将的父类
package com.wllfengshu.bean.majiang;
/**
 * 
 * @author Administrator
 *  一切麻将类的父类
 */
public class MaJiang {
    /**
     * 类型:万、条、筒: 1  2  3
     *      东、南、西、北、中、发、白:4、5、6、7、8、9、10
     */
    private int type;

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    @Override
    public String toString() {
        return "MaJiang [type=" + type + "]";
    }
}
  • (2) 字牌(万、条、筒)
package com.wllfengshu.bean.majiang;
/**
 * 
 * @author Administrator
 * 字牌的bean:包含  万、条、筒
 *                  1  2  3
 */
public class MaJiangNumber extends MaJiang{
    /**
     * 数字:1~9
     */
    private int number;

    public int getNumber() {
        return number;
    }
    public void setNumber(int number) {
        this.number = number;
    }

    @Override
    public String toString() {
        String maJiangNumberStr = "[";
        switch (this.getType()) {
        case 1:
            maJiangNumberStr+=this.getNumber()+"万";
            break;
        case 2:
            maJiangNumberStr+=this.getNumber()+"条";
            break;
        case 3:
            maJiangNumberStr+=this.getNumber()+"筒";
            break;
        }
        maJiangNumberStr+="]";
        return maJiangNumberStr;
    }

}
  • (3)风牌(风牌没有任何成员属性)
package com.wllfengshu.bean.majiang;
/**
 * 
 * @author Administrator
 * 风牌的bean:包含  东、南、西、北、中、发、白
 *              1、 2、  3、 4、  5、 6、 7
 */
public class MaJiangWind extends MaJiang{
    @Override
    public String toString() {
        String maJiangWindStr="[";
        switch (this.getType()) {
        case 4:
            maJiangWindStr+="东风";
            break;
        case 5:
            maJiangWindStr+="南风";
            break;
        case 6:
            maJiangWindStr+="西风";
            break;
        case 7:
            maJiangWindStr+="北风";
            break;
        case 8:
            maJiangWindStr+="红中";
            break;
        case 9:
            maJiangWindStr+="发财";
            break;
        case 10:
            maJiangWindStr+="白板";
            break;
        }
        maJiangWindStr+="]";
        return maJiangWindStr;
    }
}
  • (4) 麻将的工厂类
package com.wllfengshu.bean.majiang;
/**
 * 
 * @author Administrator
 * 麻将的工厂类,所有麻将必须通过这个类进行实例化
 */
public class MaJiangFactory {
    /**
     * 通过这个方法创建一张麻将
     * @param type 类型
     */
    public MaJiang createMaJiang(int type){
        //一次只允许创建一张麻将
        MaJiang maJiang=null;

        if (type<=3) {
            maJiang=new MaJiangNumber();
            maJiang.setType(type);
        }else {
            maJiang=new MaJiangWind();
            maJiang.setType(type);
        }
        return maJiang;
    }
}

4.2关于骰子的bean

package com.wllfengshu.bean.dice;

/**
 * 
 * @author Administrator
 * 骰子的bean
 */
public class Dice {
    /**
     * 骰子的点数,1~6的整数
     */
    private int num;

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    @Override
    public String toString() {
        return "Dice [num=" + num + "]";
    }   
}

4.3 关于玩家的bean(后期可以把其余的电脑也改为人来玩)

package com.wllfengshu.bean.player;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.wllfengshu.bean.majiang.MaJiang;
import com.wllfengshu.bean.majiang.MaJiangNumber;
import com.wllfengshu.bean.majiang.MaJiangWind;
import com.wllfengshu.middleware.ShuffleMaJiang;

/**
 * 
 * @author Administrator
 * 玩家
 */
public class Player {
    /**
     * 玩家姓名
     */
    private String name;
    /**
     * 每个玩家的牌都放在playerMaJiangs中
     */
    private List playerMaJiangs=new ArrayList();
    /**
     * 用来指示“每个玩家的牌”在playerMaJiangs中的下标
     */
    private int playerMaJiangsIndex=0;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List getPlayerMaJiangs() {
        return playerMaJiangs;
    }

    public void setPlayerMaJiangs(List playerMaJiangs) {
        this.playerMaJiangs = playerMaJiangs;
    }

    @Override
    public String toString() {
        return "Player [name=" + name + "]";
    }

    /**
     * 起牌:从ShuffleMaJiang中的maJiangs中取一粒麻将,放入到自己的playerMaJiangs中
     * @param index “从ShuffleMaJiang中的maJiangs”获取麻将的指定的位置
     */
    public void gainMaJiang(int index){
        //从ShuffleMaJiang中的maJiangs中取一粒麻将,放入到自己的playerMaJiangs中
        playerMaJiangs.add(playerMaJiangsIndex, ShuffleMaJiang.maJiangs.get(index));
        playerMaJiangsIndex++;
        //原来的ShuffleMaJiang的maJiangs中的牌减少这一粒
        ShuffleMaJiang.maJiangs.remove(index);
    }

    /**
     * 打牌:从自己的playerMaJiangs中取一粒牌,放入到ShuffleMaJiang中的river中
     */
    public MaJiang discardMaJiang(int index){
        if ((index>playerMaJiangs.size()) || (index<=0)) {
            System.out.println("输入的牌不存在");
            return null;
        }
        //从自己的playerMaJiangs中取一粒牌,放入到ShuffleMaJiang中的river中
        ShuffleMaJiang.river.add(ShuffleMaJiang.riverIndex, playerMaJiangs.get(index-1));
        ShuffleMaJiang.riverIndex++;
        //自己的playerMaJiangs中减少这一粒牌
        playerMaJiangs.remove(index);
        return playerMaJiangs.get(index);
    }

    /**
     * 输出该玩家拥有的牌
     */
    public void printMaJiangs(){
        for (MaJiang maJiang : playerMaJiangs) {
            int type = maJiang.getType();
            //输出字牌
            if (type<=3) {
                MaJiangNumber maJiangNumber=(MaJiangNumber)maJiang;
                System.out.print(maJiangNumber+",");
            //输出风牌
            }else {
                MaJiangWind maJiangWind=(MaJiangWind)maJiang;
                System.out.print(maJiangWind+",");
            }
        }
    }

    /**
     * 碰牌:河里刚打出的牌,在玩家手中有两张同样的牌,就可以碰牌
     */
    public void touchCards(){
        //获取河里刚打出的牌
        MaJiang riverLastJiang = ShuffleMaJiang.river.get(ShuffleMaJiang.riverIndex-1);
        //遍历自己的所有的牌,是否包含上面的牌,并且有两张
        int frequency = Collections.frequency(playerMaJiangs, riverLastJiang);
        if (frequency>=2) {
            System.out.println("【碰牌成功】");
            //把碰的牌移除
            playerMaJiangs.remove(riverLastJiang);
            playerMaJiangs.remove(riverLastJiang);
            return;
        }else {
            System.out.println("【没有对应的两张牌,碰牌失败】");
        }
    } 

    /**
     * 杠牌:河里刚打出的牌,在玩家手中有3张同样的牌,就可以杠牌
     */
    public void barCards(){
        //获取河里刚打出的牌
        MaJiang riverLastJiang = ShuffleMaJiang.river.get(ShuffleMaJiang.riverIndex-1);
        //遍历自己的所有的牌,是否包含上面的牌,并且有两张
        int frequency = Collections.frequency(playerMaJiangs, riverLastJiang);
        if (frequency>=3) {
            System.out.println("【杠牌成功】");
            //把杠的牌移除
            playerMaJiangs.remove(riverLastJiang);
            playerMaJiangs.remove(riverLastJiang);
            playerMaJiangs.remove(riverLastJiang);
            return;
        }else {
            System.out.println("【没有对应的三张牌,杠牌失败】");
        }
    } 

    /**
     * 胡牌:满足胡牌的规则
     */
    public void huCards(){
        //难度较大,以后再研究
    }
}

4.4 洗牌

package com.wllfengshu.middleware;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.wllfengshu.bean.majiang.MaJiang;
import com.wllfengshu.bean.majiang.MaJiangFactory;
import com.wllfengshu.bean.majiang.MaJiangNumber;
import com.wllfengshu.bean.majiang.MaJiangWind;
/**
 * 洗牌
 */
public class ShuffleMaJiang {
    /**
     * 牌局中所有的牌:使用List放所有的牌
     */
    public static List maJiangs=new ArrayList();
    /**
     * 用来指示“牌局中所有的牌”的当前下标
     */
    public static int maJiangsIndex=0;
    /**
     * 河:用来存放玩家打出的牌
     */
    public static List river=new ArrayList();
    /**
     * 用来指示“河”的当前下标
     */
    public static int riverIndex=0;

    public ShuffleMaJiang() throws InterruptedException {
        //创建一副麻将
        createMaJiangs();
        //输出此时的所有的牌
        System.out.println("【初始化所有的牌:】");
        printMaJiangs(0);
        //把初始牌打乱
        chaosMaJiangs();
        //输出此时的所有的牌
        System.out.println("【洗牌后所有的牌:】");
        printMaJiangs(0);
        System.out.println("【按照东南西北四个方向输出的牌(牌局里的牌):】");
        printMaJiangs(1);
        //下标恢复
        riverIndex=0;
        maJiangsIndex=135;
    }

    /**
     * 创建一副麻将
     * @throws InterruptedException 
     */
    private void createMaJiangs() throws InterruptedException {
        //创建麻将的工厂
        MaJiangFactory maJiangFactory = new MaJiangFactory();
        //循环中的i用来把1到10代表的牌填入数组
        for (int i = 1; i <= 10 ; i++ ) {
            //对万、条、筒进行填入
            if (i<=3) {
                //循环中的j用来存字牌的数值
                for (int j = 1; j <= 9; j++) {
                    //循环中的g表示每种字牌有4张
                    for (int g = 1; g <= 4; g++) {
                        MaJiangNumber maJiangNumber=(MaJiangNumber) maJiangFactory.createMaJiang(i);
                        maJiangNumber.setNumber(j);
                        maJiangs.add(maJiangsIndex, maJiangNumber);
                        maJiangsIndex++;
                    }
                }
            //对 东、南、西、北、中、发、白进行填入
            }else {
                //循环中的g表示每种风牌有4张
                for (int g = 1; g <= 4; g++) {
                    MaJiangWind maJiangWind=(MaJiangWind) maJiangFactory.createMaJiang(i);
                    maJiangs.add(maJiangsIndex, maJiangWind);
                    maJiangsIndex++;
                }
            }
        }
        System.out.println();
        //睡一会,显得更加逼真
        Thread.sleep(100);
    }

    /**
     * 输出一副牌
     * @param direction 0表示输出为一行,1表示按照四个方位进行输出
     * @throws InterruptedException 
     */
    public void printMaJiangs(int direction) throws InterruptedException {
        for (int i=0;i//以下是按照方位输出
            if (direction==1) {
                if (i==0) {
                    System.out.print("【桌子东方(玩家)】");
                }else if(i==34){
                    System.out.print("\n【桌子南方(电脑)】");           
                }else if(i==68){
                    System.out.print("\n【桌子西方(电脑)】");
                }else if(i==102){
                    System.out.print("\n【桌子北方(电脑)】");
                }
            }
            MaJiang maJiangTemp=maJiangs.get(i);
            int type = maJiangTemp.getType();
            //输出字牌
            if (type<=3) {
                MaJiangNumber maJiangNumber=(MaJiangNumber)maJiangTemp;
                System.out.print(maJiangNumber+",");
            //输出风牌
            }else {
                MaJiangWind maJiangWind=(MaJiangWind)maJiangTemp;
                System.out.print(maJiangWind+",");
            }
        }
        System.out.println();
        //睡一会,显得更加逼真
        Thread.sleep(100);
    }

    /**
     * 把初始牌打乱
     */
    private void chaosMaJiangs(){
        Collections.shuffle(maJiangs);
    }

    /**
     * 由于第一次起牌很有可能是在整副牌的中间位置开始起牌的,然后再向后起牌。此时需要把起始位置前的牌,重新放到maJiangs中的最后,来保证整副牌的完整性
     * @throws InterruptedException 
     */
    public void moveMaJiangs() throws InterruptedException{
        //把开始位置前的牌复制到list的末尾
        for (int i = 0; i < maJiangsIndex; i++) {
            maJiangs.add(maJiangs.size(),maJiangs.get(i));
        }
        //复制后,把开始位置前的牌删除
        for (int i = 0; i < maJiangsIndex; i++) {
            maJiangs.remove(i);
        }
        //输出移动位置后的整副牌
        System.out.println("【移动位置后的整副牌:】");
        printMaJiangs(0);
        //移动过后,起始位置变为了第一张牌,需要把下标复位
        maJiangsIndex=0;
    }

    /**
     * 输出河里的牌
     * @throws InterruptedException 
     */
    public void printMaJiangsRiver() throws InterruptedException {
        for (int i=0;iint type = maJiangTemp.getType();
            //输出字牌
            if (type<=3) {
                MaJiangNumber maJiangNumber=(MaJiangNumber)maJiangTemp;
                System.out.print(maJiangNumber+",");
            //输出风牌
            }else {
                MaJiangWind maJiangWind=(MaJiangWind)maJiangTemp;
                System.out.print(maJiangWind+",");
            }
        }
        System.out.println();
        //睡一会,显得更加逼真
        Thread.sleep(100);
    }
}

4.4掷骰子

package com.wllfengshu.middleware;

import java.util.ArrayList;
import java.util.List;

import com.wllfengshu.bean.dice.Dice;

/**
 * 
 * @author Administrator
 * 掷骰子:掷两粒骰子
 */
public class HurlDice {
    /**
     * 骰子的所有数据都存在里面(2粒)
     */
    public static List dices=new ArrayList();

    /**
     * 两粒骰子
     */
    private int dice1Num,dice2Num;

    /**
     * 方向(在哪个方位开牌)
     */
    private int direction;

    /**
     * 指定方向中的某个位置开始起牌
     */
    private int place;

    public HurlDice() throws InterruptedException{
        //创建骰子
        createDices();
        //打印点数
        printDices();
        //获取方向:在哪个方位开牌
        getDirection();
        //获取指定方向中的某个位置开始起牌
        getPlace();
    }

    /**
     * 创建两粒骰子
     * @throws InterruptedException 
     */
    private void createDices() throws InterruptedException{
        //实例化两粒骰子
        Dice dice1=new Dice();
        Dice dice2=new Dice();
        //随机产生两粒骰子的点数
        dice1Num=(int)(Math.random()*6+1);
        Thread.sleep(100);//睡一会,防止产生的两个随机数相同的几率过高
        dice2Num=(int)(Math.random()*6+1);
        //设置第一粒骰子
        dice1.setNum(dice1Num);
        //设置第二粒骰子
        dice2.setNum(dice2Num);
        //把数据都存放到List中
        dices.add(dice1);
        dices.add(dice2);
    }

    /**
     * 打印两粒骰子的点数
     */
    private void printDices(){
        System.out.println("【骰子的点数:"+dice1Num+" , "+dice2Num+"】");
    }

    /**
     * 获取方向:direction (在哪个方位开牌)
     */
    private int getDirection(){
        //计算在哪个方向切牌
        direction=(dice1Num+dice2Num)%4;
        switch (direction) {
        case 0:
            System.out.println("【在东方起牌】");
            break;
        case 1:
            System.out.println("【在南方起牌】");
            break;
        case 2:
            System.out.println("【在西方起牌】");
            break;
        case 3:
            System.out.println("【在北方起牌】");
            break;
        }
        return direction;
    }

    /**
     * 获取指定方向中的某个位置开始起牌
     */
    private int getPlace(){
        //计算在上述方向中的某个位置开始起牌
        place=dice1Num"【起牌从距离该方向左边第"+place+"墩牌开始(一墩为两张牌)】");
        return place;
    }

    /**
     * 计算出从整副牌的什么位置开始起牌
     */
    public int getStartIndex(){
        //计算取牌的位置
        int startIndex=direction*(136/4)+place*2;
        System.out.println("【从整副牌的第"+startIndex+"张开始起牌】");
        return startIndex;
    }
}

4.6初始化玩家

package com.wllfengshu.middleware;

import java.util.ArrayList;
import java.util.List;

import com.wllfengshu.bean.player.Player;

/**
 * 
 * @author Administrator
 * 初始化玩家:创建四个玩家(包括3个电脑)
 */
public class InitPlayer {
    /**
     * 4个玩家的信息都存放在List中,下标为0是人,其余的为电脑
     */
    public static List players=new ArrayList();

    private Player player=null,computer1=null,computer2=null,computer3=null;

    public InitPlayer() {
        //创建4个玩家
        createPlayer();
    }

    /**
     * 创建4个玩家
     */
    private void createPlayer(){
        player = new Player();
        computer1 = new Player();
        computer2 = new Player();
        computer3 = new Player();
        player.setName("玩家");
        computer1.setName("电脑1");
        computer2.setName("电脑2");
        computer3.setName("电脑3");
        players.add(player);
        players.add(computer1);
        players.add(computer2);
        players.add(computer3);
    }

    /**
     * 输出四个玩家手中的牌
     */
    public void printPlayer(){
        //输出当前玩家手中的牌
        System.out.println("【当前玩家手中的牌如下:】");
        System.out.print("【玩家】");
        player.printMaJiangs();
        System.out.print("\n【电脑】");
        computer1.printMaJiangs();
        System.out.print("\n【电脑】");
        computer2.printMaJiangs();
        System.out.print("\n【电脑】");
        computer3.printMaJiangs();
        System.out.println();
    }

    /**
     * 第一次起牌:轮流起牌,每次起4张,一共起3轮
     */
    public void haveFirstBoard(){
        //共3轮
        for (int i = 0; i < 3; i++) {
            //玩家,每次起4张
            for (int j = 0; j < 4; j++) {
                player.gainMaJiang(ShuffleMaJiang.maJiangsIndex);
            }
            //电脑1,每次起4张
            for (int j = 0; j < 4; j++) {
                computer1.gainMaJiang(ShuffleMaJiang.maJiangsIndex);
            }
            //电脑2,每次起4张
            for (int j = 0; j < 4; j++) {
                computer2.gainMaJiang(ShuffleMaJiang.maJiangsIndex);
            }
            //电脑3,每次起4张
            for (int j = 0; j < 4; j++) {
                computer3.gainMaJiang(ShuffleMaJiang.maJiangsIndex);
            }
        }
    }

    /**
     * 第二次起牌:跳庄(玩家拿第1和第5张,电脑1拿第2张,电脑2拿第3张,电脑3拿第4张)
     */
    public void haveJumpBoard(){
        player.gainMaJiang(0);
        player.gainMaJiang(4);
        computer1.gainMaJiang(1);
        computer2.gainMaJiang(2);
        computer3.gainMaJiang(3);
    }

    /**
     * 翻癞子(癞子可以当成是任何一张牌)
     */
    public void haveWildBoard(){
        System.out.println("【癞子是:"+ShuffleMaJiang.maJiangs.get(5)+"】");
        //直接移除第6张牌
        ShuffleMaJiang.maJiangs.remove(5);
    }
}

4.7 游戏类

package com.wllfengshu.game;

import java.util.Scanner;
import java.util.regex.Pattern;

import com.wllfengshu.bean.player.Player;
import com.wllfengshu.middleware.HurlDice;
import com.wllfengshu.middleware.InitPlayer;
import com.wllfengshu.middleware.ShuffleMaJiang;

/**
 * 
 * @author Administrator
 * 游戏:整个的游戏流程
 */
public class Game {

    public static void main(String[] args) throws InterruptedException {
        @SuppressWarnings("resource")
        Scanner scanner=new Scanner(System.in);

        //初始化玩家
        InitPlayer initPlayer=null;

        //四个玩家
        Player player=null,computer1=null,computer2=null,computer3=null;

        //麻将
        ShuffleMaJiang shuffleMaJiang=null;

        //骰子
        HurlDice hurlDice=null;

        System.out.println("【欢迎开始“麻将”小游戏。请输入:[Y:开始游戏],[其他输入:退出游戏]】");
        String inputStart = scanner.nextLine();
        if ("Y".equalsIgnoreCase(inputStart)) {
            System.out.print("【开始初始化麻将桌...】");
            Thread.sleep(100);
            //洗牌
            shuffleMaJiang=new ShuffleMaJiang();
        }else {
            System.out.println("【游戏结束,再见!】");
            System.exit(0);
        }

        System.out.println("【初始化完毕,是否开始掷骰子?请输入:[Y:是],[其他输入:退出游戏]】");
        String inputDice = scanner.nextLine();
        if ("Y".equalsIgnoreCase(inputDice)) {
            //掷骰子
            hurlDice=new HurlDice();
        }else {
            System.out.println("【游戏结束,再见!】");
            System.exit(0);
        }

        System.out.println("【掷骰子完毕,是否开始第一次起牌(轮流起牌,每次起4张,一共起3轮)?请输入:[Y:是],[其他输入:退出游戏]】");
        String inputFirstBoard = scanner.nextLine();
        if ("Y".equalsIgnoreCase(inputFirstBoard)) {
            //计算出从整副牌的什么位置开始起牌
            int startIndex = hurlDice.getStartIndex();
            //设置整副牌的开始位置
            ShuffleMaJiang.maJiangsIndex=startIndex-1;
            //移动起始位置前的牌到list末尾
            shuffleMaJiang.moveMaJiangs();
            //玩家
            initPlayer = new InitPlayer();
            //第一次起牌
            initPlayer.haveFirstBoard();
            //输出此时玩家双手中的牌
            initPlayer.printPlayer();
            //输出牌局中的整副牌(剩余的牌)
            System.out.println("【此时牌局中的剩余的牌:】");
            shuffleMaJiang.printMaJiangs(0);
        }else {
            System.out.println("【游戏结束,再见!】");
            System.exit(0);
        }

        System.out.println("【第一次起牌完毕,是否开始跳庄(玩家拿第1和第5张,电脑1拿第2张,电脑2拿第3张,电脑3拿第4张)?请输入:[Y:是],[其他输入:退出游戏]】");
        String inputJumpBoard = scanner.nextLine();
        if ("Y".equalsIgnoreCase(inputJumpBoard)) {
            //第二次起牌:跳庄
            initPlayer.haveJumpBoard();
            //输出此时玩家双手中的牌
            initPlayer.printPlayer();
            //输出牌局中的整副牌(剩余的牌)
            System.out.println("【此时牌局中的剩余的牌:】");
            shuffleMaJiang.printMaJiangs(0);
        }else {
            System.out.println("【游戏结束,再见!】");
            System.exit(0);
        }

        System.out.println("【跳庄完毕,是否开始翻癞子(癞子可以当成是任何一张牌)?请输入:[Y:是],[其他输入:退出游戏]】");
        String inputWildBoard = scanner.nextLine();
        if ("Y".equalsIgnoreCase(inputWildBoard)) {
            //翻癞子
            initPlayer.haveWildBoard();
        }else {
            System.out.println("【游戏结束,再见!】");
            System.exit(0);
        }

        System.out.println("【您是庄家,请打一张牌。请输入:[待打出牌对应的顺序,例如:1表示打出第一张牌],[非数字输入:退出游戏]】");
        String inputdiscardBoard = scanner.nextLine();
        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
        if (pattern.matcher(inputdiscardBoard).matches()) {
            player=initPlayer.players.get(0);
            computer1=initPlayer.players.get(1);
            computer2=initPlayer.players.get(2);
            computer3=initPlayer.players.get(3);
            //打一张牌
            player.discardMaJiang(Integer.valueOf(inputdiscardBoard)-1);
            //输出此时玩家双手中的牌
            System.out.println("【此时玩家手中的牌:】");
            player.printMaJiangs();
            //输出河里的牌
            System.out.println("\n【河里牌:】");
            shuffleMaJiang.printMaJiangsRiver();
        }else {
            System.out.println("【游戏结束,再见!】");
            System.exit(0);
        }

        //以下是正式打麻将的逻辑,还存在很多问题
        while(true){
            //电脑起牌
            computer1.gainMaJiang(0);
            //电脑打出一张牌
            System.out.println("【电脑打出了:"+computer1.discardMaJiang(1)+"】");

            //玩家开始
            System.out.println("【开始打牌:请输入:[1:起牌],[2:打牌],[3:碰牌],[4:杠牌],[5:胡牌],[6:不做操作],[其他输入:退出游戏]】");
            String inputOperate = scanner.nextLine();
            if (shuffleMaJiang.maJiangs.size()==0) {
                System.out.println("【留局】");
                System.out.println("【游戏结束,再见!】");
                System.exit(0);
            }
            if ("1".equals(inputOperate)) {
                player.gainMaJiang(0);
            }else if("2".equals(inputOperate)) {
                player.discardMaJiang(0);
            }else if("3".equals(inputOperate)) {
                player.touchCards();
            }else if("4".equals(inputOperate)) {
                player.barCards();
            }else if("5".equals(inputOperate)) {
                player.huCards();
            }else if("6".equals(inputOperate)){
                //不做处理,继续下一次
                continue;
            }else {
                System.out.println("【游戏结束,再见!】");
                System.exit(0);
            }
        }
    }
}

5游戏玩法如下:

5.1是否开始游戏

java写的麻将小游戏_第4张图片

5.2是否掷骰子

java写的麻将小游戏_第5张图片

5.3第一轮起牌

java写的麻将小游戏_第6张图片

5.4跳庄

java写的麻将小游戏_第7张图片

5.5翻癞子

这里写图片描述

5.6打出一张牌

java写的麻将小游戏_第8张图片
(注:用户输入的是2,但是上图中显示打出的牌是第三张,是由于调用discarMaJiang方法时没有减掉1,list的下标是从0开始的,现在这个bug已经被修改了,并且代码中也是正确的,但是需要重新截图比较麻烦,就没有重新截图,请见谅)

6 分析

  • 麻将在洗牌完毕后的叠放是两层的,但是本程序中并没有使用二维数组,而是使用了一个List,原因之一是使用ArrayList的随机排序功能十分方便。另外,其实我们也可以把两层叠放的麻将看成是一维的,因为取牌(除庄家跳牌外)都是从上玩下的,而且这样做对于代码而言会更加方便,如下图:
    这里写图片描述

  • 本程序的List有如下这么多:
    (1)使用一个list表示整局麻将中所有的牌——名称为maJiangs;
    (2)使用一个list表示“河”,用来存放所有玩家打出的牌——名称为river;
    (3)每个玩家(包括3个电脑)都有一个list用来存放自己的牌——名称为playerMaJiangs;
    (4)四个玩家的实例都存放在一个list中——名称为players;
    (5)两粒骰子的信息都存放在一个list中——名称为dices;

  • 本程序实现了除胡牌外的全部功能,由于胡牌比较复杂就留着以后研究。另外本程序中也有很多代码不健壮性问题,例如,当玩家之外的人打牌还没有轮到玩家自己时,此时不应该显示“起牌和打牌”选项。本游戏现在只能按照正确的流程才能进行。

  • 本游戏没有界面,只能在控制台玩,后期需要添加上界面。本程序中的Game.java文件其实就是不断地调用其他类的方法,后期改为用户按钮点击事件再调用即可。

  • 本程序在架构方面存在一个问题,根据开发规范,bean中只能放属性和其对应地getter、setter、构造方法、toString方法。其余的代码应该放在业务逻辑层中。虽说本程序考虑了这个问题,但是感觉还是比较混乱,后期还需要修改。

7 总结

  • 总之,代码还存在许多的问题,但是通过此次开发,我学习到了如下:
    (1)系统架构的设计非常重要,严格按照开发规范进行开发非常重要;
    (2)学习了简单工厂的设计模式、单例的设计模式(学习了单例,但是感觉不适用就没用了)
    (3)熟练使用集合类的工具类Collections非常重要;
    (4)变量和方法的命名严格按照见名知意的原则非常重要;
    (5)提高代码健壮性非常重要;

你可能感兴趣的:(游戏)