导言

在一个风和日丽的一天,看完了疯狂HTML 5+CSS 3+JavaScript讲义,跟着做了书里最后一章的俄罗斯方块小游戏,并做了一些改进,作为自己前端学习的第一站。

游戏效果:

制作思路

因为书里的俄罗斯方块比较普通,太常规了,不是很好看,所以我在网上找了上面那张图片,打算照着它来做。(请无视成品和原图的差距)

然后便是游戏界面和常规的俄罗斯方块游戏逻辑。

接着便是游戏结束界面了。

原本想做个弹出层,但觉得找图片有点麻烦,所以就在网上找了文字特效,套用了一下。

代码实现:

首先是html文件和css文件,主要涉及了布局方面。作为新手,在上面真的是翻来覆去的踩坑。o(╥﹏╥)o

index.html

<!DOCTYPE html>
<html>
<head>
<title>俄罗斯方块</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<link rel=stylesheet type="text/css" href="teris.css">
<style type="text/css">
/*导入外部的字体文件*/
@font-face{
font-family:tmb;/*为字体命名为tmb*/
src:url("DS-DIGIB.TTF") format("TrueType");/*format为字体文件格式,TrueType为ttf*/
}
div>span{
font-family:tmb;
font-size:18pt;
color:green;
}
</style>
</head> <body>
<div id="container" class="bg">
<!--ui-->
<div class="ui_bg">
<div style="float:left;margin-right:4px;">
速度:<span id="cur_speed">1</span>
</div>
<div style="float:left;">
当前分数:<span id="cur_points">0</span>
</div>
<div style="float:right;">
最高分数:<span id="max_points">0</span>
</div>
</div>
<canvas id="text" width="500" height="100" style="position:absolute;"></canvas>
<canvas id="stage" width="500" height="100" style="position:absolute;"></canvas>
</div>
<script src='EasePack.min.js'></script>
<script src='TweenLite.min.js'></script>
<script src='easeljs-0.7.1.min.js'></script>
<script src='requestAnimationFrame.js'></script>
<script type="text/javascript" src="jquery-3.4.1.min.js"></script>
<script type="text/javascript" src="teris.js"></script>
</body>
</html>

teris.css

*{
margin:;
padding:;
}
html, body{
width:100%;
height:100%;
} .bg{
font-size:13pt;
background-color:rgb(239, 239, 227);
/*好看的渐变色*/
background-image:radial-gradient(rgb(239, 239, 227), rgb(230, 220, 212));
/*阴影*/
box-shadow:#cdc8c1 -1px -1px 7px 0px;
padding-bottom:4px;
} .ui_bg{
border-bottom:1px #a69e9ea3 solid;
padding-bottom:2px;
overflow:hidden;/*没有这句的话因为子div都设置了float,所以是浮在网页上的,所以父div就没有高度,这句清除了浮动,让父div有了子div的高度*/
}

然后是重头戏,teris.js

游戏变量

