zhangxinxu/quiz

JS基础测试31

Opened this issue · 28 comments

本期小测题目如下:

看上去简单,又好像不是很简单,很有意思的一道题目。

大家提交回答的时候,注意缩进距离,起始位置从左边缘开始;另外,github自带代码高亮,所以请使用下面示意的格式。

```js
// 你的JS代码写在这里
 ```

其它:

  1. 首位答题者可获得额外2积分和直播翻牌机会;
  2. 预留了2积分的缓冲附加费,精妙算法实现可以获得;
  3. 本次答疑直播为4月27日(周六)上午10:00;
<script src="//cdnjs.cloudflare.com/ajax/libs/seedrandom/2.4.0/seedrandom.min.js"></script>

用userId做seed,通过不断取随机值生成数组

let myrng = new Math.seedrandom(userId)
let ruslt_arr = [];
let sum = 1+2+3+4+5+6+7+8+9;
while(true){
  let num = Math.floor(myrng()*10);
  console.log(num)
  if(ruslt_arr.indexOf(num) === -1){
    ruslt_arr.push(num);
    sum-=num;
  }
  if(ruslt_arr.length === 9){
    ruslt_arr.push(sum);
    break
  }
}

预期是达到了,就是算法复杂度有点高了…… > 测试 DEMO <

function getRandomSkins(uid, skins) {
  skins = skins instanceof Array ? skins : [];

  if (!uid) {
    return skins;
  }

  // 1.将 uid 的每个字符串元字符转换为编码值,组合成一个数字
  var charCodes = String(uid).split('').reduce(function(total, cur) {
    return total + (isNaN(cur) ? cur.charCodeAt() : cur);
  }, '');

  // 2.使用上一步生成的数字生成一个和皮肤数组长度一致的字符串数字
  var seed = String(Math.sin(charCodes)).split('.')[1].substr(0, skins.length);      

  // 3.将上一步生成的字符串数字打散添加到皮肤数组的每一项中,用于排序
  var result = skins.map(function(item, idx) {
    item._order = Number(seed[idx]);
    return item;
  });

  return (
    // 4.根据 order 排序
    result.sort(function(o, p) {
      return o._order - p._order;
    })
    
    // 5.移除 order,还原数组本来面貌
    .map(function(item) {
      delete item._order;
      return item;
    })
  )
}

整体思路:用localStorage或者session进行存储

//皮肤库
		var arr = [{skin:1},{skin:2},{skin:3},{skin:4},{skin:5},{skin:6},{skin:7},{skin:8},{skin:9},{skin:10}]
		
		//产生随机6位数字id
		function random6(){
			let userId = "";
			for(let i=0;i<6;i++){
				userId += Math.floor(Math.random()*10);
			}
			return userId;
		}
		
		//对数组随机排序
		function randomsort(a, b) {
			return Math.random()>.5 ? -1 : 1;
		}
		//获取皮肤库长度并顺序将其加入数组
		function arrLen(skins){
			a = []
			for(let i=0;i<skins.length;i++){
				a += i;
			}
			return a;
		}

		//如果有userId,将10个皮肤进行一次随机排序并存储至 {localStorage.userSkins}
		if(localStorage.userId){
			if(!localStorage.userSkins){
				localStorage.setItem("userId", random6());
				localStorage.setItem("userSkins", JSON.stringify(arr.sort(randomsort)));
			}else {
				alert(localStorage.userSkins);
			}
		}else {
			//如果没有userId,产生一个6位随机数字id,然后再将10个皮肤随机顺序存入(同上)
			localStorage.userId = random6();
			localStorage.userSkins = JSON.stringify(arr.sort(randomsort));
		}

		//测试
		console.log(localStorage.userId,localStorage.userSkins);

源代码

class RandomCenter {
  // 增加userId
  set(userid) {
    const storage = localStorage.getItem(userid);
    if (!storage) {
      let skinList = this.shuffle();
      console.log(skinList);
      localStorage.setItem(userid, JSON.stringify(skinList));
    } else {
      console.log("请通过get直接获取随机皮肤");
    }
  }

