zoukankan      html  css  js  c++  java
  • 微信公众平台开发—24点游戏

    因为申请的是个人未认证的订阅号,开启开发者模式以后没有菜单,只能使用接收消息—回复消息的方式来开发

    一、实现思路

    1、24点题库

    第一步是建一张题库表,基础字段是:"num1"、"num2"、"num3"、"num4"、"答案"五个,如果未来需要"最难题排行"功能,需要再加入"答题数、答对数、命中率"三个字段

    我的题库来自http://www.cnblogs.com/grenet/archive/2013/02/28/2936965.html

    我把内容复制到excel里,按逗号切割了一下,然后又复制到数据库表里,因为想操作方便点,就去掉了带有数字"10"的题目

    2、出题

    先计算上一题结果,因为有404道题,从404中取一个随机数,作为题目id查询题目返回

    3、计算答案

    (1)先要把可能接收到的全角括号、长短横杠、"X"替换成能识别的"+-*/"

    (2)然后再判断答案里的4个数字是否和题目里的一致,如果题目是"1 2 3 5"回答是"4+4+4+4"就不能通过

    (3)借助ScriptEngineManager类和ScriptEngine类将表达式eval成结果,判断是否是"24"

    (4)完成判断以后根据回复时间给出用户得分,用时越少得分越多,然后更新用户的"积分、答题数、答对数、命中率"和题目的"答题数、答对数、命中率"

    4、排行榜

    按用户表的积分大小倒序输出排名即可,需要注意的是如果前10名没有当前用户,要再输出一行当前用户的排名

    5、答题状态

    出题后用户会切换成答题状态,回复的内容除了关键字都会当做答案来计算,回复"24"、"答案"、"公告"和正确答案后会再切换成正常状态

    二、核心源码

    package org.xs.dntown.wx.game24.modules.web;
    
    import java.text.NumberFormat;
    import java.util.Arrays;
    import java.util.Date;
    import java.util.List;
    import java.util.Random;
    
    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;
    import javax.servlet.http.HttpServletRequest;
    
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.xs.dntown.wx.common.utils.MessageUtil;
    import org.xs.dntown.wx.common.web.BaseController;
    import org.xs.dntown.wx.core.modules.entity.UserInfo;
    import org.xs.dntown.wx.core.modules.entity.enums.ModuleEnum;
    import org.xs.dntown.wx.core.modules.entity.req.BaseMsgReq;
    import org.xs.dntown.wx.core.modules.service.LogService;
    import org.xs.dntown.wx.core.modules.service.UserService;
    import org.xs.dntown.wx.game24.modules.entity.Game24UserInfo;
    import org.xs.dntown.wx.game24.modules.entity.QuestionInfo;
    import org.xs.dntown.wx.game24.modules.entity.enums.StepEnum;
    import org.xs.dntown.wx.game24.modules.service.Game24UserService;
    import org.xs.dntown.wx.game24.modules.service.QuestionService;
    
    /**
     * 核心Controller
     */
    @Controller(value = "game24CoreController")
    @RequestMapping("game24")
    public class CoreController extends BaseController {
    	
    	@Autowired
    	private Game24UserService game24UserService;
    	
    	@Autowired
    	private QuestionService questionService;
    	
    	@Autowired
    	private UserService userService;
    	
    	@Autowired
    	private LogService logService;
    	
    	/**
    	 * 文本消息
    	 */
    	@ResponseBody
    	@RequestMapping(value = "msg", produces = { "text/plain;charset=utf-8" })
    	public String textMsg(HttpServletRequest request) throws Exception {
    		String result = "";
    		String openId = "";
    		String userName = "";
    		String content = "";
    		try {
    			
    			//得到接收消息实体
    			BaseMsgReq msgReq = (BaseMsgReq)request.getAttribute("msgReq");
    			openId = msgReq.getFromUserName();
    			content = msgReq.getContent();
    			
    			//得到用户信息实体
    			UserInfo userInfo = (UserInfo)request.getAttribute("userInfo");
    			userName = userInfo.getUserName();
    			
    			log.info("收到消息:" + msgReq.getContent());
    			
    			//更新模块
    			userService.setModule(msgReq.getFromUserName(), ModuleEnum.game24.getValue());
    			
    			//得到game24用户信息实体
    			Game24UserInfo gUserInfo = game24UserService.getByOpenId(userInfo.getOpenId());
    			if(gUserInfo == null) {
    				log.info("新增game24用户");
    				
    				//如果没有就新增
    				gUserInfo = new Game24UserInfo();
    				gUserInfo.setOpenId(userInfo.getOpenId());
    				gUserInfo.setModuleStep(StepEnum.normal.getValue());
    				gUserInfo.setStepTime(new Date());
    				gUserInfo.setIsAnswered(false);
    				game24UserService.add(gUserInfo);
    			}
    			
    			//刷新模块(1小时)
    			long timeDiff = new Date().getTime() - userInfo.getModuleTime().getTime();
    			long hoursDiff = timeDiff / (1000 * 60 * 60);
    			if(hoursDiff >= 1) {
    				game24UserService.setStep(userInfo.getOpenId(), StepEnum.normal.getValue());
    				gUserInfo.setModuleStep(StepEnum.normal.getValue());
    			}
    			
    			log.info("开始转入步骤");
    			//出题
    			if(msgReq.getContent().equals("24")) {
    				
    				//计算上一道题
    				if(!StringUtils.isEmpty(gUserInfo.getQuestionId()) && gUserInfo.getModuleStep().equals(StepEnum.answer.getValue())) {
    					//处理答题结果
    					finishAnswer(gUserInfo, msgReq);
    				}
    				
    				log.info("开始下一题");
    				//下一题
    				Random r = new Random();
    				String questionId = String.valueOf(r.nextInt(403) + 1);
    				gUserInfo.setQuestionId(questionId);
    				gUserInfo.setModuleStep(StepEnum.answer.getValue());
    				gUserInfo.setStepTime(new Date());
    				gUserInfo.setIsAnswered(false);
    				//更新模块
    				game24UserService.update(gUserInfo);
    				//返回题目
    				QuestionInfo questionInfo = questionService.getById(questionId);
    				result = "请听题:" + questionInfo.getNum1() + "、" + questionInfo.getNum2() + "、" + questionInfo.getNum3() + "、" + questionInfo.getNum4();
    				logService.addInfoLog(openId, userName, content, result, ModuleEnum.game24.getValue(), StepEnum.answer.getValue());
    				result = MessageUtil.msgReqToXml(msgReq, result);
    				log.info(result);
    				return result;
    			} 
    			//答案
    			else if(msgReq.getContent().equals("答案")) {
    				
    				//返回答案
    				if(!StringUtils.isEmpty(gUserInfo.getQuestionId())) {
    					
    					log.info("返回答案");
    					
    					//完成答题
    					finishAnswer(gUserInfo, msgReq);
    					
    					//设置步骤
    					gUserInfo.setModuleStep(StepEnum.normal.getValue());
    					gUserInfo.setStepTime(new Date());
    					game24UserService.update(gUserInfo);
    					
    					//答案
    					String answer = questionService.getAnswer(gUserInfo.getQuestionId());
    					logService.addInfoLog(openId, userName, content, answer, ModuleEnum.game24.getValue(), StepEnum.answer.getValue());
    					result = MessageUtil.msgReqToXml(msgReq, answer);
    					log.info(result);
    					return result;
    				}
    			}
    			//排行榜
    			else if(msgReq.getContent().equals("排行") || msgReq.getContent().equals("排行榜")) {
    				
    				log.info("返回排行榜");
    				
    				result += "【排行榜】
    ";
    				
    				boolean flag = false;
    				List<Game24UserInfo> list = game24UserService.getTopScope(1000);
    				if(list != null && list.size() > 0) {
    					for (int i = 0; i < list.size(); i++) {
    						if(list.get(i).getOpenId().equals(gUserInfo.getOpenId())) {
    							flag = true;
    						}
    						//TODO 优化
    						UserInfo sUserInfo = userService.getByOpenId(list.get(i).getOpenId());
    						if(sUserInfo != null) {
    							result += "No." + (i + 1) + " 『" + sUserInfo.getUserName() + "』(" + list.get(i).getScore() + "分)
    ";
    						}
    					}
    				}
    				
    				if(!flag) {
    					result += "No." + (Integer.parseInt(game24UserService.getRankScope(gUserInfo.getScore()))) + " 『" + userInfo.getUserName() + "』(" + gUserInfo.getScore() + "分)";
    				} else {
    					result = result.substring(0, result.length() - 1);
    				}
    				
    				logService.addInfoLog(openId, userName, content, result, ModuleEnum.game24.getValue(), StepEnum.normal.getValue());
    				result = MessageUtil.msgReqToXml(msgReq, result);
    				log.info(result);
    				return result;
    			}
    			
    			//如果是新进来就刷新状态
    			if(msgReq.getContent().equals("24点")) {
    				
    				//完成答题
    				if(!StringUtils.isEmpty(gUserInfo.getQuestionId())) {
    					finishAnswer(gUserInfo, msgReq);
    				}
    				
    				//设置步骤
    				gUserInfo.setModuleStep(StepEnum.normal.getValue());
    				gUserInfo.setStepTime(new Date());
    				game24UserService.update(gUserInfo);
    			}
    			
    			//如果是答题状态
    			if(gUserInfo.getModuleStep().equals(StepEnum.answer.getValue())) {
    				
    				//返回处理答题结果
    				result = finishAnswer(gUserInfo, msgReq);
    				logService.addInfoLog(openId, userName, content, result, ModuleEnum.game24.getValue(), StepEnum.answer.getValue());
    				result = MessageUtil.msgReqToXml(msgReq, result);
    				log.info(result);
    				return result;
    			}
    			
    			//返回game24公告
    			result += "『24点游戏』
    ";
    			result += "【规则】
    ";
    			result += "利用 + - * / ( ) 列出综合算式
    结果是24即可
    ";
    			result += "【说明】
    ";
    			result += "1、输入“24”:开始答题
    ";
    			result += "2、输入“答案”:查看答案
    ";
    			result += "3、输入“排行”:查看排行
    ";
    			result += "4、输入“公告”:返回首页";
    			logService.addInfoLog(openId, userName, content, result, ModuleEnum.game24.getValue(), StepEnum.normal.getValue());
    			result = MessageUtil.msgReqToXml(msgReq, result);
    		} catch (Exception e) {
    			log.debug("执行失败");
    			logService.addErrorLog(openId, userName, content, "", ModuleEnum.game24.getValue(), StepEnum.normal.getValue(), e);
    			e.printStackTrace();
    		}
    		
    		//返回消息
    		log.info(result);
    		return result;
    	}
    	
    	/**
    	 * 处理答题结果
    	 */
    	private String finishAnswer(Game24UserInfo gUserInfo, BaseMsgReq msgReq) {
    		
    		log.info("处理答题结果");
    		
    		String result = "";
    		
    		//题目
    		QuestionInfo questionInfo = questionService.getById(gUserInfo.getQuestionId());
    		
    		//计算
    		String answer = msgReq.getContent();
    		answer = answer.replace("(", "(").replace(")", ")").replace("÷", "/").replace("/", "/").replace("×", "*").replace("-", "-").replace("—", "-").replace(" ", "");
    		//计算表达式结果
    		ScriptEngineManager manager = new ScriptEngineManager();
            ScriptEngine se = manager.getEngineByName("js");
            Double res = (double) 0;
            try {
            	
            	//校对答案
            	boolean flag = true;
            	String nums = answer.replace("(", "").replace(")", "").replace("*", "").replace("/", "").replace("-", "").replace("+", "");
            	if(nums.length() != 4) {
            		flag = false;
            	} else {
    	        	char[] strs = nums.toCharArray();
    	        	Arrays.sort(strs);
    	        	if(!String.valueOf(strs).equals(String.valueOf(questionInfo.getNum1()) + String.valueOf(questionInfo.getNum2()) + String.valueOf(questionInfo.getNum3()) + String.valueOf(questionInfo.getNum4())))
    	        	{
    	        		flag = false;
    	        	}
            	}
            	
            	if(flag) {
            		res =(Double) se.eval(answer);
            	} else {
    				res = 0.0;
    			}
    		} catch (ScriptException e) {
    			log.debug("运算失败");
    			//e.printStackTrace();
    		}
            
            //回答正确
            if(res == 24) {
            	
            	log.info("回答正确");
            	
            	//计算用时
            	long timeDiff = new Date().getTime() - gUserInfo.getStepTime().getTime();
    			long secondsDiff = timeDiff / (1000);
            	
    			int score = 0;
    			//30秒以内加5分
    			if(secondsDiff < 30) {
    				score = 5;
    			} 
    			//60秒以内加3分
    			else if(secondsDiff < 60) {
    				score = 3;
    			} 
    			//加1分
    			else {
    				score = 1;
    			}
    			
    			result = "答对了!用时" + secondsDiff + "s,积分 +" + score;
    			
    			//更新用户积分、次数、答对次数、命中率
    			gUserInfo.setScore(gUserInfo.getScore() + score);
    			gUserInfo.setRightTimes(gUserInfo.getRightTimes() + 1);
    			gUserInfo.setTimes(gUserInfo.getTimes() + 1);
    			NumberFormat numberFormat = NumberFormat.getInstance();
    			numberFormat.setMaximumFractionDigits(2);
    			gUserInfo.setHitRate(Float.valueOf(numberFormat.format((float) gUserInfo.getRightTimes() / (float) gUserInfo.getTimes() * 100)));
    			gUserInfo.setModuleStep(StepEnum.normal.getValue());
    			gUserInfo.setStepTime(new Date());
    			gUserInfo.setIsAnswered(false);
    			
    			//更新试题次数、答对次数、命中率
    			questionInfo.setRightTimes(questionInfo.getRightTimes() + 1);
    			questionInfo.setTimes(questionInfo.getTimes() + 1);
    			numberFormat.setMaximumFractionDigits(2);
    			questionInfo.setHitRate(Float.valueOf(numberFormat.format((float) questionInfo.getRightTimes() / (float) questionInfo.getTimes() * 100)));
            } 
            //回答错误
            else {
            	
            	log.info("回答错误");
            	
            	//如果第一次回答
            	if(!gUserInfo.getIsAnswered()) {
            	
    	        	//更新用户积分、次数、答对次数、命中率
    				gUserInfo.setTimes(gUserInfo.getTimes() + 1);
    				NumberFormat numberFormat = NumberFormat.getInstance();
    				numberFormat.setMaximumFractionDigits(2);
    				gUserInfo.setHitRate(Float.valueOf(numberFormat.format((float) gUserInfo.getRightTimes() / (float) gUserInfo.getTimes() * 100)));
    				gUserInfo.setIsAnswered(true);
    				
    				//更新试题次数、答对次数、命中率
    				questionInfo.setTimes(questionInfo.getTimes() + 1);
    				numberFormat.setMaximumFractionDigits(2);
    				questionInfo.setHitRate(Float.valueOf(numberFormat.format((float) questionInfo.getRightTimes() / (float) questionInfo.getTimes() * 100)));
            	}
            	
            	//gUserInfo.setModuleStep(StepEnum.answer.getValue());
    			//gUserInfo.setStepTime(new Date());
            	
            	result = "错误";
            }
            
            //更新game24用户
            game24UserService.update(gUserInfo);
            
            //更新题目
            questionService.update(questionInfo);
            
    		return result;
    	}
    }

    三、演示地址

    四、源码地址

    https://github.com/ctxsdhy/dntown

  • 相关阅读:
    Markdown编辑器:Typora
    Makefile的编写
    【转】Java基础——成员变量、局部变量和静态变量的区别
    【转】jsp 和 servlet的联系和区别
    【转】keySet和entrySet的区别
    10月25日下午PHP静态、抽象、接口
    10月25日上午PHP继承多态
    10月24日下午PHP封装
    10月24日上午PHP面向对象
    MYSQL存储过程、游标、触发器
  • 原文地址:https://www.cnblogs.com/ctxsdhy/p/5926109.html
Copyright © 2011-2022 走看看