zoukankan      html  css  js  c++  java
  • 微信公众平台开发—成语接龙

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

    一、实现思路

    1、成语接龙题库

    成语接龙的题库比24点的复杂一些,数量也很大,我建的表字段是:"四字成语"、"首字"、"首字拼音"、"尾字"、"尾字拼音"、"全字拼音"、"含义"、"出自"、"例句"这几个,未来可以支持查询读音、含义、出自和例句的功能

    题库来自http://download.csdn.net/index.php/mobile/source/download/opensrc/8385371

    找了很久的,有3w多个成语信息,我把内容拷到excel里,截取了上面需要的字段,然后复制到数据库表里,去掉了重复的和不是四个字的成语,最后数据3w不到一点

    2、接龙方式

    自己试了一下正常的成语接龙(就是首尾字完全一样的接),感觉没几个就接不下去了,所以加入了谐音接龙(首尾字谐音相同)和包含接龙(包含有那个字,不一定是第一个),这样接龙连胜可以长一点

    3、出题

    从29543中取一个随机数,作为成语id,查询成语信息然后返回

    4、计算答案

    (1)首先判断答案是否在题库里面出现(是一个成语)

    (2)判断题目尾字是否和答案首字一样,是就相同匹配,加3分

    (3)判断题目尾字拼音是否和答案首字拼音一样,是就谐音匹配,加1分

    (4)判断题目尾字是否在答案4字中存在,而且题目和答案不是同一个成语,是就包含匹配,加1分

    (5)完成判断以后更新用户的"积分、答题数、答对数、命中率、连胜次数、最长连胜"

    5、再次出题

    根据答案尾字在题库表中查询成语,如果得到一个列表,随机取出一个成语返回(防止每次返回匹配的第一个成语),如果没有结果,就提示"我也接不下去了",用户积分加5..然后重新走开始的出题步骤出下一题

    6、排行榜

    按用户表的积分大小倒序输出排名即可,需要注意的是如果前10名没有当前用户,要再输出一行当前用户的排名。还可以支持最长连胜排行榜

    7、答题状态

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

    和24点游戏不同的是这个是一直接下去的(所以增加了连胜次数和最长连胜字段)

    二、核心源码

    package org.xs.dntown.wx.idiom.modules.web;
    
    import java.util.Date;
    import java.util.List;
    import java.util.Random;
    
    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.idiom.modules.entity.IdiomListInfo;
    import org.xs.dntown.wx.idiom.modules.entity.IdiomUserInfo;
    import org.xs.dntown.wx.idiom.modules.entity.enums.StepEnum;
    import org.xs.dntown.wx.idiom.modules.service.IdiomListService;
    import org.xs.dntown.wx.idiom.modules.service.IdiomUserService;
    
    /**
     * 核心Controller
     */
    @Controller(value = "idiomCoreController")
    @RequestMapping("idiom")
    public class CoreController extends BaseController {
    	
    	@Autowired
    	private IdiomUserService idiomUserService;
    	
    	@Autowired
    	private IdiomListService idiomListService;
    	
    	@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.idiom.getValue());
    			
    			//得到接龙用户信息实体
    			IdiomUserInfo iUserInfo = idiomUserService.getByOpenId(userInfo.getOpenId());
    			if(iUserInfo == null) {
    				log.info("新增接龙用户");
    				
    				//如果没有就新增
    				iUserInfo = new IdiomUserInfo();
    				iUserInfo.setOpenId(userInfo.getOpenId());
    				iUserInfo.setModuleStep(StepEnum.normal.getValue());
    				iUserInfo.setStepTime(new Date());
    				iUserInfo.setIsAnswered(false);
    				idiomUserService.add(iUserInfo);
    			}
    			
    			//刷新模块(1小时)
    			long timeDiff = new Date().getTime() - userInfo.getModuleTime().getTime();
    			long hoursDiff = timeDiff / (1000 * 60 * 60);
    			if(hoursDiff >= 1) {
    				idiomUserService.setStep(userInfo.getOpenId(), StepEnum.normal.getValue());
    				iUserInfo.setModuleStep(StepEnum.normal.getValue());
    			}
    			
    			log.info("开始转入步骤");
    			//出题
    			if(msgReq.getContent().equals("开始")) {
    				
    				//完成上一个成语
    				if(!StringUtils.isEmpty(iUserInfo.getIdiomId()) && iUserInfo.getModuleStep().equals(StepEnum.answer.getValue())) {
    					//处理答题结果
    					disposeAnswer(iUserInfo, msgReq);
    					
    					result += finishAnswer(iUserInfo, msgReq, false) + "
    ";
    				}
    				
    				log.info("开始下一题");
    				
    				//下一题
    				result = nextIdiom(iUserInfo, result);
    				
    				logService.addInfoLog(openId, userName, content, result, ModuleEnum.idiom.getValue(), StepEnum.answer.getValue());
    				result += MessageUtil.msgReqToXml(msgReq, result);
    				log.info(result);
    				return result;
    			}
    			//答案
    			else if(msgReq.getContent().equals("答案") && iUserInfo.getModuleStep().equals(StepEnum.answer.getValue())) {
    				
    				//返回答案
    				if(!StringUtils.isEmpty(iUserInfo.getIdiomId())) {
    					
    					log.info("返回答案");
    					
    					//完成答题
    					result += finishAnswer(iUserInfo, msgReq, true);
    					
    					//设置步骤
    					iUserInfo.setModuleStep(StepEnum.normal.getValue());
    					iUserInfo.setStepTime(new Date());
    					idiomUserService.update(iUserInfo);
    					
    					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("排行") || msgReq.getContent().equals("排行榜")) {
    				
    				log.info("返回排行榜");
    				
    				result += "【排行榜】
    ";
    				
    				boolean flag = false;
    				List<IdiomUserInfo> list = idiomUserService.getTopScope(1000);
    				if(list != null && list.size() > 0) {
    					for (int i = 0; i < list.size(); i++) {
    						if(list.get(i).getOpenId().equals(iUserInfo.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(idiomUserService.getRankScope(iUserInfo.getScore()))) + " 『" + userInfo.getUserName() + "』(" + iUserInfo.getScore() + "分)";
    				} else {
    					result = result.substring(0, result.length() - 1);
    				}
    				
    				logService.addInfoLog(openId, userName, content, result, ModuleEnum.idiom.getValue(), StepEnum.normal.getValue());
    				result = MessageUtil.msgReqToXml(msgReq, result);
    				log.info(result);
    				return result;
    			}
    			
    			//如果是新进来就刷新状态
    			if(msgReq.getContent().equals("接龙")) {
    				
    				//完成答题
    				if(!StringUtils.isEmpty(iUserInfo.getIdiomId())) {
    					finishAnswer(iUserInfo, msgReq, true);
    				}
    				
    				//设置步骤
    				iUserInfo.setModuleStep(StepEnum.normal.getValue());
    				iUserInfo.setStepTime(new Date());
    				idiomUserService.update(iUserInfo);
    			}
    			
    			//如果是答题状态
    			if(iUserInfo.getModuleStep().equals(StepEnum.answer.getValue())) {
    				
    				//返回处理答题结果
    				result = disposeAnswer(iUserInfo, msgReq);
    				logService.addInfoLog(openId, userName, content, result, ModuleEnum.idiom.getValue(), StepEnum.answer.getValue());
    				result = MessageUtil.msgReqToXml(msgReq, result);
    				log.info(result);
    				return result;
    			}
    			
    			//返回接龙公告
    			result += "『成语接龙』
    ";
    			result += "【规则】
    ";
    			result += "有3种接龙方式:
    ";
    			result += "与尾字相同接龙,积分+3
    ";
    			result += "与尾字谐音接龙,积分+1
    ";
    			result += "包含尾字接龙,积分+1
    ";
    			result += "连胜有积分奖励
    ";
    			result += "【说明】
    ";
    			result += "1、输入“开始”:开始答题
    ";
    			result += "2、输入“答案”:完成答题
    ";
    			result += "3、输入“排行”:查看排行
    ";
    			result += "4、输入“公告”:返回首页";
    			logService.addInfoLog(openId, userName, content, result, ModuleEnum.idiom.getValue(), StepEnum.normal.getValue());
    			result = MessageUtil.msgReqToXml(msgReq, result);
    		} catch (Exception e) {
    			log.debug("执行失败");
    			logService.addErrorLog(openId, userName, content, "", ModuleEnum.idiom.getValue(), StepEnum.normal.getValue(), e);
    			e.printStackTrace();
    		}
    		
    		//返回消息
    		log.info(result);
    		return result;
    	}
    	
    	/**
    	 * 获得下一题
    	 */
    	private String nextIdiom(IdiomUserInfo iUserInfo, String result) {
    		//下一题
    		Random r = new Random();
    		String questionId = String.valueOf(r.nextInt(29543) + 1);
    		iUserInfo.setIdiomId(questionId);
    		iUserInfo.setModuleStep(StepEnum.answer.getValue());
    		iUserInfo.setStepTime(new Date());
    		iUserInfo.setIsAnswered(false);
    		//更新模块
    		idiomUserService.update(iUserInfo);
    		//返回题目
    		IdiomListInfo idiomListInfo = idiomListService.getById(questionId);
    		if(!StringUtils.isEmpty(result)) {
    			result += "
    ";
    		}
    		result += idiomListInfo.getWord();
    		return result;
    	}
    	
    	/**
    	 * 处理答题结果
    	 */
    	private String disposeAnswer(IdiomUserInfo iUserInfo, BaseMsgReq msgReq) {
    		
    		log.info("处理答题结果");
    		
    		String result = "";
    		boolean flag = true;
    		int score = 0;
    		
    		//上一个成语
    		IdiomListInfo idiomListInfo = idiomListService.getById(iUserInfo.getIdiomId());
    		
    		//获得回答的成语
    		IdiomListInfo idiomAnswerInfo = idiomListService.getByWord(msgReq.getContent());
    		
    		//没有这个成语
    		if(idiomAnswerInfo == null) {
    			result = "这不是成语吧";
    			flag = false;
    		} else {
    			
    			//判断是否匹配
    			//如果是相同匹配
    			if(idiomListInfo.getWordEnd().equals(idiomAnswerInfo.getWordBegin())) {
    				result = "答对了,积分+3
    ";
    				flag = true;
    				score = 3;
    			}
    			//如果是谐音匹配
    			else if(idiomListInfo.getWordEndSpell().equals(idiomAnswerInfo.getWordBeginSpell())) {
    				result = "答对了,谐音,积分+1
    ";
    				flag = true;
    				score = 1;
    			}
    			//如果是包含匹配
    			else if(idiomAnswerInfo.getWord().indexOf(idiomListInfo.getWordEnd()) > -1) {
    				if(idiomListInfo.getId().equals(idiomAnswerInfo.getId())) {
    					//不能是同一个成语
    					result = "不能是同一个成语";
    					flag = false;
    				} else {
    					result = "答对了,包含,积分+1
    ";
    					flag = true;
    					score = 1;
    				}
    			}
    			//不匹配
    			else {
    				result = "成语没接上";
    				flag = false;
    			}
    		}
    		
    		//回答正确
    		if(flag) {
    			
    			log.info("回答正确");
    			
        		//下一题
        		idiomListInfo = idiomListService.getNextIdiom(idiomAnswerInfo.getWordEnd());
        		if(idiomListInfo != null) {
        			iUserInfo.setIdiomId(idiomListInfo.getId());
        			iUserInfo.setStepTime(new Date());
        			iUserInfo.setIsAnswered(false);
        			
        			//返回题目
        			if(!StringUtils.isEmpty(result)) {
        				result += "
    ";
        			}
        			result += idiomListInfo.getWord();
        		} else {
        			result += "我接不下去了,积分+5
    ";
        			score += 5;
        			result = nextIdiom(iUserInfo, result);
        		}
        		
        		//更新用户积分、次数、答对次数、连胜次数、最长连胜
    			iUserInfo.setScore(iUserInfo.getScore() + score);
    			iUserInfo.setRightTimes(iUserInfo.getRightTimes() + 1);
    			iUserInfo.setTimes(iUserInfo.getTimes() + 1);
    			iUserInfo.setComboTimes(iUserInfo.getComboTimes() + 1);
        		if(iUserInfo.getComboTimes() > iUserInfo.getBestTimes()) {
        			iUserInfo.setBestTimes(iUserInfo.getComboTimes());
        		}
        		iUserInfo.setStepTime(new Date());
        		iUserInfo.setIsAnswered(false);
    		}
    		//回答错误
    		else {
    			
    			log.info("回答错误");
    			
    			//如果第一次回答
            	if(!iUserInfo.getIsAnswered()) {
            	
    	        	//更新用户积分、次数、答对次数、连胜次数、最长连胜
            		iUserInfo.setTimes(iUserInfo.getTimes() + 1);
            		iUserInfo.setIsAnswered(true);
            	}
    		}
    		
    		//更新接龙用户
    		idiomUserService.update(iUserInfo);
    		
    		return result;
    	}
    	
    	/**
    	 * 完成答题
    	 */
    	private String finishAnswer(IdiomUserInfo iUserInfo, BaseMsgReq msgReq, boolean flag) {
    		
    		log.info("完成答题");
    		
    		String result = "";
    		
    		//上一个成语
    		IdiomListInfo idiomListInfo = idiomListService.getById(iUserInfo.getIdiomId());
    		
    		//下一题
    		if(flag) {
    			idiomListInfo = idiomListService.getNextIdiom(idiomListInfo.getWordEnd());
    			if(idiomListInfo != null) {
    				result += "答案:" + idiomListInfo.getWord() + "
    
    ";
    			} else {
    				result += "答案我也不知道
    
    ";
    			}
    		}
    		
    		int score = 0;
    		
    		int comboTimes = iUserInfo.getComboTimes();
    		if(comboTimes > 1) {
    			int rank = comboTimes / 5 + 1;
    			score += Math.pow(2, rank);
    		}
    		
    		//更新用户积分、次数、答对次数、连胜次数、最长连胜
    		iUserInfo.setScore(iUserInfo.getScore() + score);
    		iUserInfo.setStepTime(new Date());
    		iUserInfo.setIsAnswered(false);
    		iUserInfo.setComboTimes(0);
    		
    		//更新接龙用户
    		idiomUserService.update(iUserInfo);
    		
    		result += "答对" + comboTimes + "题,连胜奖励积分+" + score;
    		return result;
    	}
    }
    

    三、演示地址

    四、源码地址

    https://github.com/ctxsdhy/dntown

  • 相关阅读:
    【BZOJ3110】K大数查询(权值线段树套线段树+标记永久化,整体二分)
    【BZOJ3669】魔法森林(LCT)
    art-template前端高性能模板
    spring新心得
    工作流程
    idea操作
    log4j学习
    对实体 "useSSL" 的引用必须以 ';' 分隔符结尾。
    JUnit4学习
    maven搭建
  • 原文地址:https://www.cnblogs.com/ctxsdhy/p/5926118.html
Copyright © 2011-2022 走看看