序)沉迷游戏,只因不安于现状却又无法改变已逝的过去

  昨天下午开始做一些细化的东西,其中就包括了用户注册的时候,系统随机分配一个昵称,这样的情况几乎在所有游戏中都可见到,不算什么稀奇的东西,策划要求的是只有汉字,必须看着像名字,不能重复,这样我最开始想的直接随机产生x个汉字的想法看来就太简单了,并且很多游戏的随机昵称看着还像模像样,确实是一个名字。

  另外在这里还有个细节问题,当用户打开注册界面选择角色的时候从服务器获得了唯一性的角色名后,该角色名则不能再分配给其他人,当用户注册后则与之绑定,如果用户选择刷新重新获取角色名,则之前角色名如何处置?当然有两种方案:

  1)直接丢掉,只要分配了即使用户没有绑定该角色名也废弃

  2)丢回池里,可再分配给其他人

  第一种情况使用率太低,当太多用户不停刷的时候,使用率更低了,于是我觉得第二种比较好,鉴于名字要像模像样这样的情况看来必须走词库进行组合了,当然百家姓要拉下来,于是我自己动手整理了如下三个文件:

  

  依次为:姓氏  ---->  女性角色名  ----> 男性角色名

  之所以要把男女分开,那是因为男性老是分配到柔柔,瑶瑶,这样的昵称,估计瞬间就会开口大骂,为了我少挨点骂,于是把他们分开了,另外由于词库比较大,组合后的数据更加大,这样的分开也能够提高速度,在刚刚开始的时候我犯了一个很大的错误,那就是把问题想简单了,我最开始的想法是:

  1)根据性别从woman.txt或者man.txt里随机选择一个名字,再随机在姓氏文件中选取一个姓氏,组合成名字

  2)判断该角色名是否已经被注册,如果已经被注册,跳转到1

  3)判断该角色是否存在于Set集合(个Set集合用来保存当前已经分配出去的,但是用户还未绑定的角色名)

  4)丢入Set集合,发给客户端

  5)用户刷新角色则将该角色从Set移除,以便复用

  做完后客户端测试了从功能上讲没啥问题,但是做完后马上自己就发现这里有很大的问题,首先走了词库,有IO问题,这里的词库男女不同的角色名分别各有100万左右,其次当用户数量太大的时候,剩下的未使用的角色名被抽中的概率会变得很小很小,越靠后分配时间越久,特别是词库快要耗尽的时候,剩下未分配的名称几乎不会再被分配到,甚至会死在这里,想到这里瞬间精神了,粗心害死人啊。

  于是打算重写这一块,首先不能使用随机数,随机就会出问题,另外因为词库的大小,正式上线的时候根据词库组合出来的用户名可能会有上千万,因此这样的数据肯定不能直接丢内存,于是我的大概处理方式如下:

  1)分别创建男性角色名表与女性角色名表,将所有昵称初始化到数据库,作为一个池。

  2)分别创建男性角色名视图与女性角色名视图

  3)服务器启动后初始化角色名表的数据,保证里面都是没有被分配的数据

  4)初始化男性与女性昵称访问游标,游标与数据库里的行index对应

  5)每次用户请求随机昵称的时候将游标的位置下移一位,取出里面的值发给客户端

  6)即使用户不使用该名字,要求刷新名字,游标依旧保持下移

  

  这样游标始终取一下个值,则肯定不会重复,省掉了取出了还要和数据库比对的情况,并且这里的游标一定不能后退,否则就会出现一个用户刷新昵称不停在两个昵称中切换的情况,这样估计就要骂娘了,这样做了后还有几个问题就是如何保证使用率,就是游标移过了,但是该昵称没有被使用的数据,能够再次被分配到,于是我的想法是刷新数据表,重置游标位置。每天或者每周刷新一次表,重置游标位置为1,这样则可合理使用里面的数据。

  这里还要处理一些其他并发问题,比如游标移动要保证唯一,另外刷新后台数据表的时候不能让游标移动,否则会出现脏数据。

  实现取随机昵称的代码:

  

  private volatile int currentMaleRoleNameCursorIndex = 1;private volatile int currentFemaleRoleNameCursorIndex = 1;private Lock lock = new ReentrantLock();private Condition condition = lock.newCondition();private boolean isRefurbish = false;public static final int DEFAULT_INDEX_VALUE = 1;private interface SexType {int WOMAN = 0;int MAN = 1;}public String getRandomRoleName(int sex) {try {lock.lock();while (isRefurbish) {condition.await();}String name = null;switch (sex) {case SexType.MAN:name = this.jdbcAccess.findString("select * from v_male_role_name_table where index = ?", currentMaleRoleNameCursorIndex, sex);currentMaleRoleNameCursorIndex += 1;break;case SexType.WOMAN:name = this.jdbcAccess.findString("select * from v_female_role_name_table where index = ?", currentFemaleRoleNameCursorIndex, sex);currentFemaleRoleNameCursorIndex += 1;break;default:break;}return StringUtils.hasText(name) ? name : "notFound";} catch (Exception e) {e.printStackTrace();return "error";} finally {lock.unlock();}}

  Quartz中的任务每天刷新池里的数据:

  

  @Injectprivate RandomHan randomHan;private static class RoleItems {private int id;private String name;public static RoleItems setValues(ResultSet resultSet) throws SQLException {RoleItems item = new RoleItems();item.id = resultSet.getInt("id");item.name = resultSet.getString("name");return item;}}public void refurbishRandomNameTable() {randomHan.setRefurbish(true);List<RoleItems> cacheMaleNameItems = this.jdbcAccess.find("select t.id, t.name from v_male_role_name_table where 1 = 1 and index <= ?", new RowMapper<RoleItems>() {@Overridepublic RoleItems mapRow(ResultSet resultSet, int rowNum) throws SQLException {return RoleItems.setValues(resultSet);}}, randomHan.getCurrentMaleRoleNameCursorIndex());for (RoleItems item : cacheMaleNameItems) {if (isExistRoleName(item.name)) {this.jdbcAccess.execute("delete from male_role_name_table where id = ?", item.id);}}randomHan.setCurrentMaleRoleNameCursorIndex(RandomHan.DEFAULT_INDEX_VALUE);List<RoleItems> cacheFemaleNameItems = this.jdbcAccess.find("select t.id, t.name from v_female_role_name_table where 1 = 1 and index <= ?", new RowMapper<RoleItems>() {@Overridepublic RoleItems mapRow(ResultSet resultSet, int rowNum) throws SQLException {return RoleItems.setValues(resultSet);}}, randomHan.getCurrentMaleRoleNameCursorIndex());for (RoleItems item : cacheFemaleNameItems) {if (isExistRoleName(item.name)) {this.jdbcAccess.execute("delete from female_role_name_table where id = ?", item.id);}}randomHan.setCurrentFemaleRoleNameCursorIndex(RandomHan.DEFAULT_INDEX_VALUE);randomHan.setRefurbish(false);}private boolean isExistRoleName(String nickName) {return this.jdbcAccess.findInteger("select count(*) from player_role where nick_name = ?", nickName) > 0;}

  数据库基本操作自己重新封装了下,如下:

