您的位置:首页 > 编程语言 > Java开发

java写的麻将小游戏

2018-02-23 23:03 369 查看
过年回家在家打麻将,觉得蛮有趣的,就用java写了一个麻将小游戏(没有界面,只能在控制台玩)。

说明:

使用语言:java(jdk1.7)

开发工具:eclipse

项目集成:maven

1 麻将说明

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



1.2 规则说明

可以碰牌、杠牌

不能吃牌

有东西南北中发白

有癞子

可以自摸,可以放炮

其余的麻将知识请自行百度

2 架构图



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.wll
1a3f7
fengshu.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<MaJiang> playerMaJiangs=new ArrayList<MaJiang>();
/**
* 用来指示“每个玩家的牌”在playerMaJiangs中的下标
*/
private int playerMaJiangsIndex=0;

public String getName() {
return name;
}

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

public List<MaJiang> getPlayerMaJiangs() {
return playerMaJiangs;
}

public void setPlayerMaJiangs(List<MaJiang> 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<MaJiang> maJiangs=new ArrayList<MaJiang>();
/**
* 用来指示“牌局中所有的牌”的当前下标
*/
public static int maJiangsIndex=0;
/**
* 河:用来存放玩家打出的牌
*/
public static List<MaJiang> river=new ArrayList<MaJiang>();
/**
* 用来指示“河”的当前下标
*/
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<maJiangs.size();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;i<river.size();i++) {
MaJiang maJiangTemp=river.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);
}
}


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<Dice> dices=new ArrayList<Dice>();

/**
* 两粒骰子
*/
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<dice2Num?dice1Num:dice2Num;
System.out.println("【起牌从距离该方向左边第"+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<Player> players=new ArrayList<Player>();

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是否开始游戏



5.2是否掷骰子



5.3第一轮起牌



5.4跳庄



5.5翻癞子



5.6打出一张牌



(注:用户输入的是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)提高代码健壮性非常重要;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息