工作之余,总想做点什么有意思的东西。但是苦于不知道做什么,也就一直没有什么动作。在一个午饭后,跟@jedmeng和@墨尘聊天过程中,发现可以写一些小东西来练练手,有以下几点好处:

1. 加强巩固前端相关知识

2. 可以用一些平时项目中想用但没用的新东西

3. 一块儿做相同的东西,可以分享各自不同的想法

先来一张效果图,也可以来这里玩玩~

接下来就介绍一下做这个小游戏,自己的一些步骤和思路:

首先就是熟悉连连看的规则,为此还专门下载了一个app感受了一下,规则简单的说就是:找到两个相同的图标,但是之前的连线不能大于条线;

其次就要准备棋盘的UI设计和结构的成型,这块儿我直接使用了@墨尘的设计;

再次就看是思考js里需要哪些功能:

初始化棋盘

绑定连线事件

处理连线的核心逻辑:判断是否可以连线

成功、失败提示等其他功能

最后完善细节基本上就搞定了。

下面详细介绍一下实现连连看核心功能的一些想法:

第一:初始化棋盘

初始化棋盘的时候,需要一些原始数据,页面才能知道哪里需要展现什么。我这里一共有45个不同的图标,那么所有的数据都是从这45个数据中获取,这个地方遇到的问题是:怎么能保证每个图标出现是偶数个?我的做法是随机去除总个数一般的数据,然后每个数据存入两次,这样就能保证每个图标都是偶数个。

/**

* 获取源数据

* @param {Number} total 获取个数,默认整个棋盘需要的棋子数

* @returns {Array} 源数据

*/

getRandomData: function(total) {

total = total || this.cols * this.rows;

var halfTotal = total/2;

var pieces = [];

for(var i = 0; i < halfTotal; i++) {

//保证每个元素都是成双的

var num = Math.floor(Math.random() * 45);

pieces.push(num);

pieces.push(num);

}

return pieces;

}

在展示数据的时候,需要时随机布局,这个时候我想到了数组的sort方法,可以创建规则进行排序,如果我的排序规则是随机的呢?是不是这样展示的时候就是随机的呢。当然可能还有更加好的随机做法,也希望可以分享给我。

/**

* 随机排序算法

* @returns {number} -1或1

*/

randomSort: function() {

return Math.random() > 0.5 ? -1 : 1;

}

这样基本上就可以初始化一个随机排序的棋盘了。

第二:绑定连线事件

这个相对比较简单,需要注意的是,只有在点击两个点的时候才能进行判断是否可以连接,并且保证同时处于选中状态的不能超过两个。

第三:连线的核心逻辑

经过分析,所有的连线情况无非就是三种情况:连线没有拐点、连线只有一个拐点、连线有两个拐点

连线没有拐点:

这个很简单,这种情况就是两个点(x,y)和(m,n),两点必须同行或者同列,再通过一个循环就能知道两个能不能连起来了,伪代码大概是这样:

//假设方法名是 dealOneLine(x,y,m,n)

if(x == m || y == n) {

// y == n 是从x轴方向开始遍历

if(x ==m) {

for(i = mixY; i<=maxY;i++) {

//判断是否能连通

}

}

}

一个拐点:

这种情况,必须得保证两点不是同行或者同列,这个时候只要检测要使得两点连通并且只能有一个拐点的话,这个拐点只有两个(x,n)和(m, y),所以就变成了带上这两个虚拟的点,能不能成功连通,伪代码是这样的:

//假设方法名是 oneFoldPoint(x,y,m,n)

if(this.dealOneLine(x, y, x, n) && this.dealOneLine(x, n, m, n)) {

// console.log('纵向一个折点');

}else if(this.dealOneLine( m, y, m, n) && this.dealOneLine( x, y, m, y)) {

// console.log('横向一个折点');

return this.isSamePic();

}

两个拐点:

这种情况,可以理解为出发地能不能到达目的地,将一个点作为不动点,另外一点寻找正确的路径找到不动点。所以这个动点就得通过遍历上线左右四个方向找到适合自己路径。每移动一次,就得使用oneFoldPoint判断是否可以通过一个拐点连通,如果可以直接返回,如果不能连通就再移动。

基本上这些就是连连看比较核心的算法了。在一块儿我们的讨论的过程中,@宁宁提到了两外一个思路,就是分别遍历(x,y)和(m,n)四个方向,找到可以连通的路径。这个我没有去实现,但是感觉可以行的通。(做这个小游戏的一好处已经体现出来了,感觉非常好)