public class JDBCAccess {private final Logger logger = LoggerFactory.getLogger(JDBCAccess.class);private JdbcTemplate jdbcTemplate;public <T> List<T> find(String sql, RowMapper<T> rowMapper, Object... params) {StopWatch watch = new StopWatch();try {return jdbcTemplate.query(sql, params, rowMapper);} finally {logger.debug("find, sql={}, params={}, elapsedTime={}", new Object[]{sql, params, watch.elapsedTime()});}}public <T> T findUniqueResult(String sql, RowMapper<T> rowMapper, Object... params) {StopWatch watch = new StopWatch();try {return jdbcTemplate.queryForObject(sql, params, rowMapper);} finally {logger.debug("findUniqueResult, sql={}, params={}, elapsedTime={}", new Object[]{sql, params, watch.elapsedTime()});}}public int findInteger(String sql, Object... params) {StopWatch watch = new StopWatch();try {return jdbcTemplate.queryForInt(sql, params);} finally {logger.debug("findInteger, sql={}, params={}, elapsedTime={}", new Object[]{sql, params, watch.elapsedTime()});}}public boolean findBooleanFiled(String sql, Object... params) {StopWatch watch = new StopWatch();try {return jdbcTemplate.queryForObject(sql, params, new RowMapper<Boolean>() {@Overridepublic Boolean mapRow(ResultSet resultSet, int rowNum) throws SQLException {return resultSet.getBoolean(1);}});} catch(Exception e) {return false;} finally {logger.debug("findString, sql={}, params={}, elapsedTime={}", new Object[]{sql, params, watch.elapsedTime()});}}public Long findLongFiled(String sql, Object... params) {StopWatch watch = new StopWatch();try {return jdbcTemplate.queryForObject(sql, params, new RowMapper<Long>() {@Overridepublic Long mapRow(ResultSet resultSet, int rowNum) throws SQLException {return resultSet.getLong(1);}});} finally {logger.debug("findString, sql={}, params={}, elapsedTime={}", new Object[]{sql, params, watch.elapsedTime()});}}public int findIntegerFiled(String sql, Object... params) {StopWatch watch = new StopWatch();try {return jdbcTemplate.queryForObject(sql, params, new RowMapper<Integer>() {@Overridepublic Integer mapRow(ResultSet resultSet, int rowNum) throws SQLException {return resultSet.getInt(1);}});} catch (Exception e) {return -1;}  finally {logger.debug("findString, sql={}, params={}, elapsedTime={}", new Object[]{sql, params, watch.elapsedTime()});}}public String findString(String sql, Object... params) {StopWatch watch = new StopWatch();try {return jdbcTemplate.queryForObject(sql, params, new RowMapper<String>() {@Overridepublic String mapRow(ResultSet resultSet, int rowNum) throws SQLException {return resultSet.getString(1);}});} finally {logger.debug("findString, sql={}, params={}, elapsedTime={}", new Object[]{sql, params, watch.elapsedTime()});}}public int execute(String sql, Object... params) {StopWatch watch = new StopWatch();try {return jdbcTemplate.update(sql, params);} finally {logger.debug("execute, sql={}, params={}, elapsedTime={}", new Object[]{sql, params, watch.elapsedTime()});}}public int[] batchExecute(String sql, List<Object[]> params) {StopWatch watch = new StopWatch();try {return jdbcTemplate.batchUpdate(sql, params);} finally {logger.debug("batchExecute, sql={}, params={}, elapsedTime={}", new Object[]{sql, params, watch.elapsedTime()});}}public void setDataSource(DataSource dataSource) {jdbcTemplate = new JdbcTemplate(dataSource);}public JdbcTemplate getJdbcTemplate() {return jdbcTemplate;}
}

  这里还有一个问题,那就是用户刷新昵称后应该是不一样的姓氏的昵称,这个可以使用游标解决,也可是在初始化数据里做手脚,不过再说吧,总觉得这个东西自己也搞的很挫了,先在这里记录下吧。。。

  

    