  // 取对应userid的排序队列
  get(userid) {
    if (!userid) return;
    return JSON.parse(localStorage.getItem(userid));
  }

  // 随机产生等概率分布的数组队列
  shuffle() {
    let skinList = [
      { skin: 1 },
      { skin: 2 },
      { skin: 3 },
      { skin: 4 },
      { skin: 5 },
      { skin: 6 },
      { skin: 7 },
      { skin: 8 },
      { skin: 9 },
      { skin: 10 }
    ];
    let len = skinList.length;
    for (let i = len - 1; i >= 0; i--) {
      let randomIndex = Math.floor(Math.random() * (i + 1));
      let itemAtIndex = skinList[randomIndex];
      skinList[randomIndex] = skinList[i];
      skinList[i] = itemAtIndex;
    }
    return skinList;
  }
}

let randomCenter = new RandomCenter();
randomCenter.set('a123');
let skinSort = randomCenter.get('a123');
console.log(skinSort);

方式一

在知乎看到过类似的,可以生成一个伪随机数
需要注意的是id必须为数字

var arr = [{skin:1},{skin:2},{skin:3},{skin:4},{skin:5},{skin:6},{skin:7},{skin:8},{skin:9},{skin:10}];

function rnd( seed ){
    seed = ( seed * 9301 + 49297 ) % 233280; 
    return seed / ( 233280.0 ) * 10e17;
};

function rndskin(uid,arr){
    var rules = rnd(uid)+'';
    return arr.map(function(el,index){
        el.index = +rules[index];
        return el;
    }).sort(function(a,b){
        return a.index-b.index;
    })
}

rndskin(312,arr);
rndskin(312,arr);

rndskin(222,arr);
rndskin(222,arr);

方式二

借助localStorage保存排序,但是只能在浏览器环境使用

var arr = [{skin:1},{skin:2},{skin:3},{skin:4},{skin:5},{skin:6},{skin:7},{skin:8},{skin:9},{skin:10}]

function rndskin(uid,arr){
    var rules = [0,1,2,3,4,5,6,7,8,9];
    if(!localStorage['uid_'+uid]){
        rules = rules.sort(function(){
            return Math.random()-0.5;
        })
        localStorage['uid_'+uid] = rules.join(',');
    }else{
        rules = localStorage['uid_'+uid].split(',');
    }
    return arr.map(function(el,index){
        el.index = +rules[index];
        return el;
    }).sort(function(a,b){
        return a.index-b.index;
    })
}

rndskin(312,arr);
rndskin(312,arr);

rndskin(222,arr);
rndskin(222,arr);

数组乱序后使用 localStorge 存储数据
Demo in CodePen

    <h1>当前的userid为</h1>
    <input type="text" value="10" />
    <button onclick="randomArray()">确定</button>
    <h1>当前顾客的皮肤的顺序为</h1>
    <div class="answer"></div>
      const NUM = 10
      const MANLENGTH = Array(10)
        .fill('')
        .reduce((total, v, index) => (index + 1) * total, 1)
      const cache = localStorage.getItem('userList')
      const cacheUser = localStorage.getItem('user')
      var exist = localStorage.getItem('exist') || ''
      const userList = cache ? JSON.parse(cache) : {}
      var userId

      if (cacheUser === null) {
        userId = (Math.random() * 1000) >> 0
        localStorage.setItem('user', userId)
      } else {
        userId = cacheUser
      }
      // 生成随机皮肤

      function getRandomArr() {
        var skins = Array(NUM)
          .fill()
          .map((v, index) => ({ skin: index + 1 }))
        function swap(a, b) {
          ;[skins[a], skins[b]] = [skins[b], skins[a]]
        }
        for (let i = 0; i < NUM - 1; i++) {
          const seed = ((Math.random() * (NUM - i)) >> 0) + i
          swap(seed, i)
        }
        var existStr = skins.map(v => v.skin).join('#') + '$'
        if (exist.indexOf(existStr) === -1) {
          return [skins, existStr]
        } else {
          return getRandomArr()
        }
      }

      function randomArray() {
        userId = document.querySelector('input').value
        localStorage.setItem('user', userId)
        if (!userId) {
          userId = (Math.random() * 1000) >> 0
          localStorage.setItem('user', userId)
        }
        document.querySelector('input').value = userId
        // 防止死循环
        if (userList[userId] || MANLENGTH < Object.keys(userList).length) {
          return
        }

        var skins = getRandomArr()
        exist += skins[1]
        document.querySelector('.answer').innerHTML = JSON.stringify(skins[0])
        userList[userId] = skins[0]
        localStorage.setItem('exist', exist)
        localStorage.setItem('userList', JSON.stringify(userList))
      }

      window.onload = () => {
        document.querySelector('input').value = userId
        if (cache) {
          if (userId && userList[cacheUser]) {
            document.querySelector('.answer').innerHTML = JSON.stringify(
              userList[cacheUser],
            )
          } else {
            randomArray()
          }
        } else {
          randomArray()
        }
      }

