Java TCP通信 FastJson 在线纸牌游戏
主要想法
- 设计初衷:本作品名称叫做在线纸牌游戏。开发该作品的原因:在学习了JavaTCP与UDP网络编程的相关知识,以及对Java多线程知识比较感兴趣所以结合两者知识萌生了一个制作在线纸牌游戏的想法。
- 该作品的主要功能是:第一,在线即时信息聊天,具体表现为在游戏开始之前,玩家进入了相应的房间之后,玩家可以跟同在房间内的玩家进行聊天。第二,纸牌的玩法,与斗地主的规则类似,只不过本游戏的地主是随机分配,且三名玩家的牌的数量相同,最先出完的玩家赢得游戏的胜利。
- 主要用法:首先在云服务器上运行Server端,之后只要在本地终端或者java编辑器中运行Client端程序即可。游戏需要三名玩家在同一房间内才可以进行游戏。
- 借鉴产品:斗地主
- 创新点:
1.采用TCP封装Send和Receive方法,在方法传输上具有稳定和即时的特点 2.传输的信息封装以及解析采用了FastJson的数据序列化和反序列化方法。通过FastJson把程序中的Data对象转化为特定格式的Json字符串传输。其特点是有稳定性和速度极快。
概要设计
client:
Server:
人机交互:
核心代码部分
public static String getCardType(String[] cardSeparated){
if(!isConfirmed(cardSeparated)){
return WRONG_CARD;
}
int cardLength=cardSeparated.length;
switch (cardLength) {
case 1-> {
if (cardSeparated[0].equals(PASS)) {
return PASS;
} else {
return SINGLE;
}
}
case 2-> {
if (isSame(cardSeparated)) {
return PAIRS;
} else if (cardSeparated[0].equals(BIG_KING)
&& cardSeparated[1].equals(SMALL_KING)) {
return KING_BOMB;
} else {
return WRONG_CARD;
}
}
case 3-> {
if (isSame(cardSeparated)) {
return THREES;
} else {
return WRONG_CARD;
}
}
case 4-> {
if (isSame(cardSeparated)) {
return BOMB;
} else if (isSame(cardSeparated, 1, 3)
&& !cardSeparated[3].equals(SMALL_KING)
&& !cardSeparated[3].equals(BIG_KING)) {
return THREE_WITH_SINGLE;
} else {
return WRONG_CARD;
}
}
case 5,7-> {
if (isSame(cardSeparated, 1, 3)
&& isSame(cardSeparated, 4, 5)) {
return THREE_WITH_PAIRS;
} else if (isShunZi(cardSeparated, SINGLE_SHUN_ZI)) {
return SINGLE_SHUN_ZI;
} else {
return WRONG_CARD;
}
}
case 6,8-> {
if (isShunZi(cardSeparated, SINGLE_SHUN_ZI)) {
return SINGLE_SHUN_ZI;
} else if (isShunZi(cardSeparated, PAIRS_SHUN_ZI)) {
return PAIRS_SHUN_ZI;
} else {
return WRONG_CARD;
}
}
case 10-> {
if (isShunZi(cardSeparated, PAIRS_SHUN_ZI)) {
return PAIRS_SHUN_ZI;
}
}
}
return WRONG_CARD;
}
public static Data receive(){
String msgReceived = null;
try {
msgReceived =dis.readUTF();
} catch (IOException e) {
System.out.println("数据接受异常");
}
Data data= JSONObject.parseObject(msgReceived,Data.class);
return data;
}
public static void send(Data msgToBeSend){
if(msgToBeSend!=null){
try {
String msg=JSONObject.toJSONString(msgToBeSend);
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
System.out.println("连接异常!");
}
}
}
public void playCards() {
while (gameIsStart) {
dataReceived = playerMap.get(secondPlayer).getTransmit().receive();
if (dataReceived.getDataType().equals(Type.GAME_OVER)) {
playerMap.get(secondPlayer).sendToOther(dataReceived, this.getPlayerMap());
break;
} else if (dataReceived.getDataType().equals(Type.CARD_PLAY)) {
System.out.println("信息种类:" + dataReceived.getDataType() + " 房间号:" + this.roomNumber +
" 出牌人:" + dataReceived.getWhoSend() +
" 出牌类型:" + dataReceived.getCardType() + " 出牌内容:" + dataReceived.getDataText());
dataReceived.setMyTurn(false);
playerMap.get(firstPlayer).getTransmit().send(dataReceived);
dataReceived.setMyTurn(true);
playerMap.get(thirdPlayer).getTransmit().send(dataReceived);
}
dataReceived = playerMap.get(thirdPlayer).getTransmit().receive();
if (dataReceived.getDataType().equals(Type.GAME_OVER)) {
playerMap.get(secondPlayer).sendToOther(dataReceived, this.getPlayerMap());
break;
} else if (dataReceived.getDataType().equals(Type.CARD_PLAY)) {
System.out.println("信息种类:" + dataReceived.getDataType() + " 房间号:" + this.roomNumber +
" 出牌人:" + dataReceived.getWhoSend() +
" 出牌类型:" + dataReceived.getCardType() + " 出牌内容:" + dataReceived.getDataText());
dataReceived.setMyTurn(false);
playerMap.get(secondPlayer).getTransmit().send(dataReceived);
dataReceived.setMyTurn(true);
playerMap.get(firstPlayer).getTransmit().send(dataReceived);
}
dataReceived = playerMap.get(firstPlayer).getTransmit().receive();
if (dataReceived.getDataType().equals(Type.GAME_OVER)) {
playerMap.get(secondPlayer).sendToOther(dataReceived, this.getPlayerMap());
break;
} else if (dataReceived.getDataType().equals(Type.CARD_PLAY)) {
System.out.println("信息种类:" + dataReceived.getDataType() + " 房间号:" + this.roomNumber +
" 出牌人:" + dataReceived.getWhoSend() +
" 出牌类型:" + dataReceived.getCardType() + " 出牌内容:" + dataReceived.getDataText());
dataReceived.setMyTurn(true);
playerMap.get(secondPlayer).getTransmit().send(dataReceived);
dataReceived.setMyTurn(false);
playerMap.get(thirdPlayer).getTransmit().send(dataReceived);
}
}
}
主要测试
- 运行速度上:由TCP以及FastJson的保证,在信息传输和展示上速度快且准确率高。但是在一些特定场景,比如说牌的展示上,为了获得一些动态的效果,采用了sleep
- 安全性: 安全性较低,在一些不确定场景会出现线程安全问题,因为本人对线程类知识匮乏,所以在一些特定场景下存在较多线程安全的问题。
- 部署方便性:部署较为方便合理,只需要在服务器上运行Server程序,之后在本地终端上运行Client程序即可
- 可用性:房间复用性较差(作者尝试解决但是未果)。房间只能一次性使用,即一个服务端的开启最多支持五轮游戏。
更多图片
使用方法
|