转载于:https://www.cnblogs.com/bfchuan/p/4283816.html

(原)游戏用户注册之随机昵称系统相关推荐

  1. unity2d随机生成物体_unity2D游戏关卡地图编辑随机生成系统Strata Easy 2D Level Generator 1.3...

    unity2D游戏关卡地图编辑随机生成系统Strata Easy 2D Level Generator 1.3,是一个易于使用的程序工具包,用于使用手动和随机生成2D关卡场景.它可以在Unity编辑器 ...

  2. java 随机昵称_Java随机产生中文昵称

    有时候我们注册一个网站第一次登陆系统会产生一个随机昵称供用户选择,在项目测试阶段遇到了这个问题,因为注册时没有让用户填写昵称,于是找了两种产生随机中文昵称的方法: 代码如下 package com.u ...

  3. 让《弹射世界》告诉你,二次元游戏该如何打造社交系统?

    编者按:近几年,二次元游戏发展势头良好,但你知道二次元游戏是怎么做社交系统的吗?本文作者分析了日本Cygames出品的<弹射世界>的社交系统,或许会对您有所启发. <弹射世界> ...

  4. C#:获取随机昵称实现

    获取随机昵称实现 前言:游戏中关于用户取名的问题,多数情况下,玩家默认是随机取名的(也会有自己取名的),那这个随机昵称的获取怎么实现呢?先理一下思路~ 实现思路: 首先,你得有一个昵称集合的数据,并把 ...

  5. 超赞随机点名系统(抽奖系统),快来看看是不是你想要的(附完整源码)

    名称:随机点名系统 新人在线求点赞,有什么建议也可以在评论里告诉我哦~ 需求及功能: 1.点击按钮开始随机,再次点击按钮停止随机: 2.已经被随机到的下一次开始随机时将不能再被随机到: 3.随机的位数 ...

  6. 帧同步_微信小游戏接入“熊孩子噩梦”健康系统 帧同步能力上线

    3月31日,微信小游戏官方公众号"做个小游戏"发文宣布全新面向未成年人保护的健康系统已经上线,该系统联动"成长守护平台"的功能,可以更好助力家长群体对于未成年人 ...

  7. 自动点名系统c语言,用C语言编写一个随机点名系统

    /*编写一个随机点名系统,运行该系统后,按空格键可以显示出一名同学,以前被选中的同学,将不会再次被选中*/ #include /*standard input & output*/ #incl ...

  8. python循环10次_开发一个循环 5 次计算的小游戏, 设置随机种子为10,每次随机产生两个 1~10的数字以及随机选择...

    开发一个循环 5 次计算的小游戏, 设置随机种子为10,每次随机产生两个 1~10的数字以及随机选择 "+.-.*"运算符,构成一个表达式, 让用户计算式子结果并输入结果,如果计算 ...

  9. 游戏服务器系统是什么意思,游戏服务器都是什么系统

    游戏服务器都是什么系统 内容精选 换一换 华为云帮助中心,为用户提供产品简介.价格说明.购买指南.用户指南.API参考.最佳实践.常见问题.视频帮助等技术文档,帮助您快速上手使用华为云服务. 云游戏作 ...