乘法散列+康托展开

//1!-10!阶乘
const fac=[ 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800 ]
//逆康托展开
let decantor=(index)=>{
    var quot,remain=index,result=[1,2,3,4,5,6,7,8,9,10],revId
    for(var i=0;i<9;i++){
        quot=parseInt(remain/fac[10-i-1])
        remain=remain%fac[10-i-1]
        revId=result.slice(i,10).sort((a,b)=>a-b)[quot]
        result[result.indexOf(revId)]=result[i]
        result[i]=revId
    }
    return result
}
//userId 要映射到 全排列=10!个槽中
let hash=(number)=>fac[10]*(0.6180339887*number%1)
//主函数
let getSkinByUserId=(userId)=>{
    userId=parseInt((userId+'').split('').map(v=>v.charCodeAt(0).toString(16)).join(''),16)%1e15
    return decantor(hash(userId)).map(v=>({skin:v}))
}

skin=getSkinByUserId(1)
console.log(skin)
//话不多说洗牌算法
function shuffle(arr) {
    for (var i = arr.length - 1; i >= 0; i--) {
        var index = Math.floor(Math.random() * (i + 1));
        arr[i] = arr.splice(index, 1, arr[i])[0];
    }
    return arr;
}

var userId = 'uid57392028';
var arr = [{skin: 1}, {skin: 2}, {skin: 3}, {skin: 4}, {skin: 5}, {skin: 6}, {skin: 7}, {skin: 8}, {skin: 9}];
var skin = [];
if (localStorage.getItem('userId') === userId) {
    skin = JSON.parse(localStorage.getItem('skin'));
} else {
    localStorage.setItem('userId', userId);
    skin = shuffle(arr);
    localStorage.setItem('skin', JSON.stringify(shuffle(arr)));
}
console.log(skin);

首先是线性同余方法,生成统计学伪随机数

const sequence = (uid) => {
  const arr = [{ skin: 1 }, { skin: 2 }, { skin: 3 }, { skin: 4 }, { skin: 5 }, { skin: 6 }, { skin: 7 }, { skin: 8 }, { skin: 9 }];
  const r = rnd(uid) + '';
  return arr.map((el, index) => {
    el.index = +r.slice(index, index + 2);
    return el;
  }).sort((a, b) => {
    return a.index - b.index;
  })

  //线性同余,用用户的id生成一串数字
  function rnd(uid) {
    let seed = (uid * 9301 + 49297) % 233280;
    seed = seed / (233280.0) * 10e20
    return Math.ceil(seed);
  }
}

console.log(sequence(112342))
console.log(sequence(112))

然后复习了排列组合,弄出了一个丢人算法——算出部分序列的组合,然后用部分id当作索引,合并序列。

// 根据给出的数组递归排出所有组合,但是序列过了8就就要算很久很久了。
const arrange = (arr) => {
  if(arr && arr.length === 1) return arr
  if (arr.length === 2) {
    return [
      [arr[0], arr[1]],
      [arr[1], arr[0]]
    ]
  }
  let resArr = []
  for (let i = 0; i < arr.length; i++) {
    //计算索引
    let len = arr.length, baseI = i, tempArr = []
    for (let l = 0; l < len - 1; l++) {
      let target
      if (baseI + 1 > len - 1) {
        target = baseI = 0
      } else {
        target = ++baseI
      }
      tempArr.push(arr[target])
    }
    let reTempArr = arrange(tempArr)
    for (let j = 0; j < reTempArr.length; j++) {
      resArr.push([arr[i], reTempArr[j]].flat(10))
    }

  }
  return resArr
}

