您的位置:首页 > Web前端 > JavaScript

【JS小游戏】游戏编程初体验之扫雷

2017-02-17 17:11 651 查看

前言

昨天接触到一个叫做net的游戏,类似接点灯的那种类型,在一个方阵中随机分配了一些点,然后给了一些管道让玩家将其连通才算过关,完了几把就上瘾了。但是这个游戏是PC端的单机游戏,不方便我在其他地方随时可以玩,于是想自己写一个类似的游戏出来,但是发现自己水平有限,一时没有想出该组合实现管道分布的算法,就只能留着后面慢慢想了,我就退而求其次的写了一个扫雷游戏,也算是进入了游戏这个行业了吧(自我安慰而已啦)。扫雷的游戏相对net来少了那个管道的分布算法,是随机的将雷分不到方阵中,然后由用户一步一步的确定雷的位置。算法相对来说较为简单,具体算法我就不想多做赘述了,在文中末尾记录该小游戏的完整js代码,请各位看官雅正。

界面截图



测试demo页面

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title></title>
</head>
<body>
<div>
<label><span>x:</span><input id="x"/></label>
<label><span>y:</span><input id="y"/></label>
<label><span>mine:</span><input id="mine"/></label>
<input type="submit" id="submit"/>
<div id="game_container">
</div>
</div>
</body>
<script type="text/javascript" src="js/jquery-1.11.0.js"></script>
<script type="text/javascript" src="js/sweeper.js"></script>
<script>
$("#submit").click(function () {
sweeper.init({
x: $("#x").val(),
y: $("#y").val(),
mine: $("#mine").val(),
container: $("#game_container"),
start: function (data) {
},
pass: function (data) {
},
over: function (data) {
}
})
})
</script>
</html>


核心的js代码 sweeper.js

(function (w, $) {
var sweeper = {
data: {
globalData: {
isStarted: false,
real: 0,
rest: 0
}
},
/**
* 初始化游戏
* @param {Object} params初始化参数对象
*/
init: function (params) {
//初始化参数
var globalData = sweeper.data.globalData
globalData.x = params && params.x ? params.x : 10
globalData.y = params && params.y ? params.y : 10
globalData.mine = params && params.mine ? params.mine : 30
globalData.container = params && params.container ? params.container : $("#game_container")
globalData.start = params && params.start ? params.start : function (data) {
}
globalData.pass = params && params.pass ? params.pass : function (data) {
alert("you are winner")
}
globalData.over = params && params.over ? params.over : function (data) {
alert("game over")
}
globalData.matrix = new Array()

//初始化游戏容器
globalData.container.html("")
globalData.container.css("line-height", "0px")
$("head").append("<style>.grid {width: 1.2em;height: 1.2em;font-size: 1em;margin: 0px;padding: 0px;}</style>")

//计算雷区面积和地雷出现概率
var maxGrid = globalData.x * globalData.y
var mineP = globalData.mine / maxGrid

//构建雷区
for (var i = 0; i < globalData.y; i++) {
for (var j = 0; j < globalData.x; j++) {
//当前位置随机生成地雷
var isMine = Math.random() <= mineP ? true : false
//如果生成了地雷,将游戏全局变量的真实地雷数加1
if (isMine) {
globalData.real++
}

//构造位置对象,并保存当前位置是否有雷和排雷状态
var grid = {
x: j,
y: i,
isMine: isMine,
isSweeped: false
}
globalData.matrix.push(grid);

//向页面游戏容器加入位置格子,并未格子绑定排雷事件
globalData.container.append("<button class='grid' onclick='sweeper.sweep(" + j + "," + i + ")'> </button>")
}
globalData.container.append("<br />")
}

//保存页面格子,并初始化当前雷区格子剩余量
globalData.butMatrix = globalData.container.children("button")
globalData.rest = globalData.butMatrix.length

},
/**
* 排雷操作
* @param {Object} x 当前位置横向索引
* @param {Object} y 当前位置纵向索引
*/
sweep: function (x, y) {
var globalData = sweeper.data.globalData

/**
* 获取指定位置的详细信息
* @param {Object} x 位置横向索引
* @param {Object} y 位置纵向索引
*/
function getGrid(x, y) {
if (x < 0 || x >= globalData.x) {
return
} else if (y < 0 || y >= globalData.y) {
return
} else {
return globalData.matrix[globalData.y * y + x]
}
}

/**
* 获取指定位置的格子对象
* @param {Object} x 位置横向索引
* @param {Object} y 位置纵向索引
*/
function getGridBut(x, y) {
if (x < 0 || x >= globalData.x) {
return
} else if (y < 0 || y >= globalData.y) {
return
} else {
return $(globalData.butMatrix[globalData.y * y + x])
}
}

/**
* 获取指定位置周边位置详情列表
* @param {Object} x 中心位置横向索引
* @param {Object} y 中心位置纵向索引
*/
function listSrd(x, y) {
var srdGrid = new Array();

function pushGrid(obj) {
if (obj) {
srdGrid.push(obj)
}
}

pushGrid(getGrid(x - 1, y - 1))
pushGrid(getGrid(x - 1, y))
pushGrid(getGrid(x - 1, y + 1))
pushGrid(getGrid(x + 1, y - 1))
pushGrid(getGrid(x + 1, y))
pushGrid(getGrid(x + 1, y + 1))
pushGrid(getGrid(x, y + 1))
pushGrid(getGrid(x, y - 1))
return srdGrid
}

/**
* 踩雷,游戏结束
*/
function dead() {
globalData.over('') //踩雷调用
for (var i = 0; i < globalData.matrix.length; i++) {
var grid = globalData.matrix[i]
if (!grid.isSweeped) {
var but = getGridBut(grid.x, grid.y)

if (grid.isMine) {
but.css("background-color", "black")
}

but.attr("disabled", "disabled")
}
}
}

/**
* 地雷完全排除,顺利通关
*/
function pass() {
globalData.pass('') //通关调用
for (var i = 0; i < globalData.matrix.length; i++) {
var grid = globalData.matrix[i]
if (!grid.isSweeped) {
var but = getGridBut(grid.x, grid.y)

if (grid.isMine) {
but.css("background-color", "red")
}
but.attr("disabled", "disabled")
}
}
}

/**
* 在未踩雷的情况下进行排雷操作
* @param {Object} grid 排雷位置
*/
function compute(grid) {
if (!grid.isSweeped) {
grid.isSweeped = true
globalData.rest--
if (globalData.rest == globalData.real) {
pass()
}
var srdGrid = listSrd(grid.x, grid.y)
var gridBut = globalData.butMatrix[globalData.y * grid.y + grid.x]
$(gridBut).css("background-color", "white")
$(gridBut).attr("disabled", "disabled")
var count = 0;
for (var i = 0; i < srdGrid.length; i++) {
if (srdGrid[i].isMine) {
count++
}
}
if (count == 0) {
for (var i = 0; i < srdGrid.length; i++) {
compute(srdGrid[i])
}
} else {
$(gridBut).html(count)
}
}
}

// 首次点击时算开始
if (!globalData.isStarted) {
globalData.start('') //开始调用
globalData.isStarted = true
}

//排雷
var grid = getGrid(x, y)
if (grid) {
if (grid.isMine) {
dead()
} else {
compute(grid)
}
}
}
}

w.sweeper = sweeper

})(window, $)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: