原生 JS 实现扫雷 (分析+代码实现)
阅读这篇文章需要掌握的基础知识:Html5、CSS、JavaScript
在线Demo:查看
扫雷规则
在写扫雷之前,我们先了解下它的游戏规则
● 扫雷是一个矩阵,地雷随机分布在方格上。
● 方格上的数字代表着这个方格所在的九宫格内有多少个地雷。
● 方格上的旗帜为玩家所作标记。
● 踩到地雷,游戏失败。
● 打开所有非雷方格,游戏胜利。
功能实现思路分析
矩阵的生成
- 矩阵的生成有多种方式可以实现,我们这里使用<table>+<span>标签。
- 通过 js 给定行数与列数在<table>的 innerHtml 写入<span>标签来动态生成矩阵。
方格的打开与标记
- 通过 onmousedown 事件,传入点击的方格的坐标及event,判断event为左键还是右键。
- 左键打开方格,右键标记方格。
地雷的随机分布
- 由于第一次打开的方格不能为地雷所以我们把生成地雷的函数放在第一次点击方格时。
- 我们通过循环用 Math.random() 函数来随机生成地雷的二维坐标。
- 判断坐标是否不为第一次点击方格的坐标以及没有雷存在。
- 是则将方格设置为地雷,当前地雷数+1,并且将九宫格内的方格的计雷数+1。
- 否则跳过进入下个循环,直到地雷的数量达到设定的最大雷数,结束循环。
踩到地雷游戏结束
- 打开方格为地雷时,提示游戏结束。
- 通过遍历矩阵来打开所有地雷
连锁打开方格
- 当打开的方格为计雷数为0的方格,自动打开九宫格内的非雷方格。
- 如果打开的非雷方格九宫格内仍有非雷方格,继续打开九宫格内的非雷方格,直到没有为止。
游戏胜利条件
- 当所有非雷方格被打开即为游戏胜利。
- 在每次打开方格函数中都遍历一遍矩阵,当找到有未打开的非雷方格时则结束遍历。
- 当遍历完未找到未打开的非雷方格则提示游戏胜利。
剩余地雷数与计时器
- 地雷的总数减去玩家标记的方格数即为剩余地雷数
- 计时器可以用setInterval()函数实现
代码实现
生成矩阵
我们先在<body>里写一个<table>标签,设定个 id='grid'
- <table id='grid'></table>
然后在<script>里 定义两个变量 row--行数 col--列数
通过两个for循环把 (方格)<span> 写入到 (矩阵)<table> 里,通过<td><tr>标签控制行列。
- var row = 10; //行数
- var col = 10; //列数
- //生成矩阵html <tr>--行标签 <td>--列标签
- let gridHtml = '';
- for (let i = 0; i < row; i++) {
- gridHtml += '<tr>'
- for (let j = 0; j < col; j++) {
- gridHtml += '<td><span class="blocks"></span></td>';
- }
- gridHtml += '<tr>'
- }
- //写入html
- document.getElementById('grid').innerHTML = gridHtml;
写一下矩阵和方格的CSS样式。
- #grid {
- margin: auto; /* 让矩阵居中显示于页面 */
- }
- .blocks {
- width: 30px;
- height: 30px;
- line-height: 30px;
- display: block; /* 让span以block方式显示 */
- text-align: center;
- border: solid 1px #000;
- user-select: none; /* 设置不可拖拽选中 */
- cursor: pointer; /* 设置鼠标停留样式 */
- }
- .blocks:hover {
- background: #0af; /* 鼠标停留时背景颜色变化 */
- }
至此打开页面,矩阵就初步显示出来了。
把矩阵的方格放入二维数组中
我们先定义一个全局变量grid。
把刚才写的生成矩阵的代码写成一个函数 function init_grid()
document.getElementsByClassName('blocks') 返回的是一个一维数组,我们把它通过两个for循环转化为二维数组。
给每个方格定义一个属性 count 计雷数 --- blocks[i].count = 0;
然后把返回值赋值给grid --- grid = init_grid();
- var row = 10; //行数
- var col = 10; //列数
- var grid = init_grid();
- //初始化矩阵 (row-行数 col-列数)
- function init_grid() {
- //生成矩阵html <tr>--行标签 <td>--列标签
- let gridHtml = '';
- for (let i = 0; i < row; i++) {
- gridHtml += '<tr>'
- for (let j = 0; j < col; j++) {
- gridHtml +=
- '<td><span class="blocks"></span></td>';
- }
- gridHtml += '<tr>'
- }
- //写入html
- document.getElementById('grid').innerHTML = gridHtml;
- //返回矩阵二维数组
- let blocks = document.getElementsByClassName('blocks');
- let grid = new Array();
- for (let i = 0; i < blocks.length; i++) {
- if (i % col === 0) {
- grid.push(new Array());
- }
- //初始化计雷数
- blocks[i].count = 0;
- grid[parseInt(i / col)].push(blocks[i]);
- }
- return grid;
- }
写完了这段我们先写一段代码测试下grid有没有赋值成功,遍历grid把方格的值改为对应的坐标。
- for (let i = 0; i < row; i++) {
- for (let j = 0; j < col; j++) {
- grid[i][j].innerHTML = i + ',' + j;
- }
- }
可以看到 grid 已经赋值成功!没成功的回去检查下代码。(Tip:测试完记得把测试代码删除)
方格的点击事件
定义一个函数 function block_click( _i, _j, e) 的大致框架
e为传入的鼠标事件,e.button ( 0为左键,2为右键 )。
isOpen属性为自定义属性,用来判断方格是否打开。
- //方格点击事件 _i:坐标i _j:坐标j e:鼠标事件
- function block_click(_i, _j, e) {
- //跳过已打开的方格
- if (grid[_i][_j].isOpen) {
- return;
- }
- //鼠标左键打开方格
- if (e.button === 0) {
- }
- //鼠标右键标记方格
- else if (e.button === 2) {
- }
- }
然后修改下之前写在 init_grid 函数里的<span>的属性,绑定 onmousedown 事件,传入 i,j 坐标,和鼠标事件 event
- gridHtml += '<td><span class="blocks" onmousedown="block_click(' + i + ',' + j + ',event)"></span></td>';
修改下body的属性 加入防拖拽生成新页面和屏蔽右键菜单。
- <!-- ondragstart:防拖拽生成新页面 oncontextmenu:屏蔽右键菜单-->
- <body ondragstart='return false' oncontextmenu='self.event.returnValue=false'>
我们在鼠标左键事件里面写下测试代码,当左键方格时显示它的坐标。
- //鼠标左键打开方格
- if (e.button === 0) {
- grid[_i][_j].innerHTML = _i + ',' + _j;
- }
效果如下,没成功的回去检查下代码。(Tip:测试完记得把测试代码删除)
方格的标记
在鼠标右键事件写标记代码,这里用 ▲ 来作为标记。
右击一次添加标记,再次右击删除标记。
- //鼠标右键标记方格
- else if (e.button === 2) {
- let block = grid[_i][_j];
- if (block.innerHTML !== '▲') {
- block.innerHTML = '▲';
- } else {
- block.innerHTML = '';
- }
- }
效果如下:
随机生成地雷
由于第一次打开的方格不能为地雷所以我们把生成地雷的函数放在第一次点击方格时。
先定义全局变量 maxCount --- 最大地雷数 isFirstOpen --- 是否第一次打开方格。
- var row = 10; //行数
- var col = 10; //列数
- var grid = init_grid();
- var maxCount = 10; //最大地雷数量
- var isFirstOpen = true; //第一次打开方格
在鼠标左键事件里面写第一次打开方格生成地雷的代码的大致框架。
- //鼠标左键打开方格
- if (e.button === 0) {
- //第一次打开
- if (isFirstOpen) {
- isFirstOpen = false;
- let count = 0; //当前地雷数
- //生成地雷
- while (count < maxCount) {
- //........
- }
- }
- }
完善生成地雷代码:
生成随机坐标 ri,rj,判断该坐标不等于第一次点击方格的坐标以及该坐标表方格不为地雷。
条件成立,将坐标对应方格的 isMine 设置为true,当前地雷数+1,并使九宫格内非雷方格的计雷数 count +1
自定义属性isMine代表方格为地雷。
自定义属性count为计雷数。
当地雷数大于最大地雷数,结束循环。
- //生成地雷
- while (count < maxCount) {
- //生成随机坐标
- let ri = Math.floor(Math.random() * row);
- let rj = Math.floor(Math.random() * col);
- //坐标不等于第一次点击方格的坐标 && 非雷方格
- if (!(ri === _i && rj === _j) && !grid[ri][rj].isMine) {
- grid[ri][rj].isMine = true; //自定义属性isMine代表方格为地雷
- count++; //当前地雷数+1
- //更新九宫格内非雷方格的计雷数
- for (let i = ri - 1; i < ri + 2; i++) {
- for (let j = rj - 1; j < rj + 2; j++) {
- //判断坐标防越界
- if (i > -1 && j > -1 && i < row && j < col) {
- //计雷数+1
- grid[i][j].count++;
- }
- }
- }
- }
- }
写个测试代码在生成地雷后显示所有方格的状态。(Tip:测试完记得把测试代码删除)
- for (let i = 0; i < row; i++) {
- for (let j = 0; j < col; j++) {
- //判断方格是否为雷
- if (grid[i][j].isMine) {
- //显示为雷
- grid[i][j].innerHTML = '雷';
- } else {
- //否则显示计雷数
- grid[i][j].innerHTML = grid[i][j].count;
- }
- }
- }
效果如下:可以看到已经随机生成了雷,计雷数也正确显示了。
方格的打开事件
在生成地雷的代码下,加入方格打开代码函数 block_open(_i,_j) 的大致框架。
定义 function op(block) 函数设定打开方格的状态与样式。
判定打开的方格的类型
block.isMine 为打开地雷方格 --> 游戏结束
block.count === 0 为打开计雷数为0的方格 --> 连锁打开非雷方格
else 为打开计雷数大于0的方格 --> 显示方格计雷数
- //鼠标左键打开方格
- if (e.button === 0) {
- //第一次打开
- if (isFirstOpen) {
- //.......
- }
- //执行打开方格函数
- block_open(_i, _j);
- //打开方格函数
- function block_open(_i, _j) {
- let block = grid[_i][_j];
- op(block);
- //设定打开方格的状态与样式
- function op(block) {
- block.isOpen = true; //isOpen为自定义属性,设置为true代表已打开
- block.style.background = '#ccc'; //将背景设置为灰色
- block.style.cursor = 'default'; //将鼠标停留样式设置为默认
- }
- if (block.isMine) {
- //踩雷
- } else if (block.count === 0) {
- //打开计雷数为0的方格
- } else {
- //打开计雷数不为0的方格
- }
- }
- }
打开非雷方格显示计雷数
我们先把最简单的显示方格计雷数搞定。
- else {
- //打开计雷数不为0的方格
- block.innerHTML = block.count; //显示计雷数
- }
效果如下:
踩雷游戏结束
接下来写踩雷代码,当打开的方格为雷时,将其显示为'雷',并打开所有的地雷,提示游戏结束。
- if (block.isMine) {
- //踩雷
- block.innerHTML = '雷'; //显示为 '雷'
- //遍历矩阵打开所有的地雷方格
- for (let i = 0; i < row; i++) {
- for (let j = 0; j < col; j++) {
- //找到地雷
- block = grid[i][j];
- if (!block.isOpen && block.isMine) {
- op(block); //设置打开状态和样式
- block.innerHTML = '雷'; //显示为 '雷'
- }
- }
- }
- //提示游戏结束
- alert("游戏结束");
- }
效果如下:
连锁打开方格
打开的方格为计雷数为0的方格,自动打开九宫格内的非雷方格,循环递归到没有为止。
计雷数为0就没必要让innerHtml显示0了,保持空白就行。
- else if (block.count === 0) {
- //打开计雷数为0的方格
- //遍历九宫格内的方格
- for (let i = _i - 1; i < _i + 2; i++) {
- for (let j = _j - 1; j < _j + 2; j++) {
- //判断是否越界&&跳过已打开的方格&&非雷
- if (i > -1 && j > -1 && i < row && j < col && !grid[i][j].isOpen && !grid[i][j].ismine) {
- //递归打开方格函数
- block_open(i, j);
- }
- }
- }
- }
效果如下:
游戏胜利条件
扫雷大体框架已经出来了,我们现在做胜利条件的判定。
在方格点击函数最后写判断代码。
- //方块点击事件 _i:坐标i _j:坐标j e:鼠标事件
- function block_click(_i, _j, e) {
- //跳过已打开的方块
- if (grid[_i][_j].isOpen) {
- //...
- }
- //鼠标左键打开方块
- if (e.button === 0) {
- //...
- }
- //鼠标右键标记方块
- else if (e.button === 2) {
- //...
- }
- //遍历矩阵
- let isWin = true;
- for (let i = 0; i < row; i++) {
- for (let j = 0; j < col; j++) {
let block = grid[i][j];- //判断游戏胜利条件(所有的非雷方格已打开)
- if (!block.isMine && !block.isOpen) {
- //如果有未打开的非雷方块 条件不成立
- isWin = false;
- }
- }
- }
- if (isWin) {
- alert("游戏胜利");
- }
- }
效果如下:(还专门玩了一遍^ ^)
游戏部分到这里就完成了!
剩余地雷数与计时器
最后,我们做一下剩余地雷数和计时器的显示。
我们写个 <div> 在 <table> 的上面,放两个 <span> 来做显示框,<label> 用来给 js 计数。
- <div id='bar'>
- <span class='bar'>剩余雷数:<label id='count'>0</label></span>
- <span class='bar'>计时:<label id='time'>0</label>s</span>
- </div>
- <table id='grid'></table>
再写下CSS样式:
- #bar {
- text-align: center;
- margin-bottom: 20px;
- }
- .bar {
- height: 25px;
- width: 150px;
- line-height: 25px;
- display: inline-block;
- border: solid 1px #000;
- margin-left: 20px;
- margin-right: 20px;
- }
效果如下:
在 js 中定义两个全局变量拿到 <lable> count 和 time
然后让地雷数量等于最大地雷数,设置个100ms定时器,每次+0.1s,保留一位小数。
- var count = document.getElementById('count'); //剩余地雷数
- count.innerHTML = maxCount; //初始化剩余雷数
- var time = document.getElementById('time'); //计时器
- var timer = setInterval(function () {
- let seconds = (parseFloat(time.innerHTML) + 0.1).toFixed(1); //保留一位小数
- time.innerHTML = seconds;
- }, 100) //定时器 100ms执行一次
我们修改下方格点击事件中遍历矩阵的代码,更新剩余地雷数,胜利时结束计时。
- //遍历矩阵
- let isWin = true;
- count.innerHTML = maxCount; //重置剩余地雷数
- for (let i = 0; i < row; i++) {
- for (let j = 0; j < col; j++) {
- let block = grid[i][j];
- //找到标记
- if (block.innerHTML === '▲') {
- count.innerHTML = parseInt(count.innerHTML) - 1; //剩余地雷数-1
- }
- //判断游戏胜利条件(所有的非雷方格已打开)
- if (!block.isMine && !block.isOpen) {
- //如果有未打开的非雷方块 条件不成立
- isWin = false;
- }
- }
- }
- if (isWin) {
- clearInterval(timer); //游戏胜利结束计时,清除定时器
- alert("游戏胜利");
- }
再修改踩雷的代码,结束计时。
- if (block.isMine) {
- //踩雷
- block.innerHTML = '雷'; //显示为 '雷'
- //遍历矩阵打开所有的地雷方格
- for (let i = 0; i < row; i++) {
- for (let j = 0; j < col; j++) {
- //找到地雷
- block = grid[i][j];
- if (!block.isOpen && block.isMine) {
- op(block); //设置打开状态和样式
- block.innerHTML = '雷'; //显示为 '雷'
- }
- }
- }
- clearInterval(timer); //游戏结束停止计时,清除定时器
- //提示游戏结束
- alert("游戏结束");
- }
OK,大功告成!!!后续还可以加入选择难度的功能,重新开始按钮,动画效果等等,这个就看你们发挥了!!
完整代码
- <!DOCTYPE html>
- <html>
- <head>
- <title>扫雷</title>
- <style>
- #bar {
- text-align: center;
- margin-bottom:20px;
- }
- .bar {
- height: 25px;
- width: 150px;
- line-height: 25px;
- display: inline-block;
- border: solid 1px #000;
- margin-left: 20px;
- margin-right: 20px;
- }
- #grid {
- margin: auto;
- }
- .blocks {
- width: 30px;
- height: 30px;
- line-height: 30px;
- display: block;
- text-align: center;
- border: solid 1px #000;
- user-select: none;
- cursor: pointer;
- }
- .blocks:hover {
- background: #0af;
- }
- </style>
- </head>
- <!-- ondragstart:防拖拽生成新页面 oncontextmenu:屏蔽右键菜单-->
- <body ondragstart='return false' oncontextmenu='self.event.returnValue=false'>
- <div id='bar'>
- <span class='bar'>剩余雷数:<label id='count'>0</label></span>
- <span class='bar'>计时:<label id='time'>0</label>s</span>
- </div>
- <table id='grid'></table>
- <script>
- var row = 10; //行数
- var col = 10; //列数
- var maxCount = 10; //最大地雷数量
- var isFirstOpen = true; //第一次打开方格
- var grid = init_grid(); //初始化
- var count = document.getElementById('count'); //剩余雷数
- var time = document.getElementById('time'); //计时
- //初始化矩阵 (row-行数 col-列数)
- function init_grid() {
- //生成矩阵html <tr>--行标签 <td>--列标签
- let gridHtml = '';
- for (let i = 0; i < row; i++) {
- gridHtml += '<tr>'
- for (let j = 0; j < col; j++) {
- gridHtml +=
- '<td><span class="blocks" onmousedown="block_click(' + i + ',' + j + ',event)"></span></td>';
- }
- gridHtml += '<tr>'
- }
- //写入html
- document.getElementById('grid').innerHTML = gridHtml;
- //返回矩阵二维数组
- let blocks = document.getElementsByClassName('blocks');
- let grid = new Array();
- for (let i = 0; i < blocks.length; i++) {
- if (i % col === 0) {
- grid.push(new Array());
- }
- //初始化计雷数
- blocks[i].count = 0;
- grid[parseInt(i / col)].push(blocks[i]);
- }
- return grid;
- }
- //方格点击事件 _i:坐标i _j:坐标j e:鼠标事件
- function block_click(_i, _j, e) {
- //跳过已打开的方格
- if (grid[_i][_j].isOpen) {
- return;
- }
- //鼠标左键打开方格
- if (e.button === 0) {
- //第一次打开
- if (isFirstOpen) {
- isFirstOpen = false;
- let count = 0; //当前地雷数
- //生成地雷
- while (count < maxCount) {
- //生成随机坐标
- let ri = Math.floor(Math.random() * row);
- let rj = Math.floor(Math.random() * col);
- //坐标不等于第一次点击方格的坐标 && 非雷方格
- if (!(ri === _i && rj === _j) && !grid[ri][rj].isMine) {
- grid[ri][rj].isMine = true; //自定义属性isMine代表方格为地雷
- count++; //当前地雷数+1
- //更新九宫格内非雷方格的计雷数
- for (let i = ri - 1; i < ri + 2; i++) {
- for (let j = rj - 1; j < rj + 2; j++) {
- //判断坐标防越界
- if (i > -1 && j > -1 && i < row && j < col) {
- //计雷数+1
- grid[i][j].count++;
- }
- }
- }
- }
- }
- }
- //执行打开方格函数
- block_open(_i, _j);
- //打开方格函数
- function block_open(_i, _j) {
- let block = grid[_i][_j];
- op(block);
- //设定打开方格的状态与样式
- function op(block) {
- block.isOpen = true; //isOpen为自定义属性,设置为true代表已打开
- block.style.background = '#ccc'; //将背景设置为灰色
- block.style.cursor = 'default'; //将鼠标停留样式设置为默认
- }
- if (block.isMine) {
- //踩雷
- block.innerHTML = '雷'; //显示为 '雷'
- //遍历矩阵打开所有的地雷方格
- for (let i = 0; i < row; i++) {
- for (let j = 0; j < col; j++) {
- //找到地雷
- block = grid[i][j];
- if (!block.isOpen && block.isMine) {
- op(block); //设置打开状态和样式
- block.innerHTML = '雷'; //显示为 '雷'
- }
- }
- }
- //提示游戏结束
- alert("游戏结束");
- } else if (block.count === 0) {
- //打开计雷数为0的方格
- //遍历九宫格内的方格
- for (let i = _i - 1; i < _i + 2; i++) {
- for (let j = _j - 1; j < _j + 2; j++) {
- //判断是否越界&&跳过已打开的方格&&非雷
- if (i > -1 && j > -1 && i < row && j < col && !grid[i][j].isOpen && !grid[i][j].ismine) {
- //递归打开方格函数
- block_open(i, j);
- }
- }
- }
- } else {
- //打开计雷数不为0的方格
- block.innerHTML = block.count; //显示计雷数
- }
- }
- }
- //鼠标右键标记方格
- else if (e.button === 2) {
- let block = grid[_i][_j];
- if (block.innerHTML !== '▲') {
- block.innerHTML = '▲';
- } else {
- block.innerHTML = '';
- }
- }
- //判断游戏是否结束(所有的非雷方格已打开)
- for (let i = 0; i < row; i++) {
- for (let j = 0; j < col; j++) {
- if (!grid[i][j].isMine && !grid[i][j].isOpen) {
- return;
- }
- }
- }
- alert("游戏胜利");
- }
- </script>
- </body>
- </html>
原生 JS 实现扫雷 (分析+代码实现)的更多相关文章
- 原生js 当前时间 倒计时代码
源:https://www.oschina.net/code/snippet_2318153_54763 <!DOCTYPE html> <html> <head> ...
- [笔记]原生JS实现的DOM操作笔记
原生JS实现的DOM一系列操作参考: 原生JavaScript封装DOM库 siblings: 原生JS-查找相邻的元素-siblings方法的实现 addClass,removeClass,hasC ...
- 导航栏中各按钮在点击当前按钮变色其他按钮恢复为原有色的实现方法(vue、jq、原生js)
一.vue如何实现? 代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...
- Rails Guide--Working with JavaScript in Rails; 如何把jquery转化为原生js
1 An Introduction to Ajax 打开网页的的过程也叫:request response cycel. JavaScript也可以request然后parse the respons ...
- 原生js封装十字参考线插件(一)
需求来源: 拓扑图之机房平面图,显示机房长宽比例尺,房间内标注各种设备间距不易实现,特在机房平面图上层加一个十字参考线 横竖两条线垂直,在鼠标指针处交叉,显示鼠标指针坐标(相对机房平面图的坐标,不是相 ...
- 原生JS与JQ获取元素的区别
刚学JQ不久,有时候可能会把JS和JQ获取元素的方式搞错,接下来获取属性方法什么的就一发不可收拾了,现在把两者获取获取元素的代码整理下. 一.原生JS获取元素. 1.常用的三种方式获取元素对象(将指定 ...
- C#保留2位小数几种场景总结 游标遍历所有数据库循环执行修改数据库的sql命令 原生js轮盘抽奖实例分析(幸运大转盘抽奖) javascript中的typeof和类型判断
C#保留2位小数几种场景总结 场景1: C#保留2位小数,.ToString("f2")确实可以,但是如果这个数字本来就小数点后面三位比如1.253,那么转化之后就会变成1.2 ...
- 原生js复制粘贴上传图片前后台代码,兼容firebox,chrome, ie11,亲测有效
需求:粘贴上传图片,截图工具,右键粘贴,或者ctrl+v粘贴 方法1:可直接套用富文本框的图片上传功能,完成复制粘贴 缺点:麻烦,样式难控制 方法2:用原生js完成,以下案例基于此,样式请自己动手调整 ...
- 原生JS实现购物车结算功能代码+zepto版
html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3 ...
随机推荐
- eayui grid 每一页的行号都是从1开始
问题背景: easyui 需要显示行号的时候,我们只需要设置 rownumbers: true, 但是 不管是在哪一页,行号都是从1开始,不能连续 我们在分页的 onSelectPage 函数里去执 ...
- 基础架构之Docker私有库
由于项目要容器化,所有搭建自己的镜像库也是很有必要的,不然发到直接使用官方的镜像库,速度绝对能让你头疼,这篇文章就介绍搭建自己的镜像私有库. (一) 环境要求 Centos 7.5.1804 Doc ...
- python完全学习笔记
dir(__builtins__) help(input) 'let\'s go' #转义字符 \ r'c:\now' #字符串前加r 自动转义 str= ''' shdiufhi s ...
- Session和Cookie详解(1)
面试常问的有关session和cookie的问题: 1.session在分布式环境下怎么解决 2.集群下如何保证session踩中 3.cookie的大小 4.服务器怎么识别一个用户的 5.sessi ...
- 深度解析pos机,养卡人必看!
好多人对POS 好像都比较迷茫,这个说这个POS 好,那个说那个POS 好.下面就我对POS 的认知给兄弟们说下.对与不对的各位见谅. 第一.一清机 一清机是指在结算日结算后直接通过支付公司账号转 ...
- SQL Server ->> OFFSET & FETCH子句
SQL Server 2012引入OFFSET + FETCH字句.它俩出现在SELECT .... ORDER BY ...后面.作用是告诉SQL Server在结果集中忽略前N行然后取前M行出来. ...
- easyUI datagrid 重复发送URL请求
如果在table属性中配置了URL参数,在初始化datagrid时,会发送一次url请求.或者在js中datagrid{url:''}时,也会自动发送一次url请求. 在初始化datagrid时,我并 ...
- Java文件操作工具类
import com.foriseland.fjf.lang.DateUtil;import org.apache.commons.io.FileUtils;import org.slf4j.Logg ...
- lua-excel助手
excel是我们工作及生活当中不可或缺的东西,好吧,我是一个游戏程序员,数值哥哥肯定会给我些表格的.回归正题,为什么需要做这个封装? 为什么需要这个项目,因为我们需要使用程序进行自动化操作 VBA我们 ...
- web 应用程序转化为多租户 SaaS 解决方案
web 应用程序转化为多租户 SaaS 解决方案 https://www.ibm.com/developerworks/cn/cloud/library/cl-multitenantsaas/inde ...