最后就是一些辅助功能,如:连接成功或是失败怎么表现、过关成功和失败处理、倒计时处理等等,这些都比较常规,也比较简单,这里就不再赘述了~

交流过程中,@尊杰也提到了一些安全方面的问题,如:通过提供的接口,机器进行过关;我这里没有进行处理,倒是需要考虑的地方。@jedmeng提到,可以将逻辑、数据和UI进行分离,各自完成各自的逻辑,相互直接不能有太多影响,这个想法会在以后的开发中多多考虑这方面的问题。还存在一个问题就是:我可以记录路径,但是不能顺序记录路径,导致不能进行画线,我初步分析了一下,应该是我的算法没有办法准确的记录路径~这个@墨尘实现了,他跟我的算法不太一样,想了解的可以看这里。

这里是实现连连看的源码:

/**

* LinkGame 360产品连连看

* @author 黑MAO

* @time 2014-7-24

* @desription 描述

*/

(function() {

'use strict';

var isError = false;

var clickTimes = 0;

var timer = null;

var pointOne = {

x: 0,

y: 0

};

var pointTwo = {

x: 0,

y: 0

};

var levelSum = 1;

/**

* LinkGame构造函数

* @param {Number} rows 行数

* @param {Number} cols 列数

*/

function LinkGame(rows, cols) {

if((rows && rows%2 != 0) && (rows && rows%2 != 0)) {

isError = true;

}

this.rows = rows || 6;

this.cols = cols || 7;

}

$.extend(LinkGame.prototype, {

/**

* 初始化函数

* @param {Boolean} restart 是否是重新初始化

* @param {Number} total 总倒计时时间,默认值200s

* @param {Number} level 等级,默认是levelSum

*/

init: function(restart, total, level) {

total = total || 200;

this.total = total;

levelSum = level || levelSum;

if(isError) return;

this.restart = restart || false;

this.initGameBoard();

this.initEvent();

//初始化时间条

this.startTime(total, 300);

this.setLevel(levelSum);

},

//初始化棋盘

initGameBoard: function() {

var $gameBoard = $('.game-board');

this.restart && $gameBoard.html('');

for(var y = 1; y <= this.rows; y++) {

for(var x = 1; x <= this.cols; x++) {

this.renderHtml(x, y);

}

}

this.fillBoardData();

},

//重新初始化棋盘

rebuildGameBoard: function() {

var $items = $('.game-board').find('.item');

this.fillBoardData($items.length);

},

//初始化事件

initEvent: function() {

var self = this;

var $gameBoard = $('.game-board');

$gameBoard.find('.item').on('click', function(e) {

e.preventDefault();

var pos = $(this).data('pos').split('_');

clickTimes++;

if(clickTimes > 2) return;

if(pointOne.x > 0 || pointOne.y > 0) {

pointTwo.x = pos[0];

pointTwo.y = pos[1];

$(this).addClass('current-one');

}else {

pointOne.x = pos[0];

pointOne.y = pos[1];

$(this).addClass('current-two');

}

self.dealGame(this);

});

},

/**

* 渲染棋子

* @param {Number} x 横坐标

* @param {Number} y 纵坐标

*/

renderHtml: function(x, y) {

var $gameBoard = $('.game-board');

var left= 15+(x-1)*79;

var top = 15+(y-1)*79;

var pos = x + '_' + y;

var $item = $('

$gameBoard.append($item);

$item.css({

top: top,

left: left

});

},

/**

* 填充数据

* @param {Number} total 棋子总个数

*/

fillBoardData: function(total) {

var sourceArr = this.getRandomData(total).sort(this.randomSort);

var $gameBoard = $('.game-board');

$.each(sourceArr, function(i, value) {

var className = 'p'+value;

var pos = $gameBoard.find('.item').eq(i).data('pos')

$gameBoard.find('.item').eq(i).data('pic', className).removeClass()

.addClass(className)

.addClass('item')

.addClass('pos' + pos);

});

},

/**

* 获取源数据

* @param {Number} total 获取个数,默认整个棋盘需要的棋子数

* @returns {Array} 源数据

*/

getRandomData: function(total) {

total = total || this.cols * this.rows;

var halfTotal = total/2;

var pieces = [];

for(var i = 0; i < halfTotal; i++) {

//保证每个元素都是成双的

var num = Math.floor(Math.random() * 45);

pieces.push(num);

pieces.push(num);

}

return pieces;

},

/**

* 随机排序算法

* @returns {number} -1或1

*/

randomSort: function() {

return Math.random() > 0.5 ? -1 : 1;

},

/**

* 开始计时

* @param {Number} total 总时间,单位秒

* @param {Number} interval 间隔时间

*/

startTime: function(total, interval) {

interval = interval || 1000;

var self = this;

var $bar = $('.time-line').find('.bar');

var remain = total;

this.reset();

clearInterval(timer);

$('.remain-time').html(total);

$bar.css('background-color', '#40b60f');

timer = setInterval(function() {

if(remain < 0.1) {

clearInterval(timer);

self.fail();

return;

}

remain = remain-interval/1000;

$bar.css('width', remain*100/total + '%');

if(remain*100/total > 25 && remain*100/total < 50) {

$bar.css('background-color', 'orange');

}else if(remain*100/total <= 25){

$bar.css('background-color', 'red');

}

$('.remain-time').html(Math.round(remain));

},interval)

},

/**

* 处理游戏逻辑

* @param {Object} el 需要处理的元素

*/

dealGame: function(el) {

var x = pointOne.x * 1;

var y = pointOne.y * 1;

var m = pointTwo.x * 1;

var n = pointTwo.y * 1;

var self = this;

if(clickTimes > 2) return;

this.dealSelectStatus(el);

//点击同一个点

if(x == m && y == n) {

self.showError();

return;

}

if(pointTwo.x > 0 || pointTwo.y > 0) {

if(self.isOk(x, y, m, n)) {

self.showRight();

}else {

self.showError();

}

}

},

/**

* 连线没有折点的处理

* @param {Number} x 第一个点的横坐标

* @param {Number} y 第一个点的纵坐标

* @param {Number} m 第二个点的横坐标

* @param {Number} n 第二个点的纵坐标

* @returns {Boolean} 是否可以连通

*/

noFoldPoint: function(x, y, m, n) {

if(this.isOneLine(x, y, m, n)) {

if(this.dealOneLine(x, y, m, n)) {

// console.log('同行或同列');

return this.isSamePic();

}

}

return false;

},

/**

* 处理在一条线上的情况

* @param {Number} x 第一个点的横坐标

* @param {Number} y 第一个点的纵坐标

* @param {Number} m 第二个点的横坐标

* @param {Number} n 第二个点的纵坐标

* @returns {boolean} 是否可以连通

*/

dealOneLine: function(x, y, m, n) {

var $gameBoard = $('.game-board');

var currentOnePos = $gameBoard.find('.current-one').data('pos');

var currentTwoPos = $gameBoard.find('.current-two').data('pos');

var minX = Math.min(x, m);

var maxX = Math.max(x, m);

var minY = Math.min(y, n);

var maxY = Math.max(y, n);

var isSuccess = true;

if(x == m) {

for(var b = minY; b <= maxY; b++) {

var pos = x + '_' + b;

var $item = $gameBoard.find('.pos'+ pos);

var status = $item.data('status');

if(status == 1 && pos != currentOnePos && pos != currentTwoPos) {

isSuccess = false;

break;

}

}

}else if(y == n) {

for(var a = minX; a <= maxX; a++) {

var pos = a + '_' + y;

var $item = $gameBoard.find('.pos'+ pos);

var status = $item.data('status');

if(status == 1 && pos != currentOnePos && pos != currentTwoPos) {

isSuccess = false;

break;

}

}

}

return isSuccess;

},

/**

* 处理一个折点的情况

* @param {Number} x 第一个点的横坐标

* @param {Number} y 第一个点的纵坐标

* @param {Number} m 第二个点的横坐标

* @param {Number} n 第二个点的纵坐标

* @returns {Boolean} 是否可以连通

*/

oneFoldPoint: function(x, y, m, n) {

//两种情况

if(this.dealOneLine(x, y, x, n) && this.dealOneLine(x, n, m, n)) {

// console.log('纵向一个折点');

return this.isSamePic();

}else if(this.dealOneLine( m, y, m, n) && this.dealOneLine( x, y, m, y)) {

// console.log('横向一个折点');

return this.isSamePic();

}

return false;

},

/**

* 处理两个折点的情况

* @param {Number} x 第一个点的横坐标

* @param {Number} y 第一个点的纵坐标

* @param {Number} m 第二个点的横坐标

* @param {Number} n 第二个点的纵坐标

* @returns {boolean} 是否可以连通

*/

twoFoldPoint: function(x, y, m, n) {

if(this.deepSearch(x, y, m, n, 'right')

|| this.deepSearch(x, y, m, n, 'down')

|| this.deepSearch(x, y, m, n, 'left')

|| this.deepSearch(x, y, m, n, 'up')) {

// console.log('两个折点');

return true;

}

return false;

},

/**

* 深度搜索

* @param {Number} x 第一个点的横坐标

* @param {Number} y 第一个点的纵坐标

* @param {Number} m 第二个点的横坐标

* @param {Number} n 第二个点的纵坐标

* @param {String} direction 搜索方向

* @returns {Boolean} 是否可以连通

*/

deepSearch: function(x, y, m, n, direction) {

switch (direction) {

case 'up':

for(var i = y - 1; i >= 0; i--) {

if(!this.isHasPic(x, i)) {

var result = this.oneFoldPoint(x, i, m, n);

if(!result) continue;

return result;

}else {

return false;

}

}

case 'down':

for(var i = y + 1; i <= this.rows + 1; i++) {

if(!this.isHasPic(x, i)) {

var result = this.oneFoldPoint(x, i, m, n);

if(!result) continue;

return result;

}else {

return false;

}

}

case 'left':

for(var i = x - 1; i >= 0; i--) {

if(!this.isHasPic(i, y)) {

var result = this.oneFoldPoint(i, y, m, n);

if(!result) continue;

return result;

}else {

return false;

}

}

case 'right':

for(var i = x + 1; i <= this.cols + 1; i++) {

if(!this.isHasPic(i, y)) {

var result = this.oneFoldPoint(i, y, m, n);

if(!result) continue;

return result;

}else {

return false;

}

}

}

},

/**

* 检测是否存在棋子

* @param {Number} x 横坐标

* @param {Number} y 纵坐标

* @returns {boolean} 是否存在

*/

isHasPic: function(x, y) {

var status = $('.game-board').find('.pos' + x + '_' + y).data('status');

return status == 1 ? true : false;

},

/**

* 检测两点是否同行或同列

* @param {Number} x 第一个点的横坐标

* @param {Number} y 第一个点的纵坐标

* @param {Number} m 第二个点的横坐标

* @param {Number} n 第二个点的纵坐标

* @returns {boolean} 是否同行或同列

*/

isOneLine: function(x, y, m, n) {

if(x == m || y == n){

return true;

}

return false;

},

/**

* 检测选中两点是否相同棋子

* @returns {boolean}

*/

isSamePic: function() {

var $gameBoard = $('.game-board');

var $currentOne = $gameBoard.find('.current-one');

var $currentTwo = $gameBoard.find('.current-two');

if($currentOne.data('pic') == $currentTwo.data('pic')) {

return true;

}else {

return false;

}

},

/**

* 检测两点是否可以连通

* @param {Number} x 第一个点的横坐标

* @param {Number} y 第一个点的纵坐标

* @param {Number} m 第二个点的横坐标

* @param {Number} n 第二个点的纵坐标

* @returns {boolean}

*/

isOk: function(x, y, m, n) {

if(this.noFoldPoint(x, y, m, n) || this.oneFoldPoint(x, y, m, n) || this.twoFoldPoint(x, y, m, n)) {

return true;

}

return false;

},

/**

* 处理选中状态

* @param {Object} el 选中元素

*/

dealSelectStatus: function(el) {

$(el).addClass('selected');

},

//提示功能

hints: function() {

var self = this;

var switchFlag = false;

var $items = $('.game-board').find('.item');

$items.each(function(i, sourceItem) {

var $sourceItem = $(sourceItem);

var $remainItems = $sourceItem.siblings('.item');

var sourcePos = $sourceItem.data('pos').split('_');

$remainItems.each(function(i, item) {

var $targetItem = $(item);

var targetPos = $targetItem.data('pos').split('_');

$sourceItem.addClass('current-one');

$targetItem.addClass('current-two');

if(self.isSamePic()) {

pointOne = {

x: sourcePos[0],

y: sourcePos[1]

};

pointTwo = {

x: targetPos[0],

y: targetPos[1]

};

if(self.isOk(pointOne.x, pointOne.y, pointTwo.x, pointTwo.y)) {

$targetItem.addClass('tip');

$sourceItem.addClass('tip');

self.reset();

switchFlag = true;

$sourceItem.removeClass('current-one');

$targetItem.removeClass('current-two');

return false;

}

}

$sourceItem.removeClass('current-one');

$targetItem.removeClass('current-two');

});

if(switchFlag) return false;

});

//没有可以提示的情况下,重新排序

if(!switchFlag) {

self.rebuildGameBoard();

self.hints();

}

},

//可正确连线

showRight: function() {

var self = this;

var $gameBoard = $('.game-board');

var $currentOne = $gameBoard.find('.current-one');

var $currentTwo = $gameBoard.find('.current-two');

var posOne = $currentOne.data('pos');

var posTwo = $currentTwo.data('pos');

$currentOne.addClass('remove').data('status', 0);

$currentTwo.addClass('remove').data('status', 0);

setTimeout(function() {

$currentOne.removeClass().addClass('item-remove').addClass('pos'+posOne);

$currentTwo.removeClass().addClass('item-remove').addClass('pos'+posTwo);

self.reset();

self.checkSuccess();

}, 300);

},

//不可正确连线

showError: function() {

var self = this;

var $gameBoard = $('.game-board');

var $currentOne = $gameBoard.find('.current-one');

var $currentTwo = $gameBoard.find('.current-two');

$currentOne.addClass('error');

$currentTwo.addClass('error');

setTimeout(function() {

$currentOne.removeClass('error').removeClass('current-one').removeClass('selected').remove('tip');

$currentTwo.removeClass('error').removeClass('current-two').removeClass('selected').remove('tip');

self.reset();

}, 300);

},

//检测是否过关

checkSuccess: function() {

var $item = $('.game-board').find('div').filter('.item');

if(!$item[0]) {

clearInterval(timer);

this.win();

}

},

//过关成功通知

win: function() {

var self = this;

var total = this.total;

var newTotal = 0;

clearInterval(timer);

if(total > 100) {

this.showMsg('成功提示', '看来你很厉害,要不要再来一局!点击确定减少10秒钟');

newTotal = total - 10;

}else if(total > 50) {

this.showMsg('成功提示', '果然不同反响!点击确定减少5秒钟');

newTotal = total - 5;

}else if(total > 10){

this.showMsg('成功提示', '你要超神啊!点击确定减少1秒钟');

newTotal = total - 1;

}

$('.sure-btn').off('click').on('click', function(e) {

e.preventDefault();

self.init(true, newTotal);

levelSum++;

self.hideMsg();

});

$('.unsure-btn').off('click').on('click', function(e) {

e.preventDefault();

self.hideMsg();

});

},

//过关失败通知

fail:function () {

var self = this;

this.showMsg('失败提示', '不要气馁,点击确定重新开始,点击取消关闭');

$('.sure-btn').off('click').on('click', function(e) {

e.preventDefault();

$('.restart').trigger('click');

levelSum = 1;

self.hideMsg();

});

$('.unsure-btn').off('click').on('click', function(e) {

e.preventDefault();

self.hideMsg();

$('.item').off('click').on('click', function() {

e.preventDefault();

self.showMsg('温馨提示', '您可以点击确定重新开始按钮');

});

});

},

//设置关数

setLevel: function(level) {

$('.level').find('.level-num').html(level);

},

/**

* 显示提示信息

* @param {String} title 标题

* @param {String} msg 信息内容

*/

showMsg: function(title, msg) {

$('.panel-title').html(title);

$('.panel-msg').html(msg);

$('.mask').show();

$('.panel').show();

},

//隐藏提示信息

hideMsg: function() {

$('.mask').hide();

$('.panel').hide();

this.setLevel(levelSum);

},

//重置坐标、点击状态

reset: function() {

pointOne.x = pointOne.y = pointTwo.x = pointTwo.y = 0;

clickTimes = 0;

}

});

window.LinkGame = LinkGame;

})();

通过跟小伙伴们讨论自己感觉思路更加开阔了,也希望各位大神不吝赐教,不胜感激~

java连连看倒计时_javascrpit开发连连看记录-小游戏相关推荐

  1. java开发的俄罗斯方块小游戏,可下载,2021-06-22

    java开发的俄罗斯方块小游戏,可下载 文章目录 java开发的俄罗斯方块小游戏,可下载 游戏操作介绍 游戏压缩包下载 最近在老师要求下组队,一起使用eclipse编写了Java游戏代码,导入sqli ...

  2. 用Java开发贪食蛇小游戏

    用Java开发贪食蛇小游戏 一.实验内容 1.实现贪吃蛇游戏基本功能,屏幕上随机出现一个"食物",称为豆子,上下左右控制"蛇"的移动,吃到"豆子&qu ...

  3. Java开发贪吃蛇小游戏

    Java开发贪吃蛇小游戏 文章目录 Java开发贪吃蛇小游戏 一.开发思路 二.具体开发过程 1.绘制静态游戏窗口 2.导入素材图标 3.绘制游戏面板 4.绘制一条静态的小蛇 5.让小蛇动起来 ①监听 ...

  4. java代码实现打气球游戏_javascript+css3开发打气球小游戏完整代码

    效果知识点: css3画气球, 自定义属性运用,随机阵列, DOM元素操作,高级回调函数与参数复传,动态布局,鼠标事件,定时器运用,CSS3新增样式等. css代码如下: {margin:0;padd ...

  5. java代码实现打气球游戏_关于javascript和css3开发打气球小游戏的完整代码

    这篇文章主要介绍了关于javascript和css3开发打气球小游戏的完整代码,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 这是一个简单但是印象深刻的小游戏,打气球小游戏的实现代码, ...

  6. 226款H5手机端小游戏源码下载 - HTML+JavaScript开发的网页小游戏开源源码大合集,经过亲测可用!

    演示端:http://game.tutou.wang/  (手机访问)  可在线试玩的分享. 链接:https://pan.baidu.com/s/1-R6wEZjLXYm0iowBJLFS8g?pw ...

  7. android开发--推箱子小游戏(二)

    一.前言 迎来第二章的更新啦:使用ListView实现关卡的选择. 本章的内容有点小复杂,毕竟涉及使用了安卓开发中最难用也是最常用的控件之一:ListView 本章可以说是复杂但是单一吧.主要是想大家 ...

  8. 如何开发一个扫雷小游戏?

    如何用C#开发一个扫雷小游戏? 十分自豪的说,计算机编程就是变魔术,每一个coder都是一个魔术师. 初学C#的时候,我相信很多人都和我一样,学会了基本语法,掌握了基本的数据结构,也见过了不少微软提供 ...

  9. 游戏自审自查报告_开发的射箭小游戏上线了,分享一下我在开发过程中遇到的问题...

    利用业余时间开发的微信小游戏-射箭救人质上线了,主要玩法就是操作弓箭射断绳子把人救下来就可以了.图片资源是我找一个朋友做的.开发过程不算太顺利.磕磕绊绊做了12关.希望大家支持下.谢谢. 分享一下我在 ...

  10. C语言开发打气球小游戏

    C语言开发打气球小游戏 首先我们写一下项目所需要的头文件 #include<stdio.h>//标准输入输出头文件 #include<math.h>//数学库头文件 #incl ...

最新文章

  1. 关于WriteFile函数的lpNumberOfBytesWritten在Win8开始的不同
  2. [补档][中山市选2011]杀人游戏
  3. php调用c windows,php:在WINDOWS中设置计划任务执行PHP文件_PHP教程
  4. 【收藏】HDFS的Java API使用
  5. OpenStack核心组件-glance镜像服务
  6. python对excel操作简书_Python读写Excel表格,就是这么简单粗暴又好用
  7. 数据库有哪些设计技巧
  8. linux怎么才能算telnet成功_怎么表白才算成功呢
  9. ios13苹方字体ttf_字体 | iOS1013 SF Compact Rounded 英文 By alex
  10. react留言功能准备一
  11. general protection fault怎么办_法院离婚调解书我想办补充协议怎么办?-免费法律咨询...
  12. awesome python 中文版 相见恨晚!(pythonNB的第三方资源库)
  13. JSONSerializer把类转换成JSON字符串
  14. 【Linux】VMware虚拟机中如何配置静态IP
  15. 钢构件建筑材料英国UKCA认证—EN 13381-4
  16. BoundsChecker用法
  17. 给大家分享【CDR基础教程】
  18. 判定两个矩形框是否相交
  19. html怎么设置后退链接,怎么创建HTML后退按钮?
  20. python 换国内源

热门文章

  1. 力扣:714.买卖股票的最佳时机含手续费
  2. 使用GitHub搭建个人博客
  3. 软件测试工程师需要具备哪些能力?
  4. python中if语句中可用break_python跳出if语句
  5. OpenGL日常-GLAD
  6. python 三角函数计算
  7. 致远免费动态域名解析服务软件[永久免费]
  8. css折叠样式(4)——div+css布局
  9. 鸿雪因缘--穿越千年的朋友圈
  10. 配置cts performance最优范围