最新文章

  1. oracle服务器找不到怎么解决,简析Oracle数据库常见问题及解决方案
  2. 【洛谷 P1659】 [国家集训队]拉拉队排练(manacher)
  3. 【牛客 - 82B】区间的连续段(贪心,建图,倍增)
  4. 重磅!GitHub发布年度机器学习榜:TensorFlow最火,PyTorch消失!
  5. 利用维纳滤波编码实现给定的运动模糊图像恢复
  6. MapReduce案例一:天气温度
  7. php顺序查找法,php二分查找、顺序查找算法
  8. 4线电子围栏安装示意图_红外对射、电子围栏、振动光纤、智能警戒4种常用的周界安防系统...
  9. cholesky分解_Time Series Analysis-1.2 LDL分解
  10. jmeter安装插件的方法
  11. html解决ajax调用跨域,JQuery Ajax执行跨域请求数据的解决方案
  12. 版本设置X:none node Title golang版本错误
  13. win7动态壁纸_壁纸软件推荐-wallpaper engine
  14. 在开发板显示24位的bmp格式图片
  15. codec2中的函数命名后缀vb nb sm
  16. 上海亚商投顾大盘回顾:两市成交仅5600亿元 创两年半以来新低
  17. eclipse Android添加权限
  18. 让MySQL远程用户访问的方法
  19. java基于springboot家庭水电燃气网上交费系统
  20. 禾川科技通过注册:拟募资8亿 达晨与国弘投资是股东

热门文章

  1. 撰写生活(学习向) - 好久不见 持续更新 21/03/15
  2. 鸿蒙狙击谷歌,全面狙击华为鸿蒙OS系统!谷歌霸气联手三星:发布新版鸿蒙OS系统...
  3. VC10如何在Release模式下调试代码
  4. 撇开泡沫,看智能家居联盟乱象
  5. 大学面试三分钟自我介绍七篇
  6. 沙城怒火--ios技术支持
  7. GTX1660Ti 本地部署 Stable Diffusion踩坑记录
  8. tess_two Android图片文字识别
  9. 微信支付宝刷脸支付积极助力行业效率提升
  10. this:它到底指向哪里!箭头函数的this又是啥?