才发现前面有康托展开...

const sequence = id => {
  if (typeof id === 'number') {
    id = id + ''
    if (id.length < 3) {
      id += '0'.repeat(3 - id.length)
    }
  } else if (typeof id === 'string') {
    id = id.split("").map(s => s.charCodeAt(0)).join('')
  }

  //取最后一位当作切割点
  let cut = Number(id[id.length - 1]),
    temp1 = [], temp2 = []

  //切割序列,分成2组,一组有120种可能(5!)
  for (let i = 0; i < 10; i++) {
    cut = cut + 1 > 9 ? 0 : cut + 1
    if (i < 5) {
      temp1.push(cut)
    } else {
      temp2.push(cut)
    }
  }
  const
    part1 = arrange(temp1),
    part2 = arrange(temp2),
    //id前后各取2个数字当索引
    seed1 = getSeed(id.length - 4, -2, part1.length),
    seed2 = getSeed(0, 2, part2.length)
   function getSeed(a, b, l) {
    return Number(id.slice(a, b))
  }
  return arrange(temp1)[seed1].concat(arrange(temp2)[seed2])
}

console.log(sequence(13012972))
console.log(sequence(12))
console.log(sequence('12'))
//'12'和数字12输出是不一样的
    (function () {
        /**
         * 随机生成userId
         * @returns {string}
         */
        const randomUserId = () => Math.random().toString(16).substring(2);

        //用于随机排列数组
        const randomSort = () => Math.random() - 0.5;

        //皮肤数组
        let skinArr = [
            {skin: 1},
            {skin: 2},
            {skin: 3},
            {skin: 4},
            {skin: 5},
            {skin: 6},
            {skin: 7},
            {skin: 8},
            {skin: 9},
            {skin: 10}
        ];


        function showSkin(userId) {
            if (localStorage.userId) {
                //存在用户
                return localStorage.userId;
            } else {
                //不存在用户
                let randomArr = JSON.stringify(skinArr.sort(randomSort));
                localStorage[userId] = randomArr;
                return randomArr;
            }
        }

        console.log(showSkin(randomUserId()));

    })()
const myRand = ( seed ) => {
    seed = ( seed * 9301 + 49297 ) % 233280
    return seed / ( 233280.0 ) * 10e17
}

const suffleSkins = userId => {
    let arr = new Array(10).fill(10).map((_, i) => ({skin: i+1}))

    let num = (userId + '').split('').reduce((acc, cur) => {
        return acc + cur.charCodeAt()   
    }, 0)

    let rand = myRand(num) + ''

    return arr.sort((a, b) => {
        let t = (+rand[a.skin]) - (+rand[b.skin])
        return t > 0 ? 1 : (t < 0 ? -1 : 0)
    })
}

suffleSkins('abc123')
suffleSkins(123)
// zxx: userid可能是字母字符串id

var userid = '2019042501';
var arr = [{skin:1},{skin:2},{skin:3},{skin:4},{skin:5},{skin:6},{skin:7},{skin:8},{skin:9},{skin:10}]


function createSkinSort(userid){
    var userIdStr = ''+userid,
        userIdLength=userIdStr.length,
        skinSort=[],
        numArr = [1,2,3,4,5,6,7,8,9,10];

    // userid超出10位,取后10位
    if(userIdLength > 10){
        userIdStr = userId.slice(-10)
    }

    for(var r = 0;r<10;r++){
        var newId = userIdStr%(10-r);
        skinSort.push(numArr.splice(newId,1)[0])
    }
    return skinSort;
}
createSkinSort(userid)

jsbin