//游戏设定
var TETRIS_ROWS = 20;
var TETRIS_COLS = 14;
var CELL_SIZE = 24;
var NO_BLOCK=0;
var HAVE_BLOCK=1;
// 定义几种可能出现的方块组合
var blockArr = [
// Z
[
{x: TETRIS_COLS / 2 - 1 , y:0},
{x: TETRIS_COLS / 2 , y:0},
{x: TETRIS_COLS / 2 , y:1},
{x: TETRIS_COLS / 2 + 1 , y:1}
],
// 反Z
[
{x: TETRIS_COLS / 2 + 1 , y:0},
{x: TETRIS_COLS / 2 , y:0},
{x: TETRIS_COLS / 2 , y:1},
{x: TETRIS_COLS / 2 - 1 , y:1}
],
// 田
[
{x: TETRIS_COLS / 2 - 1 , y:0},
{x: TETRIS_COLS / 2 , y:0},
{x: TETRIS_COLS / 2 - 1 , y:1},
{x: TETRIS_COLS / 2 , y:1}
],
// L
[
{x: TETRIS_COLS / 2 - 1 , y:0},
{x: TETRIS_COLS / 2 - 1, y:1},
{x: TETRIS_COLS / 2 - 1 , y:2},
{x: TETRIS_COLS / 2 , y:2}
],
// J
[
{x: TETRIS_COLS / 2 , y:0},
{x: TETRIS_COLS / 2 , y:1},
{x: TETRIS_COLS / 2 , y:2},
{x: TETRIS_COLS / 2 - 1, y:2}
],
// □□□□
[
{x: TETRIS_COLS / 2 , y:0},
{x: TETRIS_COLS / 2 , y:1},
{x: TETRIS_COLS / 2 , y:2},
{x: TETRIS_COLS / 2 , y:3}
],
// ┴
[
{x: TETRIS_COLS / 2 , y:0},
{x: TETRIS_COLS / 2 - 1 , y:1},
{x: TETRIS_COLS / 2 , y:1},
{x: TETRIS_COLS / 2 + 1, y:1}
]
]; // 记录当前积分
var curScore=0;
// 记录曾经的最高积分
var maxScore=1;
var curSpeed=1;
//ui元素
var curSpeedEle=document.getElementById("cur_speed");
var curScoreEle=document.getElementById("cur_points");
var maxScoreEle=document.getElementById("max_points"); var timer;//方块下落控制 var myCanvas;
var canvasCtx;
var tetris_status;//地图数据
var currentFall;//当前下落的block

游戏界面的完善

//create canvas
function createCanvas(){
myCanvas=document.createElement("canvas");
myCanvas.width=TETRIS_COLS*CELL_SIZE;
myCanvas.height=TETRIS_ROWS*CELL_SIZE;
//绘制背景
canvasCtx=myCanvas.getContext("2d");
canvasCtx.beginPath();
//TETRIS_COS
for(let i=1; i<TETRIS_COLS; i++){
canvasCtx.moveTo(i*CELL_SIZE, 0);
canvasCtx.lineTo(i*CELL_SIZE, myCanvas.height);
}
for(let i=1; i<TETRIS_ROWS; i++){
canvasCtx.moveTo(0, i*CELL_SIZE);
canvasCtx.lineTo(myCanvas.width, i*CELL_SIZE);
}
canvasCtx.closePath();
canvasCtx.strokeStyle="#b4a79d";
canvasCtx.lineWidth=0.6;
canvasCtx.stroke();
//第一行,最后一行,第一列,最后一列粗一点。
canvasCtx.beginPath();
canvasCtx.moveTo(0, 0);
canvasCtx.lineTo(myCanvas.width, 0);
canvasCtx.moveTo(0, myCanvas.height);
canvasCtx.lineTo(myCanvas.width, myCanvas.height);
canvasCtx.moveTo(0, 0);
canvasCtx.lineTo(0, myCanvas.height);
canvasCtx.moveTo(myCanvas.width, 0);
canvasCtx.lineTo(myCanvas.width, myCanvas.height);
canvasCtx.closePath();
canvasCtx.strokeStyle="#b4a79d";
canvasCtx.lineWidth=4;
canvasCtx.stroke();
//设置绘制block时的style
canvasCtx.fillStyle="#201a14";
}

draw canvas

 function changeWidthAndHeight(w, h){
//通过jquery设置css
h+=$("ui_bg").css("height")+$("ui_bg").css("margin-rop")+$("ui_bg").css("margin-bottom")+$("ui_bg").css("padding-top")+$("ui_bg").css("padding-bottom");
$(".bg").css({
"width":w,
"height":h,
"top":0, "bottom":0, "right":0, "left":0,
"margin":"auto"
});
}

change width and height

 //draw blocks
