版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hzy199772/article/details/87864175
这是一个关于战舰的游戏:游戏中有三个战舰群,呈横向或竖向连续排列,当击毁3艘战舰后,战舰群沉没。
下面给出贴图和代码:
贴图:
battleship.js:
var view = {
dispalyMessage:function(msg){
var messageArea = document.getElementById("messageArea");
messageArea.innerHTML = msg;
},
displayHit:function(location){
var cell = document.getElementById(location);
cell.setAttribute("class","hit");
},
displayMiss:function(location){
var cell = document.getElementById(location);
cell.setAttribute("class","miss");
}
} ;
var model = {
boardSize:7,
numShips:3,
shipsSunk:0,
shipLength:3,
ships:[ { locations:["0","0","0"],hits:["","",""]},
{ locations:["0","0","0"],hits:["","",""]},
{ locations:["0","0","0"],hits:["","",""]} ],
fire:function(guess){
for (var i = 0; i < this.numShips; i++) {
var ship = this.ships[i];
var index = ship.locations.indexOf(guess);
if(index >= 0){
ship.hits[index] = "hit";
view.displayHit(guess);
view.dispalyMessage("HIT!");
if(this.isSunk(ship)){
view.dispalyMessage("You Sank My Battleship!");
this.shipsSunk++;
}
return true;
}
}
view.displayMiss(guess);
view.dispalyMessage("You Missed!");
return false;
},
isSunk:function(ship){
for(var i = 0;i < this.shipLength;i++){
if(ship.hits[i] !== "hit"){
return false;
}
}
return true;
},
generateShipLocation:function(){
var loactions;
for(var i = 0;i<this.numShips;i++){
do {
locations = this.generateShip();
} while (this.collision(locations));
this.ships[i].locations = locations;
}
},
generateShip:function(){
var direction = Math.floor(Math.random()*2);
var row,col;
/*水平放置*/
if(direction ===1){
row = Math.floor(Math.random()*this.boardSize);
col = Math.floor(Math.random()*(this.boardSize - this.shipLength));
}else{
row = Math.floor(Math.random()*(this.boardSize-this.shipLength));/*竖直放置*/
col = Math.floor(Math.random()*this.boardSize);
}
var newShipLocations = [];
for(var i = 0;i<this.shipLength;i++){
if(direction === 1){
newShipLocations.push(row + "" + (col + i));
}else{
newShipLocations.push((row+i)+""+col);
}
}
return newShipLocations;
},
collision:function(locations){
for(var i =0;i<this.numShips;i++){
var ship = model.ships[i];
for(var j = 0;j<locations.length;j++){
if(ship.locations.indexOf(locations[j]) >= 0){
return true;
}
}
}
return false;
}
};
var controller = {
guesses:0,
processGuess:function(guess){
var location = parseGuess(guess);
if(location){
this.guesses++;
var hit = model.fire(location);
if(hit && model.shipsSunk === model.numShips){
view.dispalyMessage("你击沉了我们所有的战舰,经过"+this.guesses+"次猜测");
}
}
}
};
function parseGuess(guess){
var alphabet = ["A","B","C","D","E","F","G"];
if(guess === null || guess.length !==2){
alert("请输出符合规定的输入");
}else{
firstChar = guess.charAt(0);
var row = alphabet.indexOf(firstChar);
var column = guess.charAt(1);
if(isNaN(row) || isNaN(column)){
alert("请输入范围内的数字");
}else if(row<0 || row>=model.boardSize || column<0 || column>=model.boardSize){
alert("输入内容不再范围内");
}else{
return row + column;
}
}
return null;
}
function init(){
var fireButton = document.getElementById("fireButton");
fireButton.onclick = handleFireButton;
var guessInput = document.getElementById("guessInput");
guessInput.onkeypress = handleKeyPress;
model.generateShipLocation();
}
function handleFireButton(){
var guessInput = document.getElementById("guessInput");
var guess = guessInput.value;
controller.processGuess(guess);
guessInput.value = "";
}
function handleKeyPress(e){
var fireButton = document.getElementById("fireButton");
if(e.keyCode === 13){
fireButton.click();
return false;
}
}
window.onload = init;
battleship.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>战舰世界</title>
<style>
body{
background-color: black;
}
div#board{
position:relative;
width:1024px;
height:863px;
margin:auto;
background: url("board.jpg") no-repeat;/*不平铺*/
}
div#messageArea{
position:absolute;
top:0px;
left:0px;
color: rgb(83, 175, 19);
}
table{
position:absolute;
left: 173px;
top:98px;
border-spacing: 0px;
}
td{
width: 94px;
height: 94px;
}
form{
position: absolute;
bottom: 0px;
right: 0px;
padding: 15px;
background-color: rgb(83, 175, 19);
}
form input{
background-color: rgb(152, 207, 113);
border-color: rgb(83, 175, 19);
font-size: 1em;
}
.hit{
background: url("ship.png") no-repeat center center;
}
.miss{
background: url("miss.png") no-repeat center center;
}
</style>
</head>
<body>
<div id="board">
<div id="messageArea"></div>
<table>
<tr>
<td id="00"></td> <td id="01"></td> <td id="02"></td> <td id="03"></td>
<td id="04"></td> <td id="05"></td> <td id="06"></td>
</tr>
<tr>
<td id="10"></td> <td id="11"></td> <td id="12"></td> <td id="13"></td>
<td id="14"></td> <td id="15"></td> <td id="16"></td>
</tr>
<tr>
<td id="20"></td> <td id="21"></td> <td id="22"></td> <td id="23"></td>
<td id="24"></td> <td id="25"></td> <td id="26"></td>
</tr>
<tr>
<td id="30"></td> <td id="31"></td> <td id="32"></td> <td id="33"></td>
<td id="34"></td> <td id="35"></td> <td id="36"></td>
</tr>
<tr>
<td id="40"></td> <td id="41"></td> <td id="42"></td> <td id="43"></td>
<td id="44"></td> <td id="45"></td> <td id="46"></td>
</tr>
<tr>
<td id="50"></td> <td id="51"></td> <td id="52"></td> <td id="53"></td>
<td id="54"></td> <td id="55"></td> <td id="56"></td>
</tr>
<tr>
<td id="60"></td> <td id="61"></td> <td id="62"></td> <td id="63"></td>
<td id="64"></td> <td id="65"></td> <td id="66"></td>
</tr>
</table>
<form>
<input type="text" id="guessInput" placeholder="A0">
<input type="button" id="fireButton" value="Fire!">
</form>
</div>
<script src="battleship.js"></script>
</body>
</html>
下面开始解释具体的js代码:
首先我们采用MVC模型,model、view、controller各司其职,所以分别建立了这三个对象,有其各自的属性和方法
view对象:
我们首先来看看负责视图的view对象:
这个对象没什么好说的,就包含了三个视图的更新任务:
显示未击中战舰的MISS
显示击沉的战舰图标
显示提示信息
model对象:
属性:
方法:
fire:
首先需要一个读入的玩家猜测guess,然后通过for循环将战舰从战舰数组中分别读出来,然后使用indexof方法判断猜测是否在ship的locations数组中,如果存在就将对应hit数组位置进行标记,并通知view更新视图,不存在则更新miss视图;同时还需判断战舰群是否已经被击沉,若击沉,将shipsSunk++。
isSunk:
传入一个ship战舰参数,遍历所有hit标记,全部沉没,战舰群才沉没。
generateShipLocation:
这是一个产生战舰的总方法:调用generateShip和collision方法
generateShip:
首先产生一个方向随机数:0表示竖直,1表示水平
这里要注意放置时,不能超出游戏板,所以对起始位置做了限定。
然后将产生的随机位置放入临时数组中return。
collision:
这是一个判断战舰重合的方法,通过遍历检查该位置是否在已有战舰的locations数组中判断是否碰撞。
controller对象:
这是一个控制器,主要是对模型model进行处理:
processGuess:
主要进行获取用户猜测并通知model进行fire的操作
parseGuess:
进行将用户输入转换为位置坐标的操作。
最后要注意的是:window.onload = init;
表示在网页加载完成后回调init方法。
而init方法则是对获取用户输入和战舰初始化的操作。