/**
 * 通过传入的userId获取到arr的固定随机排序
 * 
 * @description 我是这样实现的:
 *              1.先使用1和9个质数作为基本数字数组
 *              2.基本数组循环一次,每次生成一个数字,那么正好是十个数字
 *              3.在每次基本数组循环的时候,将charCodes的每一项跟对应的基本数组中的对应项相乘然后相加,乘以基本数组中当前的数然后取余放到最终数组中
 *              4.每次生成一个数字以后将基本数组的第一项放到最后一项
 *              5.上面生成的数组中有重复数字,那么将重复数字用未使用的数字替换一下
 * @param {*} userId 
 * @param {*} arr 
 * 
 */
function getSort(userId,arr) {
    let base = [1, 2, 3, 5, 7, 11, 13, 17, 19, 23],
        charCodes = [],
        hash = {},
        notFound = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
        order = [];

    for (let i = 0, len = userId.length; i < len; i++) {
        charCodes.push(userId.charCodeAt(i));
    }
    for (let j = 0, len = base.length; j < len; j++) {
        let no = charCodes.reduce(function (code, no, i) {
            return no + code * base[i % 10];
        }, 0) * base[j] % 10;
        hash[no] = hash[no] ? hash[no] + 1 : 1;
        if (notFound.includes(no)) {
            notFound.splice(notFound.indexOf(no), 1);
        }
        order.push(no);
        base.push(base.shift());
    }
    for (let k = order.length - 1; k >= 0; k--) {
        let no = order[k];
        if (hash[no]-- > 1) {
            order[k] = notFound.shift()
        }
    }
    let privateArr = [];
    order.forEach(function(no){
        privateArr.push(arr[no]);
    })
    return privateArr;
}

JS BIN

var userId = "4326afadsr4325w";
var skins = Array.apply(null, { length: 10 }).map(function(item, index) {
  return { skin: index };
});

function idCharToNumber(id) {
  if (typeof id == "number") return id.toString();
  return Array.prototype.map.call(id, function(char) {
    if (/[0-9]/.test(char)) return char;
    return char.charCodeAt();
  }).join("");
}

var numberCharId = idCharToNumber(userId);
if (numberCharId.length < skins.length) {
  var idLen = numberCharId.length;
  var i = 0;
  while (numberCharId.length < skins.length) {
    numberCharId += numberCharId[i % idLen];
    i ++;
  }
}

var charCount = Math.floor(numberCharId.length / skins.length);
skins.forEach(function(item, index) {
  item._index = numberCharId.substr(index * charCount, charCount);
});
skins.sort(function(skinA, skinB) {
  return skinA._index - skinB._index
});
skins;
  1. 利用localStorage
let randomFn = (arr = []) => {
  arr.sort(function () {
    return .5 - Math.random();
  });
  return arr
}
let uidSkinArr = localStorage.getItem('uidSkinArr')
if (uidSkinArr) {
    uidSkinArr = JSON.parse(uidSkinArr)
  } else {
  let arr = [{skin:1},{skin:2},{skin:3},{skin:4},{skin:5},{skin:6},{skin:7},{skin:8},{skin:9},{skin:10}];
  uidSkinArr = randomFn(arr)
  localStorage.setItem('uidSkinArr', JSON.stringify({
    arr
  }))
}
  1. 线性同余生成器
let arr = [{skin:1},{skin:2},{skin:3},{skin:4},{skin:5},{skin:6},{skin:7},{skin:8},{skin:9},{skin:10}];

function rnd( seed ){
  seed = ( seed * 9301 + 49297 ) % 233280
  return seed / ( 233280.0 ) * 10e17
};