function drawBlocks(){
//清空地图
for(let i=0; i<TETRIS_ROWS;i++){
for(let j=0;j<TETRIS_COLS;j++)
canvasCtx.clearRect(j*CELL_SIZE+1, i*CELL_SIZE+1, CELL_SIZE-2, CELL_SIZE-2);
}
//绘制地图
for(let i=0; i<TETRIS_ROWS;i++){
for(let j=0;j<TETRIS_COLS;j++){
if(tetris_status[i][j]!=NO_BLOCK)
canvasCtx.fillRect(j*CELL_SIZE+1, i*CELL_SIZE+1, CELL_SIZE-2, CELL_SIZE-2);//中间留点缝隙
}
}
//绘制currentFall
for(let i=0;i<currentFall.length;i++)
canvasCtx.fillRect(currentFall[i].x*CELL_SIZE+1, currentFall[i].y*CELL_SIZE+1, CELL_SIZE-2,CELL_SIZE-2);
}

draw block

游戏逻辑

 function rotate(){
// 定义记录能否旋转的旗标
var canRotate = true;
for (var i = 0 ; i < currentFall.length ; i++)
{
var preX = currentFall[i].x;
var preY = currentFall[i].y;
// 始终以第三个方块作为旋转的中心,
// i == 2时,说明是旋转的中心
if(i != 2)
{
// 计算方块旋转后的x、y坐标
var afterRotateX = currentFall[2].x + preY - currentFall[2].y;
var afterRotateY = currentFall[2].y + currentFall[2].x - preX;
// 如果旋转后所在位置已有方块,表明不能旋转
if(tetris_status[afterRotateY][afterRotateX + 1] != NO_BLOCK)
{
canRotate = false;
break;
}
// 如果旋转后的坐标已经超出了最左边边界
if(afterRotateX < 0 || tetris_status[afterRotateY - 1][afterRotateX] != NO_BLOCK)
{
moveRight();
afterRotateX = currentFall[2].x + preY - currentFall[2].y;
afterRotateY = currentFall[2].y + currentFall[2].x - preX;
break;
}
if(afterRotateX < 0 || tetris_status[afterRotateY-1][afterRotateX] != NO_BLOCK)
{
moveRight();
break;
}
// 如果旋转后的坐标已经超出了最右边边界
if(afterRotateX >= TETRIS_COLS - 1 ||
tetris_status[afterRotateY][afterRotateX+1] != NO_BLOCK)
{
moveLeft();
afterRotateX = currentFall[2].x + preY - currentFall[2].y;
afterRotateY = currentFall[2].y + currentFall[2].x - preX;
break;
}
if(afterRotateX >= TETRIS_COLS - 1 ||
tetris_status[afterRotateY][afterRotateX+1] != NO_BLOCK)
{
moveLeft();
break;
}
}
}
if(canRotate){
for (var i = 0 ; i < currentFall.length ; i++){
var preX = currentFall[i].x;
var preY = currentFall[i].y;
if(i != 2){
currentFall[i].x = currentFall[2].x +
preY - currentFall[2].y;
currentFall[i].y = currentFall[2].y +
currentFall[2].x - preX;
}
}
localStorage.setItem("currentFall", JSON.stringify(currentFall));
}
}

旋转

 //按下 下 或 interval到了
function next(){
if(moveDown()){
//记录block
for(let i=0;i<currentFall.length;i++)
tetris_status[currentFall[i].y][currentFall[i].x]=HAVE_BLOCK;
//判断有没有满行的
for(let j=0;j<currentFall.length;j++){
for(let i=0;i<TETRIS_COLS; i++){
if(tetris_status[currentFall[j].y][i]==NO_BLOCK)
break;
//最后一行满了
if(i==TETRIS_COLS-1){
//消除最后一行
for(let i=currentFall[j].y; i>0;i--){
for(let j=0;j<TETRIS_COLS;j++)
tetris_status[i][j]=tetris_status[i-1][j];
}
//分数增加
curScore+=5;
localStorage.setItem("curScore", curScore);
if(curScore>maxScore){
//超越最高分
maxScore=curScore;
localStorage.setItem("maxScore", maxScore);
}
//加速
curSpeed+=0.1;
localStorage.setItem("curSpeed", curSpeed);
//ui输出
curScoreEle.innerHTML=""+curScore;
maxScoreEle.innerHTML=""+maxScore;
curSpeedEle.innerHTML=curSpeed.toFixed(1);//保留两位小数
clearInterval(timer);
timer=setInterval(function(){
next();
}, 500/curSpeed);
}
}
}
//判断是否触顶
for(let i=0;i<currentFall.length;i++){
if(currentFall[i].y==0){
gameEnd();
return;
}
}
localStorage.setItem("tetris_status", JSON.stringify(tetris_status));
//新的block
createBlock();
localStorage.setItem("currentFall", JSON.stringify(currentFall));
}
drawBlocks();
} //右移
function moveRight(){
for(let i=0;i<currentFall.length;i++){
if(currentFall[i].x+1>=TETRIS_ROWS || tetris_status[currentFall[i].y][currentFall[i].x+1]!=NO_BLOCK)
return;
}
for(let i=0;i<currentFall.length;i++)
currentFall[i].x++;
localStorage.setItem("currentFall", JSON.stringify(currentFall));
return;
}
//左移
function moveLeft(){
for(let i=0;i<currentFall.length;i++){
if(currentFall[i].x-1<0 || tetris_status[currentFall[i].y][currentFall[i].x-1]!=NO_BLOCK)
return;
}
for(let i=0;i<currentFall.length;i++)
currentFall[i].x--;
localStorage.setItem("currentFall", JSON.stringify(currentFall));
return;
}
//judge can move down and if arrive at end return 1, if touch other blocks return 2, else, return 0
function moveDown(){
for(let i=0;i<currentFall.length;i++){
if(currentFall[i].y>=TETRIS_ROWS-1 || tetris_status[currentFall[i].y+1][currentFall[i].x]!=NO_BLOCK)
return true;
} for(let i=0;i<currentFall.length;i++)
currentFall[i].y+=1;
return false;
}

上下左右移动

 function gameKeyEvent(evt){
switch(evt.keyCode){
//向下
case 40://↓
case 83://S
next();
drawBlocks();
break;
//向左
case 37://←
case 65://A
moveLeft();
drawBlocks();
break;
//向右
case 39://→
case 68://D
moveRight();
drawBlocks();
break;
//旋转
case 38://↑
case 87://W
rotate();
drawBlocks();
break;
}
}

keydown事件监听

其他的详细情况可以看源代码,我就不整理了。

接下来我们看游戏结束时的特效。因为我也不是很懂,所以在这里整理的会比较详细。当做学习。

 //game end
function gameEnd(){
clearInterval(timer);
//键盘输入监听结束
window.onkeydown=function(){
//按任意键重新开始游戏
window.onkeydown=gameKeyEvent;
//初始化游戏数据
initData();
createBlock();
localStorage.setItem("currentFall", JSON.stringify(currentFall));
localStorage.setItem("tetris_status", JSON.stringify(tetris_status));
localStorage.setItem("curScore", curScore);
localStorage.setItem("curSpeed", curSpeed);
//绘制
curScoreEle.innerHTML=""+curScore;
curSpeedEle.innerHTML=curSpeed.toFixed(1);//保留两位小数
drawBlocks();
timer=setInterval(function(){
next();
}, 500/curSpeed);
//清除特效
this.stage.removeAllChildren();
this.textStage.removeAllChildren();
};
//特效,游戏结束
setTimeout(function(){
initAnim();
//擦除黑色方块
for(let i=0; i<TETRIS_ROWS;i++){
for(let j=0;j<TETRIS_COLS;j++)
canvasCtx.clearRect(j*CELL_SIZE+1, i*CELL_SIZE+1, CELL_SIZE-2, CELL_SIZE-2);
}
}, 200);
//推迟显示Failed
setTimeout(function(){
if(textFormed) {
explode();
setTimeout(function() {
createText("FAILED");
}, 810);
} else {
createText("FAILED");
}
}, 800);
}

