• 第二十三章《斗地主游戏》第3节:项目完整代码


    对于初学者来说,斗地主游戏是一个比较复杂的项目,它涉及的类很多,以下是这个项目所有类的源代码,源码中有两个Main.java文件,它们虽然文件名称相同,但位于不同的包下,读者在复制粘贴这两个文件时需要注意要把它们放在正确的位置。

    Message.java

    1. package client.model;
    2. import java.io.*;
    3. import java.util.*;
    4. public class Message implements Serializable {
    5. private int typeid; //消息类型
    6. private int playerid; //玩家id
    7. private String content; //消息内容
    8. private List pokers = new ArrayList(); //扑克列表
    9. public int getTypeid() {
    10. return typeid;
    11. }
    12. public void setTypeid(int typeid) {
    13. this.typeid = typeid;
    14. }
    15. public int getPlayerid() {
    16. return playerid;
    17. }
    18. public void setPlayerid(int playerid) {
    19. this.playerid = playerid;
    20. }
    21. public String getContent() {
    22. return content;
    23. }
    24. public void setContent(String content) {
    25. this.content = content;
    26. }
    27. public List getPokers() {
    28. return pokers;
    29. }
    30. public void setPokers(List pokers) {
    31. this.pokers = pokers;
    32. }
    33. public Message() {
    34. }
    35. public Message(int typeid, int playerid, String content, List pokers) {
    36. this.typeid = typeid;
    37. this.playerid = playerid;
    38. this.content = content;
    39. this.pokers = pokers;
    40. }
    41. }

    Player.java

    1. package client.model;
    2. import java.io.*;
    3. import java.net.*;
    4. import java.util.*;
    5. //玩家类
    6. public class Player implements Serializable {
    7. private int id; //玩家id
    8. private String name; //玩家姓名
    9. private Socket socket; //玩家对应的socket
    10. private List pokers=new ArrayList();//玩家的扑克列表
    11. public int getId() {
    12. return id;
    13. }
    14. public void setId(int id) {
    15. this.id = id;
    16. }
    17. public String getName() {
    18. return name;
    19. }
    20. public void setName(String name) {
    21. this.name = name;
    22. }
    23. public Socket getSocket() {
    24. return socket;
    25. }
    26. public void setSocket(Socket socket) {
    27. this.socket = socket;
    28. }
    29. public List getPokers() {
    30. return pokers;
    31. }
    32. public void setPokers(List pokers) {
    33. this.pokers = pokers;
    34. }
    35. public Player()
    36. {
    37. }
    38. public Player(int id,String name,Socket socket,List pokers)
    39. {
    40. this.id=id;
    41. this.name=name;
    42. this.socket=socket;
    43. this.pokers=pokers;
    44. }
    45. public Player(int id)
    46. {
    47. this.id=id;
    48. }
    49. public Player(int id,String name)
    50. {
    51. this.id=id;
    52. this.name=name;
    53. }
    54. public Player(int id,String name,List pokers)
    55. {
    56. this.id=id;
    57. this.name=name;
    58. this.pokers=pokers;
    59. }
    60. public String toString()
    61. {
    62. return "player[id:"+this.id+"name:"+this.name+"]";
    63. }
    64. }

    Poker.java

    1. package client.model;
    2. import javax.swing.text.html.HTMLDocument.HTMLReader.IsindexAction;
    3. //扑克类
    4. public class Poker {
    5. private int id; //扑克id
    6. private String name;//扑克名称
    7. private int num; //扑克数量
    8. private boolean isOut; //扑克是否打出
    9. public boolean isOut() {
    10. return isOut;
    11. }
    12. public void setOut(boolean isOut) {
    13. this.isOut = isOut;
    14. }
    15. public int getId() {
    16. return id;
    17. }
    18. public void setId(int id) {
    19. this.id = id;
    20. }
    21. public String getName() {
    22. return name;
    23. }
    24. public void setName(String name) {
    25. this.name = name;
    26. }
    27. public int getNum() {
    28. return num;
    29. }
    30. public void setNum(int num) {
    31. this.num = num;
    32. }
    33. public Poker()
    34. {}
    35. public Poker(int id,String name,int num)
    36. {
    37. this.id=id;
    38. this.name=name;
    39. this.num=num;
    40. }
    41. public Poker(int id,String name,int num,boolean isOut)
    42. {
    43. this.id=id;
    44. this.name=name;
    45. this.num=num;
    46. this.isOut=isOut;
    47. }
    48. }

    PokerLabel.java

    1. package client.model;
    2. import javax.swing.*;
    3. //扑克标签类
    4. public class PokerLabel extends JLabel implements Comparable{
    5. private int id;
    6. private String name;
    7. private int num;
    8. private boolean isOut;
    9. private boolean isUp;
    10. private boolean isSelected; //是否选中
    11. public boolean isSelected() {
    12. return isSelected;
    13. }
    14. public void setSelected(boolean isSelected) {
    15. this.isSelected = isSelected;
    16. }
    17. public int getId() {
    18. return id;
    19. }
    20. public void setId(int id) {
    21. this.id = id;
    22. }
    23. public String getName() {
    24. return name;
    25. }
    26. public void setName(String name) {
    27. this.name = name;
    28. }
    29. public int getNum() {
    30. return num;
    31. }
    32. public void setNum(int num) {
    33. this.num = num;
    34. }
    35. public boolean isOut() {
    36. return isOut;
    37. }
    38. public void setOut(boolean isOut) {
    39. this.isOut = isOut;
    40. }
    41. public boolean isUp() {
    42. return isUp;
    43. }
    44. public void setUp(boolean isUp) {
    45. this.isUp = isUp;
    46. }
    47. public PokerLabel()
    48. {
    49. this.setSize(105, 150);
    50. }
    51. public PokerLabel(int id,String name,int num)
    52. {
    53. this.id=id;
    54. this.name=name;
    55. this.num=num;
    56. this.setSize(105, 150);
    57. }
    58. public PokerLabel(int id,String name,int num,boolean isOut,boolean isUp)
    59. {
    60. this.id=id;
    61. this.name=name;
    62. this.num=num;
    63. this.isOut=isOut;
    64. this.isUp=isUp;
    65. if(isUp)
    66. turnUp();
    67. else {
    68. turnDown();
    69. }
    70. this.setSize(105, 150);
    71. }
    72. public void turnUp()
    73. {
    74. this.setIcon(new ImageIcon("images/poker/"+id+".jpg"));
    75. }
    76. public void turnDown()
    77. {
    78. this.setIcon(new ImageIcon("images/poker/down.jpg"));
    79. }
    80. @Override
    81. public int compareTo(Object arg0) {
    82. PokerLabel pokerLabel=(PokerLabel)arg0;
    83. if(this.num>pokerLabel.num)
    84. return 1;
    85. else if(this.num
    86. return -1;
    87. else
    88. return 0;
    89. }
    90. }

    ChuPaiThread.java

    1. package client.thread;
    2. import java.util.*;
    3. import com.alibaba.fastjson.JSON;
    4. import client.model.*;
    5. import client.view.*;
    6. public class ChuPaiThread extends Thread {
    7. private int time;
    8. private MainFrame mainFrame;
    9. private boolean isRun;
    10. public int getTime() {
    11. return time;
    12. }
    13. public void setTime(int time) {
    14. this.time = time;
    15. }
    16. public MainFrame getMainFrame() {
    17. return mainFrame;
    18. }
    19. public void setMainFrame(MainFrame mainFrame) {
    20. this.mainFrame = mainFrame;
    21. }
    22. public boolean isRun() {
    23. return isRun;
    24. }
    25. public void setRun(boolean isRun) {
    26. this.isRun = isRun;
    27. }
    28. public ChuPaiThread(int time, MainFrame mainFrame) {
    29. isRun = true;
    30. this.time = time;
    31. this.mainFrame = mainFrame;
    32. }
    33. public void run() {
    34. while (time >= 0 && isRun) {
    35. mainFrame.timeLabel.setText(time + "");
    36. time--;
    37. try {
    38. Thread.sleep(1000);
    39. } catch (InterruptedException e) {
    40. // TODO Auto-generated catch block
    41. e.printStackTrace();
    42. }
    43. }
    44. Message message = null;
    45. //如果是不出 (一种是时间到了 一种是 选择不出)
    46. if (time == -1 || isRun == false && mainFrame.isOut == false) {
    47. //时间到了不出,则将出牌按钮隐藏
    48. mainFrame.chupaiJLabel.setVisible(false);
    49. mainFrame.buchuJLabel.setVisible(false);
    50. mainFrame.timeLabel.setVisible(false);
    51. message = new Message(3, mainFrame.currentPlayer.getId(), "不出", null);
    52. //转换为json 交给 sendThread发送到服务器去
    53. String msg = JSON.toJSONString(message);
    54. mainFrame.sendThread.setMsg(msg);
    55. }
    56. //出牌
    57. if (isRun == false && mainFrame.isOut == true) {
    58. message = new Message(4, mainFrame.currentPlayer.getId(), "出牌",
    59. changePokerLableToPoker(mainFrame.selectedPokerLabels));
    60. //转换为json 交给 sendThread发送到服务器去
    61. String msg = JSON.toJSONString(message);
    62. mainFrame.sendThread.setMsg(msg);
    63. //将当前发送出去的扑克牌 从扑克牌列表中移除
    64. mainFrame.removeOutPokerFromPokerList();
    65. //如果扑克列表的数量为0 代表赢了
    66. if (mainFrame.pokerLabels.size() == 0) {
    67. //产生游戏结束的消息
    68. message = new Message(5, mainFrame.currentPlayer.getId(),
    69. "游戏结束", null);
    70. msg = JSON.toJSONString(message);
    71. try {
    72. Thread.sleep(100);
    73. //发送消息
    74. mainFrame.sendThread.setMsg(msg);
    75. } catch (InterruptedException e) {
    76. e.printStackTrace();
    77. }
    78. }
    79. }
    80. }
    81. public List changePokerLableToPoker(List selectedPokerLabels) {
    82. List list = new ArrayList();
    83. for (int i = 0; i < selectedPokerLabels.size(); i++) {
    84. PokerLabel pokerLabel = selectedPokerLabels.get(i);
    85. Poker poker = new Poker(pokerLabel.getId(), pokerLabel.getName(),
    86. pokerLabel.getNum());
    87. list.add(poker);
    88. }
    89. return list;
    90. }
    91. }

    CountThread.java

    1. package client.thread;
    2. import com.alibaba.fastjson.JSON;
    3. import client.model.*;
    4. import client.view.*;
    5. //计时器的线程
    6. public class CountThread extends Thread{
    7. private int i;
    8. private MainFrame mainFrame;
    9. private boolean isRun;
    10. public boolean isRun() {
    11. return isRun;
    12. }
    13. public void setRun(boolean isRun) {
    14. this.isRun = isRun;
    15. }
    16. public CountThread(int i,MainFrame mainFrame)
    17. {
    18. isRun=true;
    19. this.i=i;
    20. this.mainFrame=mainFrame;
    21. }
    22. public void run()
    23. {
    24. while(i>=0 && isRun)
    25. {
    26. mainFrame.timeLabel.setText(i+"");
    27. i--;
    28. try {
    29. Thread.sleep(1000);
    30. } catch (InterruptedException e) {
    31. e.printStackTrace();
    32. }
    33. }
    34. Message msg=null;
    35. //时间到了 或者 点击过不抢地主的按钮了
    36. if(i==-1 || isRun==false && mainFrame.isLord==false)
    37. {
    38. msg=new Message(1,mainFrame.currentPlayer.getId(),
    39. "不抢",null);
    40. }
    41. //点了抢地主的按钮了
    42. if(isRun==false && mainFrame.isLord==true)
    43. {
    44. msg=new Message(2,mainFrame.currentPlayer.getId(),
    45. "抢地主",null);
    46. }
    47. //将消息传到服务器端
    48. mainFrame.sendThread.setMsg(JSON.toJSONString(msg));
    49. }
    50. }

    ReceiveThread.java

    1. package client.thread;
    2. import java.awt.*;
    3. import javax.swing.*;
    4. import java.io.*;
    5. import java.net.*;
    6. import java.util.*;
    7. import com.alibaba.fastjson.*;
    8. import client.model.*;
    9. import client.view.*;
    10. //创建一个接收消息的线程
    11. public class ReceiveThread extends Thread {
    12. private Socket socket;
    13. private MainFrame mainFrame;
    14. private int step = 0;
    15. private boolean isRun = true;
    16. public boolean isRun() {
    17. return isRun;
    18. }
    19. public void setRun(boolean isRun) {
    20. this.isRun = isRun;
    21. }
    22. public ReceiveThread(Socket socket, MainFrame mainFrame) {
    23. this.socket = socket;
    24. this.mainFrame = mainFrame;
    25. }
    26. public void run() {
    27. try {
    28. DataInputStream dataInputStream =
    29. new DataInputStream(socket.getInputStream());
    30. while (true) {
    31. if (isRun == false)
    32. break;
    33. //接收从服务器端传递过来的消息 json字符串
    34. String jsonString = dataInputStream.readUTF();
    35. if (step == 0) {
    36. java.util.List players = new ArrayList();
    37. //System.out.println(jsonString);
    38. //解析json字符串 "[{},{}]" [{},{}]
    39. //将json字符串转换为json数组
    40. JSONArray playerJsonArray = JSONArray.parseArray(jsonString);
    41. for (int i = 0; i < playerJsonArray.size(); i++) {
    42. //获得当个json对象--> 玩家对象
    43. JSONObject playerJson = (JSONObject) playerJsonArray.get(i);
    44. int id = playerJson.getInteger("id");
    45. String name = playerJson.getString("name");
    46. //存放扑克列表
    47. java.util.List pokers = new ArrayList();
    48. JSONArray pokerJsonArray =
    49. playerJson.getJSONArray("pokers");
    50. for (int j = 0; j < pokerJsonArray.size(); j++) {
    51. // 每循环一次 获得一个扑克对象
    52. JSONObject pokerJSon = (JSONObject) pokerJsonArray.get(j);
    53. int pid = pokerJSon.getInteger("id");
    54. String pname = pokerJSon.getString("name");
    55. int num = pokerJSon.getInteger("num");
    56. Poker poker = new Poker(pid, pname, num);
    57. pokers.add(poker);
    58. }
    59. Player player = new Player(id, name, pokers);
    60. players.add(player);
    61. }
    62. //获得3个玩家的信息了
    63. if (players.size() == 3) {
    64. mainFrame.showAllPlayersInfo(players);
    65. step = 1; //玩家到齐 进展到第二步
    66. }
    67. } else if (step == 1) {
    68. //接收抢地主的消息或者出牌的消息
    69. JSONObject msgJsonObject = JSONObject.parseObject(jsonString);
    70. //解析消息对象
    71. int typeid = msgJsonObject.getInteger("typeid");
    72. int playerid = msgJsonObject.getInteger("playerid");
    73. String contentString = msgJsonObject.getString("content");
    74. //消息类型为不抢
    75. if (typeid == 1) {
    76. //1.主窗口显示不抢的信息
    77. mainFrame.showMsg(playerid, 1);
    78. //2.设置下一家开始抢地主
    79. if (playerid + 1 == mainFrame.currentPlayer.getId())
    80. mainFrame.getLord();
    81. }
    82. //抢地主的消息
    83. if (typeid == 2) {
    84. //获得地主牌
    85. JSONArray pokersJsonArray =
    86. msgJsonObject.getJSONArray("pokers");
    87. java.util.List lordPokers = new ArrayList();
    88. for (int i = 0; i < pokersJsonArray.size(); i++) {
    89. JSONObject pokerJsonObject = (JSONObject) pokersJsonArray.get(i);
    90. int id = pokerJsonObject.getInteger("id");
    91. String name = pokerJsonObject.getString("name");
    92. int num = pokerJsonObject.getInteger("num");
    93. Poker p = new Poker(id, name, num);
    94. System.out.println(p);
    95. lordPokers.add(p);
    96. }
    97. //如果是自己抢的地主
    98. if (mainFrame.currentPlayer.getId() == playerid) {
    99. //添加地主牌
    100. mainFrame.addLordPokers(lordPokers);
    101. //第一家出牌 显示出牌的按钮
    102. mainFrame.showChuPaiJabel();
    103. }
    104. //显示地主图标
    105. mainFrame.showLordIcon(playerid);
    106. //之前的消息框隐藏
    107. mainFrame.msgLabel.setVisible(false);
    108. //所有玩家 都可以选择出牌列表 (不代表能出牌)
    109. mainFrame.addClickEventToPoker();
    110. }
    111. if (typeid == 3) //不出牌
    112. {
    113. //显示不出牌的消息
    114. mainFrame.showMsg(playerid, 3);
    115. //判断自己是不是下一家 如果是 显示出牌按钮 0->1 1-> 2 2-> 0
    116. if (playerid + 1 == mainFrame.currentPlayer.getId() ||
    117. playerid - 2 == mainFrame.currentPlayer.getId()) {
    118. mainFrame.showChuPaiJabel();
    119. }
    120. }
    121. if (typeid == 4) //出牌
    122. {
    123. //获得出牌列表
    124. JSONArray pokersJsonArray =
    125. msgJsonObject.getJSONArray("pokers");
    126. java.util.List outPokers = new ArrayList();
    127. for (int i = 0; i < pokersJsonArray.size(); i++) {
    128. JSONObject pokerJsonObject = (JSONObject) pokersJsonArray.get(i);
    129. int id = pokerJsonObject.getInteger("id");
    130. String name = pokerJsonObject.getString("name");
    131. int num = pokerJsonObject.getInteger("num");
    132. Poker p = new Poker(id, name, num);
    133. System.out.println(p);
    134. outPokers.add(p);
    135. }
    136. //显示出牌列表
    137. mainFrame.showOutPokerList(playerid, outPokers);
    138. //判断自己是不是下一家 如果是 显示出牌按钮 0->1 1-> 2 2-> 0
    139. if (playerid + 1 == mainFrame.currentPlayer.getId() ||
    140. playerid - 2 == mainFrame.currentPlayer.getId()) {
    141. mainFrame.showChuPaiJabel();
    142. }
    143. mainFrame.prevPlayerid = playerid; //记录上一个出牌的玩家id
    144. }
    145. //如果是游戏结束的消息
    146. if (typeid == 5) {
    147. if (playerid == mainFrame.currentPlayer.getId()) {
    148. JOptionPane.showMessageDialog(mainFrame, "赢了");
    149. } else {
    150. JOptionPane.showMessageDialog(mainFrame, "输了");
    151. }
    152. //游戏结束 关闭线程 清理窗口等
    153. mainFrame.gameOver();
    154. }
    155. }
    156. }
    157. } catch (IOException e) {
    158. // TODO Auto-generated catch block
    159. e.printStackTrace();
    160. }
    161. }
    162. }

    SendThread.java

    1. package client.thread;
    2. import java.io.*;
    3. import java.net.Socket;
    4. //发送消息的线程
    5. public class SendThread extends Thread {
    6. private String msg;
    7. public String getMsg() {
    8. return msg;
    9. }
    10. public void setMsg(String msg) {
    11. this.msg = msg;
    12. }
    13. private Socket socket;
    14. public Socket getSocket() {
    15. return socket;
    16. }
    17. public void setSocket(Socket socket) {
    18. this.socket = socket;
    19. }
    20. private boolean isRun = true;
    21. public boolean isRun() {
    22. return isRun;
    23. }
    24. public void setRun(boolean isRun) {
    25. this.isRun = isRun;
    26. }
    27. public SendThread(Socket socket) {
    28. this.socket = socket;
    29. }
    30. public SendThread(Socket socket, String msg) {
    31. this.socket = socket;
    32. this.msg = msg;
    33. }
    34. public SendThread() {
    35. }
    36. public void run() {
    37. DataOutputStream dataOutputStream;
    38. try {
    39. dataOutputStream = new DataOutputStream(socket.getOutputStream());
    40. while (true) {
    41. if (isRun == false) {
    42. break;
    43. }
    44. //如果消息不为null
    45. if (msg != null) {
    46. System.out.println("消息在发送中:" + msg);
    47. //发送消息
    48. dataOutputStream.writeUTF(msg);
    49. //消息发送完毕 消息内容清空
    50. msg = null;
    51. }
    52. Thread.sleep(50); //暂停 等待新消息进来
    53. }
    54. } catch (IOException e) {
    55. e.printStackTrace();
    56. } catch (InterruptedException e) {
    57. e.printStackTrace();
    58. }
    59. }
    60. }

    GameUtil.java

    1. package client.util;
    2. import client.model.*;
    3. public class GameUtil {
    4. public static void move(PokerLabel pokerLabel,int x,int y)
    5. {
    6. pokerLabel.setLocation(x, y);
    7. try {
    8. Thread.sleep(50);
    9. } catch (InterruptedException e) {
    10. e.printStackTrace();
    11. }
    12. }
    13. public static void move2(PokerLabel pokerLabel,int x,int y)
    14. {
    15. pokerLabel.setLocation(x, y);
    16. }
    17. }

    PokerRule.java

    1. package client.util;
    2. import java.util.*;
    3. import client.model.*;
    4. public class PokerRule {
    5. //判断牌型
    6. public static PokerType checkPokerType(List list) {
    7. Collections.sort(list);
    8. int count = list.size();
    9. if (count == 1) {
    10. //单张
    11. return PokerType.p_1;
    12. } else if (count == 2) {
    13. //对子
    14. if (isSame(list, count)) {
    15. return PokerType.p_2;
    16. }
    17. //王炸
    18. if (isWangZha(list)) {
    19. return PokerType.p_2w;
    20. }
    21. return PokerType.p_error;
    22. } else if (count == 3) {
    23. //三个头
    24. if (isSame(list, count)) {
    25. return PokerType.p_3;
    26. }
    27. return PokerType.p_error;
    28. } else if (count == 4) {
    29. //炸弹
    30. if (isSame(list, count)) {
    31. return PokerType.p_4;
    32. }
    33. //三带一
    34. if (isSanDaiYi(list)) {
    35. return PokerType.p_31;
    36. }
    37. return PokerType.p_error;
    38. } else if (count >= 5) {
    39. //顺子
    40. if (isShunZi(list)) {
    41. return PokerType.p_n;
    42. } else if (isSanDaiYiDui(list)) {
    43. //三代一对
    44. return PokerType.p_32;
    45. } else if (isLianDui(list)) {
    46. //连对
    47. return PokerType.p_1122;
    48. } else if (isFeiJI(list)) {
    49. //双飞or双飞双带
    50. return PokerType.p_111222;
    51. } else if (isFeiJIDaiChiBang1(list)) {
    52. //双飞or双飞双带
    53. return PokerType.p_11122234;
    54. } else if (isFeiJIDaiChiBang2(list)) {
    55. //双飞or双飞双带
    56. return PokerType.p_1112223344;
    57. }
    58. }
    59. return PokerType.p_error;
    60. }
    61. public static boolean isWangZha(List list) {
    62. if ((list.get(0).getNum() == 16 && list.get(1).getNum() == 17) ||
    63. (list.get(0).getNum() == 17 && list.get(1).getNum() == 16)) {
    64. return true;
    65. }
    66. return false;
    67. }
    68. //判断list内扑克是否相同
    69. public static boolean isSame(List list, int count) {
    70. for (int j = 0; j < count - 1; j++) {
    71. int a = list.get(j).getNum();
    72. int b = list.get(j + 1).getNum();
    73. if (a != b) {
    74. return false;
    75. }
    76. }
    77. return true;
    78. }
    79. //判断是否是三带一
    80. public static boolean isSanDaiYi(List list) {
    81. List temp = new ArrayList();
    82. temp.addAll(list);
    83. if (isSame(temp, 3)) {
    84. return true;
    85. }
    86. temp.remove(0);
    87. if (isSame(temp, 3)) {
    88. return true;
    89. }
    90. return false;
    91. }
    92. //判断是否是三带一对
    93. public static boolean isSanDaiYiDui(List list) {
    94. List temp = new ArrayList();
    95. temp.addAll(list);
    96. if (temp.size() == 5) {
    97. if (isSame(temp, 3)) {
    98. temp.remove(0);
    99. temp.remove(0);
    100. temp.remove(0);
    101. if (isSame(temp, 2)) {
    102. return true;
    103. }
    104. return false;
    105. }
    106. if (isSame(temp, 2)) {
    107. temp.remove(0);
    108. temp.remove(0);
    109. if (isSame(temp, 3)) {
    110. return true;
    111. }
    112. return false;
    113. }
    114. }
    115. return false;
    116. }
    117. // 判断是否是顺子
    118. public static boolean isShunZi(List list) {
    119. for (int i = 0; i < list.size() - 1; i++) {
    120. int a = list.get(i).getNum();
    121. int b = list.get(i + 1).getNum();
    122. if (b - a != 1) {
    123. return false;
    124. }
    125. }
    126. return true;
    127. }
    128. // 判断是否是连对
    129. public static boolean isLianDui(List list) {
    130. int size = list.size();
    131. if (size < 6 && size % 2 != 0) {
    132. return false;
    133. }
    134. for (int i = 0; i < size; i++) {
    135. int a = list.get(i).getNum();
    136. int b = list.get(i + 1).getNum();
    137. if (a != b) {
    138. return false;
    139. }
    140. i++;
    141. }
    142. for (int i = 0; i < size; i++) {
    143. int a = list.get(i).getNum();
    144. int b = list.get(i + 2).getNum();
    145. if (b - a != 1) {
    146. return false;
    147. }
    148. i++;
    149. i++;
    150. }
    151. return true;
    152. }
    153. //判断是不是双飞
    154. public static boolean isFeiJI(List list) {
    155. List count = feiCount(list);
    156. if (count != null && count.size() >= 2) {
    157. int len = count.size();
    158. for (int i = 0; i < len - 1; i++) {
    159. if (count.get(i + 1) - count.get(i) != 1) {
    160. return false;
    161. }
    162. }
    163. int dui = feiDuiCount(list, count);
    164. if (dui == 0) {
    165. return true;
    166. }
    167. }
    168. return false;
    169. }
    170. //飞机带翅膀 3311
    171. public static boolean isFeiJIDaiChiBang2(List list) {
    172. List feiji = feiCount(list);
    173. if (feiji != null && feiji.size() >= 2) {
    174. int len = feiji.size();
    175. for (int i = 0; i < len - 1; i++) {
    176. if (feiji.get(i + 1) - feiji.get(i) != 1) {
    177. return false;
    178. }
    179. }
    180. int dui = feiDuiCount(list, feiji);
    181. if (dui == feiji.size()) {
    182. return true;
    183. }
    184. }
    185. return false;
    186. }
    187. //飞机带翅膀3322
    188. public static boolean isFeiJIDaiChiBang1(List list) {
    189. List feiji = feiCount(list);
    190. if (feiji != null && feiji.size() >= 2) {
    191. int len = feiji.size();
    192. for (int i = 0; i < len - 1; i++) {
    193. if (feiji.get(i + 1) - feiji.get(i) != 1) {
    194. return false;
    195. }
    196. }
    197. int dui = feiDanZhangCount(list, feiji);
    198. if (dui == feiji.size()) {
    199. return true;
    200. }
    201. }
    202. return false;
    203. }
    204. //判断三个头有几个
    205. public static List feiCount(List list) {
    206. List cnt = new ArrayList();
    207. for (int i = 0; i < list.size() - 2; i++) {
    208. int a = list.get(i).getNum();
    209. int b = list.get(i + 1).getNum();
    210. int c = list.get(i + 2).getNum();
    211. if (a == b && a == c) {
    212. cnt.add(a);
    213. }
    214. }
    215. return cnt;
    216. }
    217. // 判断双飞中对子有几个
    218. public static int feiDuiCount(List list,
    219. List feiji) {
    220. List temp = new ArrayList();
    221. temp.addAll(list);
    222. int cnt = 0;
    223. for (int i = 0; i < temp.size(); i++) {
    224. for (int j = 0; j < feiji.size(); j++) {
    225. int a = list.get(i).getNum();
    226. if (a == feiji.get(j)) {
    227. temp.remove(i);
    228. }
    229. }
    230. }
    231. int size = temp.size();
    232. if (size > 0 && size % 2 == 0) {
    233. for (int i = 0; i < temp.size() - 1; i++) {
    234. int a = list.get(i).getNum();
    235. int b = list.get(i + 1).getNum();
    236. if (a == b) {
    237. cnt++;
    238. }
    239. }
    240. }
    241. return cnt;
    242. }
    243. //判断双飞中单张有几个
    244. public static int feiDanZhangCount(List list,
    245. List feiji) {
    246. List temp = new ArrayList();
    247. temp.addAll(list);
    248. int cnt = 0;
    249. for (int i = 0; i < temp.size(); i++) {
    250. for (int j = 0; j < feiji.size(); j++) {
    251. int a = list.get(i).getNum();
    252. if (a == feiji.get(j)) {
    253. temp.remove(i);
    254. }
    255. }
    256. }
    257. int size = temp.size();
    258. if (size > 0) {
    259. for (int i = 0; i < temp.size() - 1; i++) {
    260. int a = list.get(i).getNum();
    261. int b = list.get(i + 1).getNum();
    262. if (a != b) {
    263. cnt++;
    264. }
    265. }
    266. }
    267. return cnt;
    268. }
    269. //判断是否符合出牌规则,即根据上家牌面判断本次出牌是否合规
    270. public static boolean legal(List prevList,
    271. List currentList) {
    272. // 首先判断牌型是不是一样
    273. PokerType paiXing = checkPokerType(prevList);
    274. if (paiXing.equals(checkPokerType(currentList))) {
    275. // 根据牌型来判断大小
    276. if (PokerType.p_1.equals(paiXing)) {
    277. // 单张
    278. if (compareLast(prevList, currentList)) {
    279. return true;
    280. }
    281. return false;
    282. } else if (PokerType.p_2w.equals(paiXing)) {
    283. // 王炸
    284. return false;
    285. } else if (PokerType.p_2.equals(paiXing)) {
    286. // 对子
    287. if (compareLast(prevList, currentList)) {
    288. return true;
    289. }
    290. return false;
    291. } else if (PokerType.p_3.equals(paiXing)) {
    292. // 三张
    293. if (compareLast(prevList, currentList)) {
    294. return true;
    295. }
    296. return false;
    297. } else if (PokerType.p_31.equals(paiXing)) {
    298. // 三带一
    299. if (compareLast(prevList, currentList)) {
    300. return true;
    301. }
    302. return false;
    303. } else if (PokerType.p_32.equals(paiXing)) {
    304. // 三带一对
    305. if (compare(prevList, currentList)) {
    306. return true;
    307. }
    308. return false;
    309. } else if (PokerType.p_4.equals(paiXing)) {
    310. // 炸弹
    311. if (compareLast(prevList, currentList)) {
    312. return true;
    313. }
    314. return false;
    315. } else if (PokerType.p_n.equals(paiXing)) {
    316. // 顺子
    317. if (compareLast(prevList, currentList)) {
    318. return true;
    319. }
    320. return false;
    321. } else if (PokerType.p_1122.equals(paiXing)) {
    322. // 连对
    323. if (compareLast(prevList, currentList)) {
    324. return true;
    325. }
    326. return false;
    327. } else if (PokerType.p_111222.equals(paiXing)) {
    328. // 双飞
    329. if (compare(prevList, currentList)) {
    330. return true;
    331. }
    332. return false;
    333. } else if (PokerType.p_11122234.equals(paiXing)) {
    334. // 飞机带翅膀(单张)
    335. if (compare(prevList, currentList)) {
    336. return true;
    337. }
    338. return false;
    339. } else if (PokerType.p_1112223344.equals(paiXing)) {
    340. // 飞机带翅膀(对子)
    341. if (compare(prevList, currentList)) {
    342. return true;
    343. }
    344. return false;
    345. }
    346. } else if (currentList.size() == 2) {
    347. //判断是不是王炸
    348. if (isWangZha(currentList)) {
    349. return true;
    350. }
    351. return false;
    352. } else if (currentList.size() == 4) {
    353. //判断是不是炸弹
    354. if (isSame(currentList, 4)) {
    355. return true;
    356. }
    357. return false;
    358. }
    359. return false;
    360. }
    361. public static boolean compareLast(List prevList,
    362. List currentList) {
    363. if (prevList.get(prevList.size() - 1).getNum() <
    364. currentList.get(currentList.size() - 1).getNum()) {
    365. return true;
    366. }
    367. return false;
    368. }
    369. public static boolean compare(List prevList,
    370. List currentList) {
    371. int a = san(prevList);
    372. int b = san(currentList);
    373. if (a == -1 || b == -1) {
    374. return false;
    375. }
    376. if (b > a) {
    377. return true;
    378. }
    379. return false;
    380. }
    381. public static int san(List list) {
    382. for (int i = 0; i < list.size() - 2; i++) {
    383. int a = list.get(i).getNum();
    384. int b = list.get(i + 1).getNum();
    385. int c = list.get(i + 2).getNum();
    386. if (a == b && a == c) {
    387. return a;
    388. }
    389. }
    390. return -1;
    391. }
    392. }

    PokerType.java

    1. package client.util;
    2. public enum PokerType {
    3. p_1,//单牌。
    4. p_2,//对子。
    5. p_2w,//王炸
    6. p_3,//3不带。
    7. p_4,//炸弹。
    8. p_n,//顺子。
    9. p_31,//3带1。
    10. p_32,//3带2。
    11. p_1122,//连队。
    12. p_111222,//飞机。
    13. p_11122234,//飞机带单排.
    14. p_1112223344,//飞机带对子.
    15. p_error//不能出牌
    16. }

    LoginFrame.java

    1. package client.view;
    2. import java.awt.*;
    3. import java.awt.event.*;
    4. import javax.swing.*;
    5. import java.io.*;
    6. import java.net.*;
    7. public class LoginFrame extends JFrame {
    8. private JLabel lblUserName;
    9. private JTextField txtUserName;
    10. private JButton btnLogin;
    11. private JButton btnCancel;
    12. private void init() {
    13. Container container = this.getContentPane();
    14. //创建组件对象
    15. lblUserName = new JLabel("用户名:");
    16. txtUserName = new JTextField();
    17. btnLogin = new JButton("登录");
    18. btnCancel = new JButton("取消");
    19. //设置窗口属性
    20. setSize(400, 220);
    21. setVisible(true);
    22. setLocationRelativeTo(null);
    23. setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    24. container.setLayout(null);
    25. //设置组件属性
    26. lblUserName.setSize(80, 25);
    27. lblUserName.setLocation(90, 50);
    28. lblUserName.setFont(new Font("微软雅黑", Font.PLAIN, 20));
    29. txtUserName.setSize(120, 25);
    30. txtUserName.setLocation(180, 50);
    31. txtUserName.setFont(new Font("微软雅黑", Font.PLAIN, 20));
    32. btnLogin.setSize(80, 25);
    33. btnLogin.setLocation(100, 100);
    34. btnLogin.setFont(new Font("微软雅黑", Font.PLAIN, 20));
    35. btnCancel.setSize(80, 25);
    36. btnCancel.setLocation(200, 100);
    37. btnCancel.setFont(new Font("微软雅黑", Font.PLAIN, 20));
    38. //添加组件到窗口中
    39. container.add(lblUserName);
    40. container.add(txtUserName);
    41. container.add(btnLogin);
    42. container.add(btnCancel);
    43. //创建监听器对象 绑定到按钮上
    44. MyEvent myEvent = new MyEvent();
    45. btnLogin.addActionListener(myEvent);
    46. }
    47. public LoginFrame() {
    48. init();
    49. }
    50. //创建事件监听器类
    51. class MyEvent implements ActionListener {
    52. @Override
    53. public void actionPerformed(ActionEvent arg0) {
    54. //点击登录
    55. //1.获得用户名
    56. String uname = txtUserName.getText();
    57. //2.创建一个socket链接服务器端
    58. try {
    59. Socket socket = new Socket("127.0.0.1", 8888);
    60. //3.跳转到主窗口
    61. new MainFrame(uname, socket);
    62. dispose();//关闭当前窗口
    63. } catch (UnknownHostException e) {
    64. e.printStackTrace();
    65. } catch (IOException e) {
    66. e.printStackTrace();
    67. }
    68. }
    69. }
    70. }

    MainFrame.java

    1. package client.view;
    2. import java.awt.*;
    3. import java.awt.event.*;
    4. import java.io.*;
    5. import java.net.*;
    6. import java.util.*;
    7. import javax.swing.*;
    8. import client.model.*;
    9. import client.util.*;
    10. import client.thread.*;
    11. public class MainFrame extends JFrame {
    12. public MyPanel myPanel;
    13. public String uname;
    14. public Socket socket;
    15. public SendThread sendThread; // 发送消息的线程
    16. public ReceiveThread receiveThread;// 接收消息的线程
    17. public Player currentPlayer; // 存放当前玩家对象
    18. public java.util.List pokerLabels =
    19. new ArrayList(); // 存放扑克标签列表
    20. public JLabel lordLabel1; // 抢地主标签
    21. public JLabel lordLabel2; // 不叫
    22. public JLabel timeLabel; // 定时器标签
    23. public CountThread countThread; // 计数器的线程
    24. public boolean isLord; // 是否是地主
    25. public JLabel msgLabel; // 存放消息
    26. public JLabel lordIconLabel; //地主图标
    27. public JLabel chupaiJLabel;//出牌标签
    28. public JLabel buchuJLabel; //不出牌标签
    29. public ChuPaiThread chuPaiThread; //出牌定时器线程
    30. public java.util.List selectedPokerLabels =
    31. new ArrayList();//存放选中的扑克列表
    32. public java.util.List showOutPokerLabels =
    33. new ArrayList(); //存放当前出牌的列表
    34. public boolean isOut; //选择的是出牌还是不出牌
    35. public int prevPlayerid = -1; //上一个出牌的玩家id
    36. public MainFrame(String uname, Socket socket) {
    37. this.uname = uname;
    38. this.socket = socket;
    39. // 设置窗口的属性
    40. this.setTitle(uname);
    41. this.setSize(1200, 700);
    42. this.setVisible(true);
    43. this.setLocationRelativeTo(null);
    44. this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    45. // 添加mypanel
    46. myPanel = new MyPanel();
    47. myPanel.setBounds(0, 0, 1200, 700);
    48. this.add(myPanel);
    49. //初始化窗口信息
    50. init();
    51. // 启动发消息的线程
    52. sendThread = new SendThread(socket, uname);
    53. sendThread.start();
    54. // 启动接收消息的线程
    55. receiveThread = new ReceiveThread(socket, this);
    56. receiveThread.start();
    57. }
    58. //窗口初始化
    59. public void init() {
    60. //创建消息框
    61. msgLabel = new JLabel();
    62. chupaiJLabel = new JLabel();
    63. chupaiJLabel.setBounds(330, 350, 110, 53);
    64. chupaiJLabel.setIcon(new ImageIcon("images/bg/chupai.png"));
    65. chupaiJLabel.addMouseListener(new MyMouseEvent());
    66. chupaiJLabel.setVisible(false);
    67. this.myPanel.add(chupaiJLabel);
    68. buchuJLabel = new JLabel();
    69. buchuJLabel.setBounds(440, 350, 110, 53);
    70. buchuJLabel.setIcon(new ImageIcon("images/bg/buchupai.png"));
    71. buchuJLabel.addMouseListener(new MyMouseEvent());
    72. buchuJLabel.setVisible(false);
    73. this.myPanel.add(buchuJLabel);
    74. timeLabel = new JLabel();
    75. timeLabel.setBounds(550, 350, 50, 50);
    76. timeLabel.setFont(new Font("Dialog", 0, 30));
    77. timeLabel.setForeground(Color.red);
    78. timeLabel.setVisible(false);
    79. this.myPanel.add(timeLabel);
    80. }
    81. public void showAllPlayersInfo(java.util.List players) {
    82. // 1.显示三个玩家的名称
    83. // 2.显示当前玩家的扑克列表
    84. for (int i = 0; i < players.size(); i++) {
    85. if (players.get(i).getName().equals(uname)) {
    86. currentPlayer = players.get(i);
    87. }
    88. }
    89. java.util.List pokers = currentPlayer.getPokers();
    90. for (int i = 0; i < pokers.size(); i++) {
    91. // 创建扑克标签
    92. Poker poker = pokers.get(i);
    93. PokerLabel pokerLabel = new PokerLabel(poker.getId(),
    94. poker.getName(), poker.getNum());
    95. pokerLabel.turnUp(); // 显示正面图
    96. // 添加到面板中
    97. this.myPanel.add(pokerLabel);
    98. this.pokerLabels.add(pokerLabel);
    99. // 动态的显示出来
    100. this.myPanel.setComponentZOrder(pokerLabel, 0);
    101. // 一张一张的显示出来
    102. GameUtil.move(pokerLabel, 300 + 30 * i, 450);
    103. }
    104. // 对扑克列表排序
    105. Collections.sort(pokerLabels);
    106. // 重新移动位置
    107. for (int i = 0; i < pokerLabels.size(); i++) {
    108. this.myPanel.setComponentZOrder(pokerLabels.get(i), 0);
    109. GameUtil.move(pokerLabels.get(i), 300 + 30 * i, 450);
    110. }
    111. if (currentPlayer.getId() == 0) {
    112. getLord(); // 抢地主
    113. }
    114. }
    115. //抢地主
    116. public void getLord() {
    117. // 显示抢地主的按钮 和 定时器按钮
    118. lordLabel1 = new JLabel();
    119. lordLabel1.setBounds(330, 400, 104, 46);
    120. lordLabel1.setIcon(new ImageIcon("images/bg/jiaodizhu.png"));
    121. lordLabel1.addMouseListener(new MyMouseEvent());
    122. this.myPanel.add(lordLabel1);
    123. lordLabel2 = new JLabel();
    124. lordLabel2.setBounds(440, 400, 104, 46);
    125. lordLabel2.setIcon(new ImageIcon("images/bg/bujiao.png"));
    126. lordLabel2.addMouseListener(new MyMouseEvent());
    127. this.myPanel.add(lordLabel2);
    128. //显示定时器的图标
    129. this.timeLabel.setVisible(true);
    130. this.setVisible(true);
    131. // 重绘
    132. this.repaint();
    133. // 启动计时器的线程
    134. countThread = new CountThread(10, this);
    135. countThread.start();
    136. }
    137. //显示出牌的标签
    138. public void showChuPaiJabel() {
    139. if (prevPlayerid == currentPlayer.getId()) {
    140. //从窗口上移除之前的出牌的列表
    141. for (int i = 0; i < showOutPokerLabels.size(); i++) {
    142. myPanel.remove(showOutPokerLabels.get(i));
    143. }
    144. //清空之前出牌的列表
    145. showOutPokerLabels.clear();
    146. }
    147. // 显示出牌和不出牌的按钮 和 定时器按钮
    148. chupaiJLabel.setVisible(true);
    149. buchuJLabel.setVisible(true);
    150. timeLabel.setVisible(true);
    151. this.repaint();
    152. chuPaiThread = new ChuPaiThread(30, this);
    153. chuPaiThread.start();
    154. }
    155. // 显示消息(不抢 或 不出)
    156. public void showMsg(int playerid, int typeid) {
    157. msgLabel.setVisible(true);
    158. msgLabel.setBounds(500, 300, 129, 77);
    159. if (typeid == 1) {
    160. msgLabel.setIcon(new ImageIcon("images/bg/buqiang.png"));
    161. }
    162. if (typeid == 3) {
    163. msgLabel.setIcon(new ImageIcon("images/bg/buchu.png"));
    164. }
    165. if (playerid == currentPlayer.getId()) {
    166. msgLabel.setLocation(400, 300);
    167. } else if (playerid + 1 == currentPlayer.getId() ||
    168. playerid - 2 == currentPlayer.getId()) //上家 // 2 0 0 1 1 2
    169. {
    170. msgLabel.setLocation(300, 100);
    171. } else { // 下家
    172. msgLabel.setLocation(800, 100);
    173. }
    174. this.myPanel.add(msgLabel);
    175. this.repaint();
    176. }
    177. // 添加地主牌
    178. public void addLordPokers(java.util.List lordPokers) {
    179. for (int i = 0; i < lordPokers.size(); i++) {
    180. Poker poker = lordPokers.get(i);
    181. PokerLabel pokerLabel = new PokerLabel(poker.getId(),
    182. poker.getName(), poker.getNum());
    183. pokerLabel.turnUp(); // 显示正面图
    184. this.pokerLabels.add(pokerLabel);
    185. }
    186. Collections.sort(pokerLabels);
    187. for (int i = 0; i < pokerLabels.size(); i++) {
    188. // 添加到面板中
    189. this.myPanel.add(pokerLabels.get(i));
    190. // 动态的显示出来
    191. this.myPanel.setComponentZOrder(pokerLabels.get(i), 0);
    192. // 一张一张的显示出来
    193. GameUtil.move(pokerLabels.get(i), 300 + 30 * i, 450);
    194. }
    195. currentPlayer.getPokers().addAll(lordPokers);
    196. }
    197. //显示地主图标
    198. public void showLordIcon(int playerid) {
    199. //创建地主图标对象
    200. lordIconLabel = new JLabel();
    201. lordIconLabel.setIcon(new ImageIcon("images/bg/dizhu.png"));
    202. lordIconLabel.setSize(60, 89);
    203. //根据玩家id显示到具体的位置
    204. //如果自己是地主
    205. if (playerid == currentPlayer.getId()) {
    206. lordIconLabel.setLocation(200, 450);
    207. } else if (playerid + 1 == currentPlayer.getId() ||
    208. playerid - 2 == currentPlayer.getId()) //上家 // 2 0 0 1 1 2
    209. {
    210. lordIconLabel.setLocation(200, 100);
    211. } else { // 下家
    212. lordIconLabel.setLocation(950, 100);
    213. }
    214. //添加地主图标到面板上
    215. this.myPanel.add(lordIconLabel);
    216. this.repaint(); //重绘
    217. }
    218. //给扑克牌添加单击事件
    219. public void addClickEventToPoker() {
    220. for (int i = 0; i < pokerLabels.size(); i++) {
    221. pokerLabels.get(i).addMouseListener(new PokerEvent());
    222. }
    223. }
    224. //显示出牌的列表
    225. public void showOutPokerList(int playerid,
    226. java.util.List outPokers) {
    227. //从窗口上移除之前的出牌的列表
    228. for (int i = 0; i < showOutPokerLabels.size(); i++) {
    229. myPanel.remove(showOutPokerLabels.get(i));
    230. }
    231. //清空之前出牌的列表
    232. showOutPokerLabels.clear();
    233. //显示当前出牌的列表
    234. for (int i = 0; i < outPokers.size(); i++) {
    235. Poker poker = outPokers.get(i);
    236. PokerLabel pokerLabel = new PokerLabel(poker.getId(),
    237. poker.getName(), poker.getNum());
    238. if (playerid == currentPlayer.getId()) {
    239. pokerLabel.setLocation(400 + 30 * i, 300);
    240. } else if (playerid + 1 == currentPlayer.getId() ||
    241. playerid - 2 == currentPlayer.getId()) {
    242. pokerLabel.setLocation(200 + 30 * i, 100);
    243. } else {
    244. pokerLabel.setLocation(700 + 30 * i, 100);
    245. }
    246. pokerLabel.turnUp();
    247. myPanel.add(pokerLabel);
    248. showOutPokerLabels.add(pokerLabel);
    249. myPanel.setComponentZOrder(pokerLabel, 0);
    250. }
    251. this.repaint(); //窗口重绘
    252. }
    253. //出牌 将出的牌从当前玩家的扑克列表中移除
    254. public void removeOutPokerFromPokerList() {
    255. //1.从当前玩家的扑克列表中移除
    256. pokerLabels.removeAll(selectedPokerLabels);
    257. //2.从面板中移除
    258. for (int i = 0; i < selectedPokerLabels.size(); i++) {
    259. myPanel.remove(selectedPokerLabels.get(i));
    260. }
    261. //3.剩下的扑克列表重新定位
    262. for (int i = 0; i < pokerLabels.size(); i++) {
    263. myPanel.setComponentZOrder(pokerLabels.get(i), 0);
    264. GameUtil.move2(pokerLabels.get(i), 300 + 30 * i, 450);
    265. }
    266. //4.清空选择的扑克牌列表
    267. selectedPokerLabels.clear();
    268. this.repaint();
    269. }
    270. //游戏结束
    271. public void gameOver() {
    272. this.myPanel.removeAll();
    273. this.repaint();
    274. try {
    275. this.socket.close();
    276. } catch (IOException e) {
    277. // TODO Auto-generated catch block
    278. e.printStackTrace();
    279. }
    280. this.countThread.setRun(false);
    281. this.chuPaiThread.setRun(false);
    282. this.sendThread.setRun(false);
    283. this.receiveThread.setRun(false);
    284. }
    285. // 创建鼠标事件监听器类
    286. class MyMouseEvent extends MouseAdapter {
    287. @Override
    288. public void mouseClicked(MouseEvent event) {
    289. // 点击的是抢地主
    290. if (event.getSource().equals(lordLabel1)) {
    291. // 停止计时器
    292. countThread.setRun(false);
    293. isLord = true;
    294. // 设置抢地主的按钮不可见
    295. lordLabel1.setVisible(false);
    296. lordLabel2.setVisible(false);
    297. timeLabel.setVisible(false);
    298. }
    299. // 点击的不抢
    300. if (event.getSource().equals(lordLabel2)) {
    301. // 停止计时器
    302. countThread.setRun(false);
    303. isLord = false;
    304. lordLabel1.setVisible(false);
    305. lordLabel2.setVisible(false);
    306. timeLabel.setVisible(false);
    307. }
    308. //点击出牌
    309. if (event.getSource().equals(chupaiJLabel)) {
    310. PokerType pokerType = PokerRule.checkPokerType(selectedPokerLabels);
    311. //判断是否符合牌型
    312. if (!pokerType.equals(PokerType.p_error)) {
    313. System.out.println(prevPlayerid + "," + currentPlayer.getId());
    314. //符合牌型,判断是不是比上家大 或者上家就是自己
    315. if (prevPlayerid == -1 || prevPlayerid == currentPlayer.getId() ||
    316. PokerRule.legal(showOutPokerLabels, selectedPokerLabels)) {
    317. isOut = true;
    318. //计时器停止
    319. chuPaiThread.setRun(false);
    320. chupaiJLabel.setVisible(false);
    321. buchuJLabel.setVisible(false);
    322. timeLabel.setVisible(false);
    323. } else {
    324. JOptionPane.showMessageDialog(null, "请按规则出牌");
    325. }
    326. } else {
    327. JOptionPane.showMessageDialog(null, "不符合牌型");
    328. }
    329. }
    330. if (event.getSource().equals(buchuJLabel)) {
    331. isOut = false;
    332. //计时器停止
    333. chuPaiThread.setRun(false);
    334. chupaiJLabel.setVisible(false);
    335. buchuJLabel.setVisible(false);
    336. timeLabel.setVisible(false);
    337. }
    338. }
    339. }
    340. //创建扑克牌的事件监听器类
    341. class PokerEvent extends MouseAdapter {
    342. @Override
    343. public void mouseClicked(MouseEvent arg0) {
    344. // TODO Auto-generated method stub
    345. PokerLabel pokerLabel = (PokerLabel) arg0.getSource();
    346. //如果之前选择过了 则取消选择(设置选中属性为false 位置回到原位,从选择的扑克牌列表中移除)
    347. if (pokerLabel.isSelected()) {
    348. pokerLabel.setSelected(false);
    349. pokerLabel.setLocation(pokerLabel.getX(), pokerLabel.getY() + 30);
    350. selectedPokerLabels.remove(pokerLabel);
    351. }
    352. //如果之前没有选择 则选中(设置选中属性为true 位置往上移动一点,添加到选择的扑克牌列表中)
    353. else {
    354. pokerLabel.setSelected(true);
    355. pokerLabel.setLocation(pokerLabel.getX(), pokerLabel.getY() - 30);
    356. selectedPokerLabels.add(pokerLabel);
    357. }
    358. }
    359. }
    360. }

    MyPanel.java

    1. package client.view;
    2. import java.awt.*;
    3. import javax.swing.*;
    4. public class MyPanel extends JPanel{
    5. public MyPanel()
    6. {
    7. this.setLayout(null);
    8. }
    9. @Override
    10. protected void paintComponent(Graphics g) {
    11. Image image=new ImageIcon("images/bg/bg1.png").getImage();
    12. g.drawImage(image, 0, 0, this.getWidth(), this.getHeight(), null);
    13. }
    14. }

    Main.java

    1. package client.view;
    2. public class Main {
    3. public static void main(String[] args) {
    4. new LoginFrame();//打开第一个玩家的登录窗口
    5. new LoginFrame();//打开第二个玩家的登录窗口
    6. new LoginFrame();//打开第三个玩家的登录窗口
    7. }
    8. }

    MainServer.java

    1. package server;
    2. import java.io.*;
    3. import java.net.*;
    4. import java.util.*;
    5. import com.alibaba.fastjson.*;
    6. import client.model.*;
    7. public class MainServer {
    8. //创建玩家列表
    9. public List players = new ArrayList();
    10. public int index = 0;
    11. //存放扑克列表
    12. public List allPokers = new ArrayList();
    13. //存放底牌
    14. public List lordPokers = new ArrayList();
    15. public int step = 0; //牌局的进展步骤
    16. public MainServer() {
    17. //创建扑克列表
    18. createPokers();
    19. try {
    20. //1.创建服务器端socket
    21. ServerSocket serverSocket = new ServerSocket(8888);
    22. while (true) {
    23. //2.接收客户端的socket
    24. Socket socket = serverSocket.accept();
    25. //3.开启线程 处理客户端的socket
    26. AcceptThread acceptThread = new AcceptThread(socket);
    27. acceptThread.start();
    28. }
    29. } catch (IOException e) {
    30. e.printStackTrace();
    31. System.out.println("服务器端异常");
    32. }
    33. }
    34. //创建一个接收线程 处理客户端的信息
    35. class AcceptThread extends Thread {
    36. Socket socket;
    37. public AcceptThread(Socket socket) {
    38. this.socket = socket;
    39. }
    40. public void run() {
    41. try {
    42. DataInputStream dataInputStream =
    43. new DataInputStream(socket.getInputStream());
    44. while (true) {
    45. String msg = dataInputStream.readUTF();
    46. if (step == 0) {
    47. //创建player对象
    48. Player player = new Player(index++, msg);
    49. player.setSocket(socket);
    50. //存入玩家列表
    51. players.add(player);
    52. System.out.println(msg + "上线了");
    53. System.out.println("当前上线人数:" + players.size());
    54. //玩家人数到齐,发给三个玩家
    55. if (players.size() == 3) {
    56. deal();//发牌
    57. step = 1;
    58. }
    59. } else if (step == 1) //接收抢地主的信息
    60. {
    61. System.out.println("接收抢地主的消息");
    62. JSONObject msgJsonObject = JSON.parseObject(msg);
    63. int typeid = msgJsonObject.getInteger("typeid");
    64. int playerid = msgJsonObject.getInteger("playerid");
    65. String content = msgJsonObject.getString("content");
    66. //抢地主
    67. if (typeid == 2) {
    68. //重新组将一个 消息对象 ,添加地主牌
    69. Message sendMessage =
    70. new Message(typeid, playerid, content, lordPokers);
    71. msg = JSON.toJSONString(sendMessage);
    72. step = 2;
    73. }
    74. //不抢 将客户端发过来的不抢的信息 原样群发到所有玩家
    75. sendMessageToClient(msg);
    76. } else if (step == 2) //出牌和不出牌和游戏结束
    77. {
    78. sendMessageToClient(msg); //转发到所有的客户端
    79. }
    80. }
    81. } catch (IOException e) {
    82. e.printStackTrace();
    83. System.out.println("服务器异常:" + e.getMessage());
    84. }
    85. }
    86. }
    87. //群发消息到客户端
    88. public void sendMessageToClient(String msg) {
    89. for (int i = 0; i < players.size(); i++) {
    90. DataOutputStream dataOutputStream;
    91. try {
    92. dataOutputStream = new DataOutputStream(
    93. players.get(i).getSocket().getOutputStream());
    94. dataOutputStream.writeUTF(msg);
    95. } catch (IOException e) {
    96. e.printStackTrace();
    97. }
    98. }
    99. }
    100. //创建所有的扑克列表
    101. public void createPokers() {
    102. //创建大王 ,小王
    103. Poker dawang = new Poker(0, "大王", 17);
    104. Poker xiaowang = new Poker(1, "小王", 16);
    105. allPokers.add(dawang);
    106. allPokers.add(xiaowang);
    107. //创建其它扑克
    108. String[] names = new String[]
    109. {"2", "A", "K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3"};
    110. String[] colors = new String[]
    111. {"黑桃", "红桃", "梅花", "双块"};
    112. int id = 2;
    113. int num = 15;
    114. //遍历扑克的种类
    115. for (String name : names) {
    116. //遍历每个种类的花色
    117. for (String color : colors) {
    118. Poker poker = new Poker(id++, color + name, num);
    119. allPokers.add(poker);
    120. }
    121. num--;
    122. }
    123. //洗牌
    124. Collections.shuffle(allPokers);
    125. }
    126. //发牌
    127. public void deal() {
    128. //发给三个玩家
    129. for (int i = 0; i < allPokers.size(); i++) {
    130. //最后三张留给地主牌
    131. if (i >= 51) {
    132. lordPokers.add(allPokers.get(i));
    133. } else {
    134. //依次分发给三个玩家
    135. if (i % 3 == 0)
    136. players.get(0).getPokers().add(allPokers.get(i));
    137. else if (i % 3 == 1)
    138. players.get(1).getPokers().add(allPokers.get(i));
    139. else
    140. players.get(2).getPokers().add(allPokers.get(i));
    141. }
    142. }
    143. //将玩家的信息发送到客户端
    144. for (int i = 0; i < players.size(); i++) {
    145. try {
    146. DataOutputStream dataOutputStream =
    147. new DataOutputStream(
    148. players.get(i).getSocket().getOutputStream());
    149. String jsonString = JSON.toJSONString(players);
    150. System.out.println(jsonString);
    151. dataOutputStream.writeUTF(jsonString);
    152. } catch (IOException e) {
    153. e.printStackTrace();
    154. }
    155. }
    156. }
    157. }

    Main.java

    1. package server;
    2. public class Main {
    3. public static void main(String[] args) {
    4. new MainServer();
    5. }
    6. }

    除阅读文章外,各位小伙伴还可以点击这里观看我在本站的视频课程学习Java!

  • 相关阅读:
    数据管理知识体系指南(第二版)-第十章——参考数据和主数据-学习笔记
    vite + vue3 的项目中使用 vitest 做单元测试(仅供参考)
    MySQL的EXPLAIN执行计划的属性解释
    经典矩阵试题(一)
    提高研发效率还得看Apipost
    项目中执行 npm run xxx 的时候发生了什么?
    极狐GitLab专家团队支招解决 CVE-2023-4998 漏洞问题
    vue3 组件响应式v-model 失效,实践踩坑,一文搞懂组件响应式原理,对初学者友好
    Auto.js中的一般全局函数
    技术人必读的「CDP选型指南」来了!
  • 原文地址:https://blog.csdn.net/shalimu/article/details/128182742