function randomFn(uid, arr){
  let rndArr = rnd(uid).toString()
  return arr.map((item, index) => {
    item.index = +rndArr.slice(index, index + 2)
    return item
  }).sort((a, b) => {
    return a.index - b.index
  })
}
(function() {
	function hashCode(str) {
		str = str + '';
		var hash = 0;
		for (var i = 0, len = str.length; i < len; i++) {
			hash = (hash << 5) - hash + str.charCodeAt(i);
			hash |= 0;
		}
		return hash;
	}
	function random(seed) {
		var next = seed;
		return function () {
			next = +('0.' + Math.sin(next).toString().substr(6)) - 0.5;
			return next;
		}
	}
	var arr = [{skin: 1},{skin: 2},{skin: 3},{skin: 4},{skin: 5},{skin: 6},{skin: 7},{skin: 8},{skin: 9},{skin: 10}];
	var userIds = ['u12','u13','u14','u15'];
	userIds.forEach(id => {
		var myRandom = random(hashCode(id));
		console.log('id: ' + id);
		arr.slice(0).sort(() => myRandom()).forEach(v => console.log(v));
	});
})();

demo

var arr = [{skin: 1}, {skin: 2}, {skin: 3}, {skin: 4}, {skin: 5}, {skin: 6}, {skin: 7}, {skin: 8}, {skin: 9}, {skin: 10}]
// 随机重组数组
function shuffleArray(array) {
    for (let i = array.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [array[i], array[j]] = [array[j], array[i]];
    }
    return array;
}

// 结果存入localStorage 主要代码
  if(localStorage.getItem('userSkin')) {
      var userSkin = JSON.parse(localStorage.getItem('userSkin'))
      var isExist = userSkin.find(el => el.userId == userId)
      if (isExist) {
        res = isExist.skin
      } else {
        res = shuffleArray(arr)
        userSkin.push({userId: userId, skin: res})
        localStorage.setItem('userSkin', JSON.stringify(userSkin))
      }
    } else {
      var userSkin = []
      res = shuffleArray(arr)
      userSkin.push({userId: userId, skin: res})
      localStorage.setItem('userSkin', JSON.stringify(userSkin))
 }
        var arr = [{skin:1},{skin:2},{skin:3},{skin:4},{skin:5},{skin:6},{skin:7},{skin:8},{skin:9},{skin:10}]

        let localStorage = window.localStorage
        getNewarr.created = JSON.parse(localStorage.getItem('created')) || {}

        function getNewarr(userId){
            if(getNewarr.created[userId]){
                return getNewarr.created[userId]
            }
            let newArr = []
            while(arr.length){
                let random = Math.floor(Math.random() * arr.length)
                newArr.push(arr.splice(random, 1)[0])
            }
            getNewarr.created[userId] = newArr
            localStorage.setItem('created', JSON.stringify(getNewarr.created))
            return newArr
        }

       getNewarr(userId)
var arr = [{ skin: 1 }, { skin: 2 }, { skin: 3 }, { skin: 4 }, { skin: 5 }, { skin: 6 }, { skin: 7 }, { skin: 8 }, { skin: 9 }, { skin: 10 }];
function skinRandom(uid, arr) {
    var newarr = localStorage['uid_' + uid];
    if (newarr) {
            var index = newarr.indexOf('[');
            var id = newarr.slice(0, index);
            if (uid == id) {
                    console.log('从已存中的读取');
                    console.log(newarr);
             }
    }
    else {
     console.log('生成新乱序数组');
     getrandom(arr);
    }
function getrandom(arr) {
       for (let i = 0; i < arr.length; i++) {
       const randomIndex = Math.round(Math.random() * (arr.length - 1 - i)) + i;
        [arr[i], arr[randomIndex]] = [arr[randomIndex], arr[i]];
        }
       localStorage.setItem('uid_' + uid, uid + JSON.stringify(arr));
       var newarr = localStorage['uid_' + uid];
       var index = newarr.indexOf('[');
       var id = newarr.slice(0, index);
       console.log(newarr);
     }
 }
//测试用例
skinRandom('3aa', arr);
skinRandom('3wwww', arr);
skinRandom('21333', arr);
var arr = [{skin:1},
			{skin:2},
			{skin:3},
			{skin:4},
			{skin:5},
			{skin:6},
			{skin:7},
			{skin:8},
			{skin:9},
			{skin:10}]

