10.2.4 核心处理逻辑

开发“猜数字”游戏最关键的部分在于如何通过编码实现10.1.3节中的核心处理流程,笔者将游戏相关的处理逻辑统一封装在GameService类中,该类的代码如下:

  1. 1 package org.liufeng.course.service;
  2. 2 
  3. 3 import java.util.HashMap;
  4. 4 import java.util.List;
  5. 5 import javax.servlet.http.HttpServletRequest;
  6. 6 import org.liufeng.course.pojo.Game;
  7. 7 import org.liufeng.course.pojo.GameRound;
  8. 8 import org.liufeng.course.util.GameUtil;
  9. 9 import org.liufeng.course.util.MySQLUtil;
  10. 10 
  11. 11 /**
  12. 12  * "猜数字"游戏业务类
  13. 13  *
  14. 14  * @author liufeng
  15. 15  * @date 2013-11-21
  16. 16  */
  17. 17 public class GameService {
  18. 18  /**
  19. 19  * "猜数字"游戏处理逻辑
  20. 20  *
  21. 21  * @param request 请求对象
  22. 22  * @param openId 用户的OpenID
  23. 23  * @param content 消息内容
  24. 24  * @return
  25. 25  */
  26. 26  public static String process(HttpServletRequest request, String openId,
  27. String content)
  28. 27 {
  29. 28  // 获取用户最近一次创建的游戏
  30. 29  Game game = MySQLUtil.getLastGame(request, openId);
  31. 30  // 本局游戏的正确答案
  32. 31  String gameAnswer = null;
  33. 32  // 本回合的猜测结果
  34. 33  String guessResult = null;
  35. 34  // 本局游戏的id
  36. 35  int gameId = -1;
  37. 36  // 是不是新的一局(默认为false)
  38. 37  boolean newGameFlag = (null == game || 0 != game.getGameStatus());
  39. 38  // 新的一局
  40. 39  if (newGameFlag) {
  41. 40  // 生成不重复的4位随机数作为答案
  42. 41  gameAnswer = GameUtil.generateRandNumber();
  43. 42  // 计算本回合"猜数字"的结果(xAyB)
  44. 43  guessResult = GameUtil.guessResult(gameAnswer, content);
  45. 44  // 创建game
  46. 45  game = new Game();
  47. 46  game.setOpenId(openId);
  48. 47  game.setGameAnswer(gameAnswer);
  49. 48  game.setCreateTime(GameUtil.getStdDateTime());
  50. 49  game.setGameStatus(0);
  51. 50  // 保存game并获取id
  52. 51  gameId = MySQLUtil.saveGame(request, game);
  53. 52  }
  54. 53  // 不是新的一局
  55. 54  else {
  56. 55  gameAnswer = game.getGameAnswer();
  57. 56  guessResult = GameUtil.guessResult(game.getGameAnswer(), content);
  58. 57  gameId = game.getGameId();
  59. 58  }
  60. 59  // 保存当前游戏回合
  61. 60  GameRound gameRound = new GameRound();
  62. 61  gameRound.setGameId(gameId);
  63. 62  gameRound.setOpenId(openId);
  64. 63  gameRound.setGuessNumber(content);
  65. 64  gameRound.setGuessTime(GameUtil.getStdDateTime());
  66. 65  gameRound.setGuessResult(guessResult);
  67. 66  MySQLUtil.saveGameRound(request, gameRound);
  68. 67  // 查询本局游戏的所有回合
  69. 68  List<GameRound> roundList = MySQLUtil.findAllRoundByGameId(request, gameId);
  70. 69  // 遍历游戏回合,组装给用户回复的消息
  71. 70  StringBuffer buffer = new StringBuffer();
  72. 71  buffer.append("查看玩法请回复:help").append("\n");
  73. 72  buffer.append("查看战绩请回复:score").append("\n");
  74. 73  for (int i = 0; i < roundList.size(); i++) {
  75. 74  gameRound = roundList.get(i);
  76. 75  buffer.append(String.format("第%d回合: %s %s", i + 1,
  77. 76  gameRound.getGuessNumber(), gameRound.getGuessResult())).append("\n");
  78. 77  }
  79. 78  // 胜利
  80. 79  if ("4A0B".equals(guessResult)) {
  81. 80  buffer.append("正确答案:").append(gameAnswer) .append("\n");
  82. 81  buffer.append("恭喜您猜对了![强]").append("\n");
  83. 82  buffer.append("重新输入4个不重复的数字开始新的一局。");
  84. 83  MySQLUtil.updateGame(request,gameId,1,GameUtil.getStdDateTime());
  85. 84  }
  86. 85  // 失败(10回合仍没猜对)
  87. 86  else if (roundList.size() >= 10) {
  88. 87  buffer.append("正确答案:").append(gameAnswer).append("\n");
  89. 88  buffer.append("唉,10回合都没猜出来,本局结束![流泪]").append("\n");
  90. 89  buffer.append("重新输入4个不重复的数字开始新的一局。");
  91. 90  MySQLUtil.updateGame(request, gameId, 2, GameUtil.getStdDateTime());
  92. 91  }
  93. 92  // 本回合没猜对
  94. 93  else {
  95. 94  buffer.append("请再接再厉!");
  96. 95  }
  97. 96  return buffer.toString();
  98. 97  }
  99. 98 
  100. 99  /**
  101. 100  * "猜数字"游戏玩法
  102. 101  *
  103. 102  * @return String
  104. 103  */
  105. 104  public static String getGameRule() {
  106. 105  StringBuffer buffer = new StringBuffer();
  107. 106  buffer.append("《"猜数字"游戏玩法》").append("\n");
  108. 107  buffer.append("系统设定一个没有重复数字的4位数,由玩家来猜,每局10次机会。")
  109. .append("\n");
  110. 108  buffer.append("每猜一次,系统会给出猜测结果xAyB,x表示数字与位置
  111. 109  均正确的数的个数,y表示数字正确但位置不对的数的个数。").append("\n");
  112. 110  buffer.append("玩家根据猜测结果xAyB一直猜,直到猜中(4A0B)为止。")
  113.   .append("\n");
  114. 111  buffer.append("如果10次都没猜中,系统会公布答案,游戏结束。")
  115.   .append("\n");
  116. 112  buffer.append("玩家任意输入一个没有重复数字的4位数即开始游戏,例如:7890");
  117. 113  return buffer.toString();
  118. 114  }
  119. 115 
  120. 116  /**
  121. 117  * "猜数字"游戏战绩
  122. 118  *
  123. 119  * @param request 请求对象
  124. 120  * @param openId 用户的OpenID
  125. 121  * @return
  126. 122  */
  127. 123  public static String getUserScore(HttpServletRequest request, String openId) {
  128. 124  StringBuffer buffer = new StringBuffer();
  129. 125  HashMap<Integer, Integer> scoreMap = MySQLUtil.getScoreByOpenId(request,
  130.   openId);
  131. 126  if (null == scoreMap || 0 == scoreMap.size()) {
  132. 127  buffer.append("您还没有玩过"猜数字"游戏!").append("\n");
  133. 128  buffer.append("请输入4个不重复的数字开始新的一局,例如:0269");
  134. 129  } else {
  135. 130  buffer.append("您的游戏战绩如下:").append("\n");
  136. 131  for (Integer status : scoreMap.keySet()) {
  137. 132  if (0L == status) {
  138. 133  buffer.append("游戏中:").append(scoreMap.get(status))
  139.   .append("\n");
  140. 134  } else if (1L == status) {
  141. 135  buffer.append("胜利局数:").append(scoreMap.get(status))
  142.   .append("\n");
  143. 136  } else if (2L == status) {
  144. 137  buffer.append("失败局数:").append(scoreMap.get(status))
  145.   .append("\n");
  146. 138  }
  147. 139  }
  148. 140  buffer.append("请输入4个不重复的数字开始新的一局,例如:0269");
  149. 141  }
  150. 142  return buffer.toString();
  151. 143  }
  152. 144 }

上述代码中的process()方法是核心处理流程的编码实现,用于处理用户每回合猜测的数字,主要说明如下。

第29行和第37行:获取用户最近一次创建的游戏,然后判断是创建新的一局游戏还是继续之前的游戏,如果数据库中没有用户的游戏记录,或者用户最近一次创建的游戏已结束(游戏状态为胜利或失败),则表示创建新的一局游戏。

第39~58行:是不是新的一局游戏关系到正确答案、猜测结果和游戏ID的获取方式。如果是新的一局游戏,正确答案和游戏ID要重新生成;如果是继续之前的游戏,正确答案和游戏ID是从数据库中获得。

第60~66行:保存当前游戏回合的数据。

第68~77行:查询出本局游戏的所有回合数据,并将每一回合的猜测数字、猜测答案追加到buffer中,方便用户推理。

第79~96行:根据猜测结果往buffer中追加不同的提示信息,如果本局游戏结束(胜利或失败),还要更新本局游戏的状态。

GameService类还有两个方法getGameRule()和getUserScore(),分别用于获取游戏玩法和用户的游戏战绩。