web版扫雷小游戏(四)
~~~接上篇,游戏的主体框架完成了,接下来我们对游戏中存在的两个主要实体进行分析,一个是雷点类BombObject(节点对象),一个是节点对象对应的图片对象BombImgObject,根据第一篇的介绍,这两个类的对象配合棋盘类实现游戏过程,这里重新解释下这两个类的用处:
一、雷点类(BombObject):一个承上启下的对象类别。
1. 此类的对象集合(棋盘类中的ObjList数组)组成了游戏棋盘上的每一个节点,节点的类型有空节点(数值为0)、雷点(数值为-1)、非雷非空节点(数值为N,依据节点周围的雷点个数而定)。
2. 每一个对象需要标记其在棋盘中的坐标位置(x、y),同时能够获取其周围8个方位上的节点坐标(没有即为null),这8个方位节点的属性标记为North、NorthEast、East、SouthEast、South、SouthWest、West、NorthWest。
3. 节点对象包含一个与其一一对应的图片对象(ImgObj),展现给玩家的棋盘最终以图片对象列表的形式,图片对象根据当前节点数值属性(DisplayNum)的值显示不同的图片。
类的定义如下:
//棋盘节点对象类
function BombObject(x, y, num, xNum, yNum) {
this.X = x; //节点的x坐标
this.Y = y; //节点的y坐标
this.ImgObj = new BombImgObject(num, x, y); //节点对应的图片对象
this.IsBomb = (num === -1) ? true : false; //节点是否是雷点
this.DisplayNum = (this.IsBomb) ? -1 : parseInt(num); //节点对应的数值
//北方节点对象
this.North = (function() {
if ((y - 1) < 0) {
return null;
}
else {
return { X: x, Y: y - 1 };
}
} ());
//东北方向节点对象
this.NorthEast = (function() {
if ((y - 1) < 0 || (x + 1) >= xNum) {
return null;
}
else {
return { X: x + 1, Y: y - 1 };
}
} ());
//东方的节点对象
this.East = (function() {
if ((x + 1) >= xNum) {
return null;
}
else {
return { X: x + 1, Y: y };
}
} ());
//东南方的节点对象
this.EastSouth = (function() {
if ((y + 1) >= yNum || (x + 1) >= xNum) {
return null;
}
else {
return { X: x + 1, Y: y + 1 };
}
} ());
//南方节点对象
this.South = (function() {
if ((y + 1) >= yNum) {
return null;
}
else {
return { X: x, Y: y + 1 };
}
} ());
//西南方节点对象
this.SouthWest = (function() {
if ((y + 1) >= yNum || (x - 1) < 0) {
return null;
}
else {
return { X: x - 1, Y: y + 1 };
}
} ());
//西方节点对象
this.West = (function() {
if ((x - 1) < 0) {
return null;
}
else {
return { X: x - 1, Y: y };
}
} ());
//西北方节点对象
this.WestNorth = (function() {
if ((x - 1) < 0 || (y - 1) < 0) {
return null;
}
else {
return { X: x - 1, Y: y - 1 };
}
} ());
}
//判断两个节点对象是否相等
BombObject.prototype.Equals = function(that) {
if (!(that instanceof BombObject) || that.constructor !== BombObject || that == null) {
throw new Error("the add obj is not allowed.");
return false;
}
else if (this.X == that.X && this.Y == that.Y) {
return true;
}
else {
return false;
}
};
//判断当前节点对象的坐标值是否一致
BombObject.prototype.EqualsEx = function(x, y) {
if (this.X == x && this.Y == y) {
return true;
}
else {
return false;
}
};
可以看到,节点对象类包含了一个图片对象,同时也定义了两个对象比较函数,可由节点类对象直接调用。下面来介绍这个图片对象类:
二、图片对象类(BombImgObject):定义与节点对象一一对应的图片对象。
1. 此类的对象是节点对象的表现层,节点的有些属性和操作均通过此对象实现,每个节点对象是根据节点数值属性定义的。
2. 图片类对象是展现给用户的表现层,游戏的功能及效果都是通过此层实现的,故需要在图片对象上定义鼠标事件(左键、右键、按下、弹起、左右键一起按、移入、移出等)。
3. 同时在响应鼠标事件的同时,需要触发有些功能监听事件,比如空节点点击事件、数值判断左右键同时按下事件等。
类的定义包括一个Img元素(展现给玩家用)标签对象,对应的棋盘坐标x、y,是否被标记标志flag(左键、右键的响应视为已经标记),类的定义如下:
//图片对象集合共用的鼠标类型值,0为无鼠标事件,1为左键,2为右键,3为左右键,4为滚轮
BombImgObject.MouseType = 0;
//定义各节点的图片对象类(传递图片在棋盘中的数值:0~8、-1,图片在棋盘中的x、y坐标)
function BombImgObject(altValue, xPos, yPos) {
//保存this指针,防止函数嵌套时指代不明确
var img = this; img.ImgObj = null; //图片实体对象
img.x = xPos; //图片在棋盘中的x坐标
img.y = yPos; //图片在棋盘中的y坐标
if (document.createElement) {
img.ImgObj = document.createElement("img");
}
if (img.ImgObj) {
img.ImgObj.lang = altValue; //保存当前图片对象对应的节点数值,0~8、-1
img.ImgObj.src = "img/small/normal.bmp"; //赋值默认图片路径
img.ImgObj.flag = false; //标记图片处理标示,如果图片处理过(标记、显示等)则不再响应其他事件
img.ImgObj.id = "img" + img.x + "-" + img.y; //根据图片对应棋盘中的坐标定义图片对象的id属性 //定义图片对象的鼠标按下事件
img.ImgObj.onmousedown = function() {
//如果没有触发雷点
if (BombObjectList.fireFlag !== 2) {
//判断是何种鼠标事件
switch (window.event.button) {
case 1:
//左键
if (this.src.indexOf("normal") >= 0) {
this.src = "img/small/kong.bmp";
}
//标记当前的鼠标操作类型
BombImgObject.MouseType = 1;
//图片鼠标按下事件,标记游戏开始
BombObjectList.fireFlag = 1;
break;
case 2:
//右键
if (this.src.indexOf("normal") >= 0) {
//标记图片已处理(被标记)
this.flag = true;
this.src = "img/small/flag.bmp";
BombObjectList.MarkedNum++;
}
else if (this.src.indexOf("flag") >= 0) {
//取消图片已处理标记(还原默认)
this.flag = false;
this.src = "img/small/normal.bmp";
BombObjectList.MarkedNum--;
}
//标记当前的鼠标操作类型
BombImgObject.MouseType = 2;
break;
case 3:
//左右键一起
BombImgObject.MouseType = 3;
//以该点为中心,在其8个方向上进行节点判断,如果已经都展开,则什么也不做,如果有未展开的节点,而这些节点里面有雷点,则不展开,反之将递归展开所有
BombObjectList.DC_X = img.x;
BombObjectList.DC_Y = img.y;
break;
case 4:
//滑轮
BombImgObject.MouseType = 4;
break;
}
}
}
//定义图片对象的右键处理程序,空返回
img.ImgObj.oncontextmenu = function() {
if (BombObjectList.fireFlag !== 2) {
return false;
}
}
//定义图片对象的鼠标提起事件处理程序
img.ImgObj.onmouseup = function() {
//如果没有触发雷点
if (BombObjectList.fireFlag !== 2) {
if (this.src.indexOf("flag") >= 0 || this.src.indexOf("normal") >= 0) {
//如果图片被标记处理或者未处理过,则直接返回
return;
}
else {
//如果不是右键事件,则进入处理
if (BombImgObject.MouseType !== 2) {
if (BombImgObject.MouseType !== 1) {
//双击时,不进行接下来的操作
BombImgObject.MouseType = 0;
return;
}
//标记图片对象已被处理过
this.flag = true;
//根据图片数值显示对应的图片信息
var caseValue = parseInt(this.lang);
switch (caseValue) {
case -1: //雷点
{
this.src = "img/small/fire.bmp";
//触雷,更行触发标记,以便定时器捕获
BombObjectList.fireFlag = 2;
break;
}
case 1: //该节点旁边有一个雷点,标记数值1
{
this.src = "img/small/1.bmp";
break;
}
case 2: //该节点旁边有两个雷点,标记数值2
{
this.src = "img/small/2.bmp";
break;
}
case 3: //该节点旁边有三个雷点,标记数值3
{
this.src = "img/small/3.bmp";
break;
}
case 4: //该节点旁边有四个雷点,标记数值4
{
this.src = "img/small/4.bmp";
break;
}
case 5: //该节点旁边有五个雷点,标记数值5
{
this.src = "img/small/5.bmp";
break;
}
case 6: //该节点旁边有六个雷点,标记数值6
{
this.src = "img/small/6.bmp";
break;
}
case 7: //该节点旁边有七个雷点,标记数值7
{
this.src = "img/small/7.bmp";
break;
}
case 8: //该节点旁边有八个雷点,标记数值8
{
this.src = "img/small/8.bmp";
break;
}
case 0:
{
//空节点,需要遍历相邻的所有空节点,目前采用递归方法
this.src = "img/small/kong.bmp";
//定义当前空节点的坐标未知,以便定时器捕获对该位置相连的所有节点进行递归处理,显示递归中发现的所有空节点
BombObjectList.fire_X = img.x;
BombObjectList.fire_Y = img.y;
break;
}
}
}
}
}
//鼠标提起时,清空鼠标操作状态。
BombImgObject.MouseType = 0;
}
//禁止图片对象的鼠标拖动事件
img.ImgObj.ondrag = function() {
return false;
}
//定义图片对象的鼠标移入事件
img.ImgObj.onmouseout = function() {
if (BombObjectList.fireFlag!==2 && !this.flag && BombObjectList.IsMouseDown && this.src.indexOf("kong") >= 0 && BombImgObject.MouseType != 2) {
this.src = "img/small/normal.bmp";
}
}
img.ImgObj.onmouseover = function() {
if (BombObjectList.fireFlag !== 2 && !this.flag && BombObjectList.IsMouseDown && this.src.indexOf("normal") >= 0 && BombImgObject.MouseType != 2) {
this.src = "img/small/kong.bmp";
}
}
}
//根据x、y坐标显示该图片对象的图像
img.ShowNumImg = function(tag) {
if (!img.ImgObj.flag) {
if (arguments.length === 0) {
if (parseInt(img.ImgObj.lang) == 0) {
//为空时
document.getElementById("img" + img.x + "-" + img.y).src = "img/small/kong.bmp";
}
else {
//数值时
document.getElementById("img" + img.x + "-" + img.y).src = "img/small/" + img.ImgObj.lang + ".bmp";
}
//标记该图像已经处理过,不再响应后续的所有操作。
img.ImgObj.flag = true;
}
else {
//双击时
if (tag === 1) {
//按下
document.getElementById("img" + img.x + "-" + img.y).src = "img/small/kong.bmp";
}
else {
//弹起
document.getElementById("img" + img.x + "-" + img.y).src = "img/small/normal.bmp";
}
}
}
} //返回节点的图像对象
return img;
}
//设置图片对象的数值
BombImgObject.prototype.SetImgNum = function(num) {
if (this !== null) {
this.ImgObj.lang = num;
}
}
由于游戏需要,从空间复杂度上考虑,需要定义两个成员函数,一个是图片节点的动态展开函数,标记为ShowNumImg;另一个是动态改变图片对象对应的数值的函数,标记为SetImgNum。
~~代码中灰色底纹部分是为了响应棋盘类监听事件所写的,在javascript中,类与类之间的相互作用没有VC++中的消息机制,这里在一个类中采用定时器监听(读)变量、另一个类中根据触发点设置变量的方法(写)的方法,技术有限,欢迎大家指导学习!!
三、游戏控制类
至此,游戏功能部分全部完成,不过就展现给玩家的界面来说,还比较单调,仅仅一个期盼而已,为了完善游戏的辅助功能,增添游戏的趣味性,还需要完成以下一系列工作:
1. 需要一个计时器,每秒钟刷新一次,统计当前游戏用时,然后反馈给玩家。
2. 需要一个计数器,显示当前游戏剩余雷点水,一旦用户标记出一个雷点,计数器减1,玩家误标记而计数器为零且游戏未结束时,需要出现负数提示。
3. 游戏可以重新开始,模仿windows下的扫雷,设置一个重新开始按钮,游戏重新开始需要清除当前过程的所有临时变量,以便为接下来新的游戏过程预留空间。
4. 剩余雷点数不多时,需要自动识别剩下的节点是否全是雷点,如果是,则游戏自动成功结束,以提高游戏趣味性。
鉴于上述分析,我们需要定义一个游戏控制类,标记为PlayBombGame,对游戏的整个流程和状态进行控制和监听,对客户机环境进行兼容性判断,为整个游戏检测提供一个正常的运行环境,类的定义如下:
//玩家操作接口类的定义
function PlayBombGame(TimerId, BombNumId, ContentId, TryAgainId, width, height, BombNum) {
//预留退路
if (ContentId === "" || BombNumId === "" || TryAgainId === "" || TimerId === "") return false;
if (!document.getElementById) return false;
if (!document.createDocumentFragment) return false;
if (!document.createElement) return false;
if (!document.getElementById(ContentId)) return false;
if (!document.getElementById(BombNumId)) return false;
if (!document.getElementById(TryAgainId)) return false;
if (!document.getElementById(TimerId)) return false; //保存当前对象,以防函数嵌套时指代不清
var PBG = this; PBG.GameInfo = new BombObjectList("ContentSection", width, height, BombNum); //游戏操作对象
PBG.TimerID = TimerId; //计时器元素id
PBG.BombNumId = BombNumId; //雷点计数器元素id
PBG.TryAgainId = TryAgainId; //重置按钮id
PBG.CurSecond = 0; //当前用户用时(s)
PBG.CurBombNum = BombNum; //当前剩余雷点个数
PBG.GameState = -1; //当前的游戏状态,-1为结束(未开始),1为进行中 var timer = null;
var ListenTimer = null;
//开始初始化游戏
PBG.play = function() {
if (PBG.GameInfo != null || PBG.GameInfo != undefined) {
PBG.GameInfo.Initial().Display();
}
}
//重新初始化游戏
PBG.playAgain = function() {
if (PBG.GameInfo != null || PBG.GameInfo != undefined) {
PBG.GameInfo.TryAgain();
BombObjectList.fireFlag = 0;
BombObjectList.MarkedNum = 0;
//关闭计时器
PBG.CurSecond = 0;
PBG.CurBombNum = BombNum;
PBG.GameState = -1;
//重新开始监测
clearInterval(ListenTimer);
clearInterval(timer);
timer = null;
ListenTimer = null;
PBG.TimerControl();
}
}
//游戏结束时的处理
PBG.GameOver = function(tag) {
//标记游戏状态结束
PBG.GameState = -1;
//结束时处理
if (arguments.length !== 0) {
//成功
PBG.GameInfo.GameOver(tag);
document.getElementById(PBG.TryAgainId).src = "img/face/over.bmp";
}
else {
//失败
PBG.GameInfo.GameOver();
document.getElementById(PBG.TryAgainId).src = "img/face/fail.bmp";
}
//关闭定时器
clearInterval(ListenTimer);
clearInterval(timer);
timer = null;
ListenTimer = null;
}
//监测游戏状态
PBG.TimerControl = function() {
if (ListenTimer === null || ListenTimer === undefined) {
ListenTimer = setInterval(function() {
if (BombObjectList.fireFlag === 2) {
PBG.GameOver();
}
else if (BombObjectList.fireFlag === 1) {
//开启计时器
if (timer == null) {
//标记游戏开始
PBG.GameState = 1;
timer = setInterval(function() {
PBG.CurSecond++;
document.getElementById(PBG.TimerID).innerHTML = GetCount(PBG.CurSecond);
if (PBG.CurSecond === 999) {
//最长时间999秒,超出即结束
PBG.GameOver();
}
}, 1000);
//开启对空节点的监听
PBG.GameInfo.ListenKong();
}
}
else {
//未开始状态下
if (PBG.GameState === -1) {
//如果在进行中点击了重新开始
document.getElementById(PBG.TimerID).innerHTML = GetCount(PBG.CurSecond);
clearInterval(timer);
timer = null;
}
}
//监听剩余雷点
if (BombObjectList.fireFlag !== 2) {
//监听玩家标记出的个数来展现当前剩余的雷的个数
PBG.CurBombNum = BombNum - BombObjectList.MarkedNum;
document.getElementById(PBG.BombNumId).innerHTML = GetCount(PBG.CurBombNum);
if ($("#" + ContentId + " > IMG").length > 0) {
//如果剩余雷点数为0,且棋盘上剩余未标记节点个数为0,则游戏结束,全部标记正确,游戏成功
if (PBG.CurBombNum === 0 && $("#" + ContentId + " > img[flag='false']").length === 0) {
PBG.GameOver(1);
BombObjectList.fireFlag = 2;
}
//剩余未标记的都是雷点,则游戏结束,程序自动标记所有的雷点,游戏成功
if (PBG.CurBombNum > 0 && $("#" + ContentId + " > img[flag='false']").not("lang='-1'").length === 0) {
PBG.GameOver(2);
BombObjectList.fireFlag = 2;
}
}
}
}, 50);
}
}
//启动检测
PBG.TimerControl();
//根据数值获取图片数值展现对象
function GetCount(num) {
var numArr = num.toString().split("");
for (var i = 0; i < numArr.length; i++) {
numArr[i] = (numArr[i] == "-") ? "line" : numArr[i];
}
if (numArr.length === 1) {
return "<img src=\"img/num/0.bmp\" alt=\"bomb\" /><img src=\"img/num/0.bmp\" alt=\"bomb\" /><img src=\"img/num/" + numArr[0] + ".bmp\" alt=\"bomb\" />";
}
else if (numArr.length === 2) {
return "<img src=\"img/num/0.bmp\" alt=\"bomb\" /><img src=\"img/num/" + numArr[0] + ".bmp\" alt=\"bomb\" /><img src=\"img/num/" + numArr[1] + ".bmp\" alt=\"bomb\" />";
}
else {
return "<img src=\"img/num/" + numArr[0] + ".bmp\" alt=\"bomb\" /><img src=\"img/num/" + numArr[1] + ".bmp\" alt=\"bomb\" /><img src=\"img/num/" + numArr[2] + ".bmp\" alt=\"bomb\" />";
}
}
//对文档的全局事件进行定义
AddEvent(document, "mousedown", function(e) {
BombObjectList.IsMouseDown = true;
//冒泡捕获图片对象的按下事件
var event = window.event || e;
var targetE = (event.srcElement) ? event.srcElement : event.target;
if (BombObjectList.fireFlag !== 2 && targetE.getAttribute("flag") !== null && BombImgObject.MouseType===1) {
document.getElementById(PBG.TryAgainId).src = "img/face/down.bmp";
}
});
AddEvent(document, "mouseup", function(e) {
BombObjectList.IsMouseDown = false;
//冒泡捕获图片对象的按下事件
var event = window.event || e;
var targetE = (event.srcElement) ? event.srcElement : event.target;
if (BombObjectList.fireFlag !== 2 && targetE.getAttribute("flag") != null) {
document.getElementById(PBG.TryAgainId).src = "img/face/up.bmp";
}
});
AddEvent(document, "contextmenu", function() { return false; });
AddEvent(document.getElementById(PBG.TryAgainId), "click", function() { PBG.playAgain(); });
AddEvent(document.getElementById(PBG.TryAgainId), "mousedown", function() { this.src = "img/face/0.bmp"; });
AddEvent(document.getElementById(PBG.TryAgainId), "mouseup", function() { this.src = "img/face/up.bmp"; }); function AddEvent(target, eventType, callback) {
if (target.addEventListener) {
target.addEventListener(eventType, callback, false);
}
else {
target.attachEvent("on" + eventType, function(event) { return callback.call(target, event); });
}
};
}
完成上面类的定义,整个游戏就完成了,展现给玩家的是篇章一所示的效果图,嗯,界面比较粗糙哈~~
题外:
经常来博客园看技术大牛的分享,不知不觉就3年过去了,就在月初,突然发现自己博客园的年龄都3年临三个月了,说来惭愧,自己的博客园却空空如野,什么都没有,作为一个程序猿,热爱编程的同时突然很强烈想着在这个职业上留下点什么,说做就做,于是就有了上述四个篇章,游戏虽小,但也要五脏俱全,玩和做真的不一样。
想是一回事,做是一回事,写出来又是一回事,个人觉得这三步的难度是递进关系的,哈哈,个人鄙见。此章节的完成,突然发现兴趣是最好的推动力,工作之余,做自己想做的事,也对之前一段时间以来所学习的内容进行一个小结,美事一桩,第一次写自己的博客,这只是个开端,接下来我将自己学习所得、所想、所做一一与大家分享,因为分享,所以快乐~~
~~Little Dream,在与大家互相交流中成长~~
web版扫雷小游戏(四)的更多相关文章
- web版扫雷小游戏(一)
作为一名程序猿,平时的爱好也不多,说起游戏,我不太喜欢大型的网游,因为太耗时间,偶尔玩玩经典的单机小游戏,比如windows下自带的游戏扫雷(秀一下,高级下最高纪录110s). 现阶段正在致力于web ...
- web版扫雷小游戏(二)
接上篇~~第一次写这种技术博客,发现把自己做的东西介绍出来还是一件脑力活,不是那么轻松啊,好吧,想到哪写到哪,流水记录之,待完成之后再根据大家的意见进行修改吧. 游戏实现 根据对扫雷游戏的体验和分析, ...
- web版扫雷小游戏(三)
~~~接上篇,上篇介绍了游戏实现过程中第一个比较繁琐的地方,现在展现在玩家面前的是一个有血有肉的棋盘,从某种意义上说玩家已经可以开始游戏了,但是不够人性化,玩家只能一个一个节点的点开,然后判断,然后标 ...
- jQuery实践-网页版2048小游戏
▓▓▓▓▓▓ 大致介绍 看了一个实现网页版2048小游戏的视频,觉得能做出自己以前喜欢玩的小游戏很有意思便自己动手试了试,真正的验证了这句话-不要以为你以为的就是你以为的,看视频时觉得看懂了,会写了, ...
- 扫雷小游戏PyQt5开发【附源代码】
也没啥可介绍哒,扫雷大家都玩过. 雷的分布算法也很简单,就是在雷地图(map:二维数组)中,随机放雷,然后这个雷的8个方位(上下左右.四个对角)的数字(非雷的标记.加一后不为雷的标记)都加一. 如何判 ...
- 用Kotlin破解Android版微信小游戏-跳一跳
前言 微信又更新了,从更新日志上来看,似乎只是一次不痛不痒的小更新.不过,很快就有人发现,原来微信这次搞了个大动作——在小程序里加入了小游戏.今天也是朋友圈被刷爆的缘故. 看到网上 有人弄了一个破解版 ...
- Angular4 扫雷小游戏
扫雷小游戏,可以升级过关,难度随关卡增加.但是有很明显的bug,以后有时间会继续优化! HTML: <div class="mainContent"> <div ...
- C++扫雷小游戏(基于CMD命令行)
这个小游戏是笔者在大一C语言课程设计的时候写的,基于命令行,为了显得漂亮一些,特别加上了彩色特效~~~ 注意:Win10系统须将命令行调为旧版命令行,否则有可能会显示乱码! 代码示例: #includ ...
- JavaScript版拼图小游戏
慕课网上准备开个新的jQuery教程,花了3天空闲时间写了一个Javascript版的拼图小游戏,作为新教程配套的分析案例 拼图游戏网上有不少的实现案例了,但是此源码是我自己的实现,所以不做太多的比较 ...
随机推荐
- [ZETCODE]wxWidgets教程一:介紹
本教程原文链接:http://zetcode.com/gui/wxwidgets/introduction/ 翻译:瓶哥 日期:2013年11月26日星期二 邮箱: 414236069@qq.com ...
- Yii常用技巧总结
//YII framework路径 Yii::getFrameworkPath(); //protected/runtime Yii::app()->getRuntimePath(); //pr ...
- 《神经网络和深度学习》系列文章三:sigmoid神经元
出处: Michael Nielsen的<Neural Network and Deep Leraning>,点击末尾“阅读原文”即可查看英文原文. 本节译者:哈工大SCIR硕士生 徐伟 ...
- PHP开发Apache服务器配置
照此配置流程,绝对一路畅通,可保无虞. 昨天弄了个PHP小程序,想在本地跑一下测试,可是工作电脑没有安装环境,于是下载了一个wamp,一路畅通,Apache.Mysql.PHP就 全有了.启动wamp ...
- Oracle DB 自动管理共享内存
• 启用Oracle Enterprise Manager (EM) 内存参数 • 设置自动优化的内存参数 • 使用手动优化的SGA 参数覆盖最小大小 • 使用SGA Advisor 设置SGA_TA ...
- macos 配置 golang 开发环境
初次接触golang这门编程语言,一下子就喜欢上了,语法简洁优雅,对于以前有c/c++编程经验的人来说会更加有亲切感. 仅仅学习了一天就能应用beego框架和mogodb数据库开发一个rest api ...
- GitHub与Versions
[第一步]建立先仓库 第一步的话看一般的提示就知道了,在github新建一个repository(谷歌可以解决),都是可视化的界面操作,所以难度不大.或者看这里:https://help.github ...
- Sending e-mail with Spring MVC---reference
reference from:http://www.codejava.net/frameworks/spring/sending-e-mail-with-spring-mvc Table of con ...
- 固定ip
192.168.1.111 255.255.255.0 192.168.1.1 8.8.8.8 202.96.134.33
- HDU2084JAVA
数塔 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submissi ...