function randomSkin(arr,userId) {
	// 深拷贝数组
	let newArr = [];
	for (let skin of arr) {
		newArr.push({...skin});
	}
	len = arr.length;
	num = arr.length*4;
	userId = userId.toString();
	// 根据userId制造一个随机数
	function hash(text) {
    'use strict';
    	text = text.toString();
	    var hash = 5381,
	        index = text.length;
	    while (index) {
	        hash = (hash * 33) ^ text.charCodeAt(--index);
	    }
	    return hash >>> 0;
	}
	// 根据随机数两两交换数组
	while(num>0){
		let tempId = hash(userId);
		userId = hash(tempId);
		temp = newArr[userId%len];
		newArr[userId%len] = newArr[tempId%len];
		newArr[tempId%len] = temp
		num--;
	}
	return newArr;
}
randomSkin(arr,123)
var userid = "yue";

if (sessionStorage.getItem("userSkin")) {
  var userSkin = JSON.parse(sessionStorage.getItem("userSkin"));
  if (userSkin[userid]) {
    var privateSkin = userSkin[userid];
    return
  }
}

var skin = [{skin: 1},{skin: 2},{skin: 3},{skin: 4},{skin: 5},{skin: 6},{skin: 7},{skin: 8},{skin: 9},{skin: 10}];

var privateSkin = getRandom(skin);

// 获得随机后的皮肤数据
console.log('privateSkin', privateSkin)
// 保存到本地
sessionStorage.setItem("userSkin", JSON.stringify({
  userid: privateSkin
}))
// 随机数组方法
function getRandom(arr) {
  var randomArr = [];
  for (var i = 0, len = arr.length; i < len; i++) {
    // 随机抽取
    var randomIndex = Math.floor(Math.random() * arr.length);
    // 添加到个人皮肤数组
    randomArr[i] = arr[randomIndex];
    // 删除选中的皮肤
    arr.splice(randomIndex, 1);
  }
  return randomArr
}
// zxx: 为何我测试顺序都没变?

const arr = [
  { skin: 1 },
  { skin: 2 },
  { skin: 3 },
  { skin: 4 },
  { skin: 5 },
  { skin: 6 },
  { skin: 7 },
  { skin: 8 },
  { skin: 9 },
  { skin: 10 }
]

function randomByUid(uid, arr) {
  const charCode =
    `${uid}`
      .split('')
      .reduce((total, item) => (total += item.charCodeAt()), 0) << 16
  const doubleChar = `${charCode * charCode}`.slice(0, 10)
  return Object.assign([], arr).sort((a, b) => {
    const aIndex = arr.indexOf(a)
    const bIndex = arr.indexOf(b)
    return doubleChar[aIndex] - doubleChar[bIndex]
  })
}

第一个想到的是localStorage,想想怕是存不住;

扫了一眼大家的,发现一个新名词种子随机数,那就借鉴一下(抄起来)

var userId = 'ad3213432';
var arr = [{
  skin: 1
},
{
  skin: 2
},
{
  skin: 3
},
{
  skin: 4
},
{
  skin: 5
},
{
  skin: 6
},
{
  skin: 7
},
{
  skin: 8
},
{
  skin: 9
},
{
  skin: 10
},
];
function sortArr(userId) {
  var total = 0;
  for (var i = 0; i < userId.length; i += 1) {
    total += userId[i].charCodeAt();
  }
  arr.forEach(function(item, index) {
    item.sort = index;
  }) ;
  var seed = (total * 9301 + 49297) % 233280;
  var newArr = arr.sort(function(next, prev) {
    return (next.sort * seed).toString().slice(0, 1) - (prev.sort * seed).toString().slice( -2, -1)
  });
  return newArr;
}
console.log(sortArr(userId));
var arr = [{skin: 1},{skin: 2},{skin: 3},{skin: 4},{skin: 5},{skin: 6},{skin: 7},{skin: 8},{skin: 9},{skin: 10}];
function randomIndex(n) {
    var res = [];
    for(n;n>0;n--) {
        var r = Math.floor(Math.random() * n);
        res.push(r);
    }
    return res;
}
function sortArr(id){
    var res;
    var storedIndex = window.localStorage.getItem('skinSort' + id);
    if (storedIndex) {
        res = storedIndex.split(',');
    } else {
        res = random(10);
        window.localStorage.setItem('skinSort' + id, res);
    }
    var newArr = [];
    var i = 0;
    for(i;i<10;i++) {
        var item = arr.splice(res[i], 1);
        newArr.push(item[0]);
    }
    return newArr;
}