上面代码里的localstorage是html5的本地数据存储。因为不是运用很难,所以具体看代码。

整个特效是运用了createjs插件。要引入几个文件。

easeljs-0.7.1.min.js, EasePacj.min.js, requestAnimationFrame.js和TweenLite.min.js
游戏重新开始就要清除特效。我看api里我第一眼望过去最明显的就是removeAllChildren(),所以就选了这个。其他的改进日后再说。

        //清除特效
this.stage.removeAllChildren();
this.textStage.removeAllChildren();
function initAnim() {
initStages();
initText();
initCircles();
//在stage下方添加文字——按任意键重新开始游戏.
tmp = new createjs.Text("t", "12px 'Source Sans Pro'", "#54555C");
tmp.textAlign = 'center';
tmp.x = 180;
tmp.y=350;
tmp.text = "按任意键重新开始游戏";
stage.addChild(tmp);
animate();
}

initAnim

上面初始化了一个stage,用于存放特效,一个textstage,用于形成“FAILED”的像素图片。还有一个按任意键重新游戏的提示。同时开始每隔一段时间就刷新stage。

根据block的位置来初始化小圆点。

 function initCircles() {
circles = [];
var p=[];
var count=0;
for(let i=0; i<TETRIS_ROWS;i++)
for(let j=0;j<TETRIS_COLS;j++)
if(tetris_status[i][j]!=NO_BLOCK)
p.push({'x':j*CELL_SIZE+2, 'y':i*CELL_SIZE+2, 'w':CELL_SIZE-3, 'h':CELL_SIZE-4});
for(var i=0; i<250; i++) {
var circle = new createjs.Shape();
var r = 7;
//x和y范围限定在黑色block内
var x = p[count]['x']+p[count]['w']*Math.random();
var y = p[count]['y']+p[count]['h']*Math.random();
count++;
if(count>=p.length)
count=0;
var color = colors[Math.floor(i%colors.length)];
var alpha = 0.2 + Math.random()*0.5;
circle.alpha = alpha;
circle.radius = r;
circle.graphics.beginFill(color).drawCircle(0, 0, r);
circle.x = x;
circle.y = y;
circles.push(circle);
stage.addChild(circle);
circle.movement = 'float';
tweenCircle(circle);
}
}

initCircles

然后再讲显示特效Failed的createText()。先将FAILED的text显示在textstage里,然后ctx.getImageData.data获取像素数据,并以此来为每个小圆点定义位置。

 function createText(t) {
curText=t;
var fontSize = 500/(t.length);
if (fontSize > 80) fontSize = 80;
text.text = t;
text.font = "900 "+fontSize+"px 'Source Sans Pro'";
text.textAlign = 'center';
text.x = TETRIS_COLS*CELL_SIZE/2;
text.y = 0;
textStage.addChild(text);
textStage.update(); var ctx = document.getElementById('text').getContext('2d');
var pix = ctx.getImageData(0,0,600,200).data;
textPixels = [];
for (var i = pix.length; i >= 0; i -= 4) {
if (pix[i] != 0) {
var x = (i / 4) % 600;
var y = Math.floor(Math.floor(i/600)/4);
if((x && x%8 == 0) && (y && y%8 == 0)) textPixels.push({x: x, y: y});
}
} formText();
textStage.clear();//清楚text的显示
}

CreateText

跟着代码的节奏走,我们现在来到了formtext.

 function formText() {
for(var i= 0, l=textPixels.length; i<l; i++) {
circles[i].originX = offsetX + textPixels[i].x;
circles[i].originY = offsetY + textPixels[i].y;
tweenCircle(circles[i], 'in');
}
textFormed = true;
if(textPixels.length < circles.length) {
for(var j = textPixels.length; j<circles.length; j++) {
circles[j].tween = TweenLite.to(circles[j], 0.4, {alpha: 0.1});
}
}
}

formtext

explode()就是讲已组成字的小圆点给重新遣散。