var sortedArr = sortArr('12321ewwer');
    var arr = [{ skin: 1 }, { skin: 2 }, { skin: 3 }, { skin: 4 }, { skin: 5 }, { skin: 6 }, { skin: 7 }, { skin: 8 }, { skin: 9 }, { skin: 10 }];
    function randomarr(arr) {
      for (var i = arr.length - 1; i >= 0; i--) {
        var randomIndex = Math.floor(Math.random() * (i + 1))
        var itemAtIndex = arr[randomIndex]
        arr[randomIndex] = arr[i]
        arr[i] = itemAtIndex
      }
      return arr
    }
    let userid = 'ceshiid'
    if (localStorage.getItem('userid') == userid) {
      skin = JSON.parse(localStorage.getItem('skin'))
    } else {
      localStorage.setItem('userid', userid);
      skin = randomarr(arr)
      localStorage.setItem('skin', JSON.stringify(skin))
    }

我自己也撸了一个:地址

var arr = [{skin:1},{skin:2},{skin:3},{skin:4},{skin:5},{skin:6},{skin:7},{skin:8},{skin:9},{skin:10}]

var randArr = function (seed) {
  // 变成数值
  seed = seed.replace(/\D/g, function (matchs) {
    return matchs.charCodeAt();
  });
  // 变成随机数值
  var str = Math.sin(seed).toString().slice(3);
  // 补全,万一数组长度很长
  var arrStr = str.padStart(arr.length, str).split('');
  // 随机
  return [...arr].map(function (obj, index) {
     obj.rand = +arrStr[index];
     return obj;
  }).sort(function (objA, objB) {
    return objA.rand - objB.rand;    
  }).map(function (obj) {
     delete obj.rand;
     return obj;
  });
};

console.dir(randArr('abc001'));
console.dir(randArr('abc001'));
console.dir(randArr('abc002'));
console.dir(randArr('abc003'));

codepen例子,不太确定是不是理解了题目意思 2333

//如果值>10,反复执行循环
function addValueCircle( value ){
  let result = 0;
  if( value > 0 && value< 11 ) {
    console.log("value:",value);
    return value;
  }
  else if(typeof value==="number"){
     (value+"").split("").map((item)=>{
       result = result + (item-0);
    })
    console.log("1:",result);
    return this.addValueCircle(result);
  }else{
    value.split("").map((item)=>{
      result = result + item.charCodeAt();
    });
    console.log("2:",result);
    return this.addValueCircle(result);
  }
}

// 最简单的想法,跟进userid值来进行皮肤随机匹配
const skin = [{skin:1},{skin:2},{skin:3},{skin:4},{skin:5},{skin:6},{skin:7},{skin:8},{skin:9},{skin:10}]
const userid = "abcd12";

// 按照固定的压缩成10个数字内的【自定义一套字符压缩机制charCodeAt】
let numberSkin = skin[this.addValueCircle(userid) - 1];
console.log(numberSkin);
var arr = [{
    skin: 1
}, {
    skin: 2
}, {
    skin: 3
}, {
    skin: 4
}, {
    skin: 5
}, {
    skin: 6
}, {
    skin: 7
}, {
    skin: 8
}, {
    skin: 9
}, {
    skin: 10
}];
var arrNew = [];
Math.seed = 1666;

function seededRandom(max, min) {
    max = max || 1;
    min = min || 0;
    Math.seed = (Math.seed * 9301 + 49297) % 233280;
    var rnd = Math.seed / 233280.0;
    return min + rnd * (max - min);
};
for (var i = 0; i < arr.length; i++) {
    arrNew.push(Math.floor(seededRandom(arr.length, 0)));
}
arrNew = arr.map(function (item, index) {
    item.index = +arrNew[index];
    return item;
}).sort(function (a, b) {
    return b.index - a.index;
});
console.log('新的随机数组为:');
console.log(arrNew);