动画实现是使用了tweenlite.

 function tweenCircle(c, dir) {
if(c.tween) c.tween.kill();
if(dir == 'in') {
/*TweenLite.to 改变c实例的x坐标,y坐标,使用easeInOut弹性函数,透明度提到1,改变大小,radius,总用时0.4s*/
c.tween = TweenLite.to(c, 0.4, {x: c.originX, y: c.originY, ease:Quad.easeInOut, alpha: 1, radius: 5, scaleX: 0.4, scaleY: 0.4, onComplete: function() {
c.movement = 'jiggle';/*轻摇*/
tweenCircle(c);
}});
} else if(dir == 'out') {
c.tween = TweenLite.to(c, 0.8, {x: window.innerWidth*Math.random(), y: window.innerHeight*Math.random(), ease:Quad.easeInOut, alpha: 0.2 + Math.random()*0.5, scaleX: 1, scaleY: 1, onComplete: function() {
c.movement = 'float';
tweenCircle(c);
}});
} else {
if(c.movement == 'float') {
c.tween = TweenLite.to(c, 5 + Math.random()*3.5, {x: c.x + -100+Math.random()*200, y: c.y + -100+Math.random()*200, ease:Quad.easeInOut, alpha: 0.2 + Math.random()*0.5,
onComplete: function() {
tweenCircle(c);
}});
} else {
c.tween = TweenLite.to(c, 0.05, {x: c.originX + Math.random()*3, y: c.originY + Math.random()*3, ease:Quad.easeInOut,
onComplete: function() {
tweenCircle(c);
}});
}
}
}

TweenLite.to函数第一个参数,要做动画的实例,第二个参数,事件,第三个参数,动画改变参数。

Quad.easeInOut()意思是在动画开始和结束时缓动。
onComplete动画完成时调用的函数。易得,在我们的应用中,我们将开始下一次动画。

个人感言

其实刚开始没想做这么复杂,所以文件排的比较随意,然后就导致了后期项目完成时那副杂乱无章的样子。^_^,以后改。等我等看懂动画效果时在说,现在用的有点半懵半懂。

这篇博客写得有点乱。新手之作,就先这样吧。同上,以后改。因为不知道这个项目会不会拿来直接当我们计算机职业实践的作业。要是的话,我就彻改,连同博客。

以下是源代码地址。(我还以为csdn的下载要的积分是自己定的。等我下次彻改的时候我传到github上。现在将就一下)

https://download.csdn.net/download/qq_26136211/12011640

Html5 小游戏 俄罗斯方块的更多相关文章

  1. 推荐10款超级有趣的HTML5小游戏

    HTML5的发展速度比任何人的都想像都要更快.更加强大有效的和专业的解决方案已经被开发......甚至在游戏世界中!这里跟大家分享有10款超级趣味的HTML5游戏,希望大家能够喜欢! Kern Typ ...

  2. HTML5小游戏UI美化版

    HTML5小游戏[是男人就下一百层]UI美化版 之前写的小游戏,要么就比较简单,要么就是比较难看,或者人物本身是不会动的. 结合了其它人的经验,研究了一下精灵运动,就写一个简单的小游戏来试一下. 介绍 ...

  3. JS练习实例--编写经典小游戏俄罗斯方块

    最近在学习JavaScript,想编一些实例练练手,之前编了个贪吃蛇,但是实现时没有注意使用面向对象的思想,实现起来也比较简单所以就不总结了,今天就总结下俄罗斯方块小游戏的思路和实现吧(需要下载代码也 ...

  4. HTML5小游戏源码收藏

    html5魅族创意的贪食蛇游戏源码下载 html5网页版打砖块小游戏源码下载 html5 3D立体魔方小游戏源码下载 html5网页版飞机躲避游戏源码下载 html5三国人物连连看游戏源码下载 js ...

  5. 通通制作Html5小游戏——第二弹(仿flappy bird像素鸟)

    亲爱的博友们,我又回来啦~因为我们技术宅的思想只有技术宅懂得,好不容易写了点好玩的东西发QQ空间,结果只有11的UV,0回复....10分钟ps一个女神的素描效果发QQ空间朋友圈,一大堆回复加赞,作为 ...

  6. 菜鸟做HTML5小游戏 - 翻翻乐

    记录下开放过程.做小游戏开发,又要跨平台,flash又不支持iPhone,html5是最好的选择. 先看看最后效果: 好了,开始demo. 1.准备工作: 图片素材(省略...最后代码一起打包) 了解 ...

  7. HTML5小游戏之见缝插针

    今天给大家带来的就是一款叫做<见缝插针>的游戏.有空你就往里插,直到你无处可插!看你能过多少关! 简洁大气 黑白搭配游戏画面非常的简洁,米白色的背景中央,放置着一个不断旋转的太阳状的球体, ...

  8. HTML5小游戏【是男人就下一百层】UI美化版

    之前写的小游戏,要么就比较简单,要么就是比较难看,或者人物本身是不会动的. 结合了其它人的经验,研究了一下精灵运动,就写一个简单的小游戏来试一下. 介绍一下几个主要的类: Frame:帧的定义,主要描 ...

  9. HTML5小游戏-简单抽奖小游戏

    换了新工作以后,专注前端开发,平常空闲时间也比较多,可以多钻研一下技术,写一下博客.最近在学习canvas,参考网上的slotmachine插件,用canvas实现了一个简单抽奖小游戏.       ...

随机推荐

  1. [动图演示]Redis 持久化 RDB/AOF 详解与实践

    Redis 是一个开源( BSD 许可)的,内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件.它支持的数据类型很丰富,如字符串.链表.集 合.以及散列等,并且还支持多种排序功能. 什么叫持 ...

  2. 转:java 解析excel,带合并单元的excel

    收集了一些对博主有帮助的博文,如下 >>>>>>>>>>>第一部分: 首先,mavn导入jar包 <!-- 解析excel需要导 ...

  3. 实例详解——编译器命令#pragma section作用于函数时作用域是否覆盖到其子函数

    在之前的博客[链接脚本(Linker Script)应用实例(一)使用copy table将函数载入到RAM中运行]中,我们第一步使用#pragma section命令将PFlashProgram函数 ...

  4. Android 网络编程(一)

    概述 一.Android平台网络相关API接口 1.java.net.*(标准Java接口) java.net.*提供与联网有关的类,包括流.数据包套接字(socket).Internet协议.常见H ...

  5. java.lang.ClassNotFoundException: com.demo.search.extractAbstract.service.ExtractAbstractServiceHandler

    在利用 Spring 对 thrift 进行集成时,出现错误: avax.servlet.ServletException: Servlet.init() for servlet search-nlp ...

  6. DRF Django REST framework 之 视图组件(四)

    引言 在我们有几十上百的视图类,都有get,post等方法,在功能类似时,会导致大量的重复代码出现,显然还有很多可以优化的地方.这也就有了视图组件,它的功能非常强大,能很好的优化接口逻辑. 视图组件 ...

  7. Apache Maven从入门到升天

    喜欢就点个赞呗! GitHub项目JavaHouse同步收录 1 引入 在日常 Java 开发中,Maven 应该是必不可少的一个工具了,当然也有人使用 Gradle 的.那么 Maven 究竟是个啥 ...

  8. 移动前端不得不了解的HTML5 head 头标签 —— HTML基本的头部标签

    HTML的头部内容特别多,有针对SEO的头部信息,也有针对移动设备的头部信息.而且各个浏览器内核以及各个国内浏览器厂商都有些自己的标签元素,有很多差异性.移动端的工作已经越来越成为前端工作的重要内容, ...

  9. HDU1079 Calender Game

    Adam and Eve enter this year’s ACM International Collegiate Programming Contest. Last night, they pl ...

  10. HTML5变化

    HTML5变化 新的语义化元素 header footer nav main article section 删除了一些纯样式的标签 表单增强 新API 离线 (applicationCache ) ...