掃雷遊戲javascript html
<html>
<head>
<meta charset="utf-8" />
<title>地雷遊戲</title>
<style>
.guoshengcontentdiv{
width:1255px;
height:600px;
margin:auto;
}
.guoshengonediv {
position: relative;
width: 1000px;
height: 600px;
float: left;
}
.canvasguosheng {
width: 1000px;
height: 600px;
position: absolute;
left: 0px;
top: 0px;
border: 1px #aaa solid;
}
.guoshengtwodiv {
float: left;
width: 250px;
height: 600px;
border: 1px #aaa solid;
}
</style>
</head>
<body>
<div class="guoshengcontentdiv">
<div class="guoshengonediv">
<canvas id="guoshengcanvas" width="1000" height="600" style="position:absolute;left:0px;top:0px;border:1px #aaa solid"></canvas>
</div>
<div class="guoshengtwodiv">
<h2 align="center">掃雷-郭勝</h2>
<hr />
<table width="100%">
<tr align="center">
<td>10*10 (bombers*20)</td>
<td>
<input type="button" id="mod1" value="選擇" οnclick="init(10,10,20);" />
</td>
</tr>
<tr align="center">
<td>20*10 (bombers*60)</td>
<td>
<input type="button" id="mod2" value="選擇" οnclick="init(15,20,60);" />
</td>
</tr>
<tr align="center">
<td>30*20 (bombers*100)</td>
<td>
<input type="button" id="mod3" value="選擇" οnclick="init(20,30,100);" />
</td>
</tr>
</table>
<hr />
<!--
作者:offline
時間:2018-01-11
描述:自定義模塊 郭勝
-->
<fieldset>
<legend>自定義</legend>
列數:<input type="text" id="cols" value="20"><br />
行數:<input type="text" id="rows" value="10"/><br />
炸彈數:<input type="text" id="bomber" value="50" /><br />
<input type="button" value="確定" id="custom" />
</fieldset>
<hr />
<table>
<tr>
<td>時間:</td>
<td><input type="text" id="time" value="0" readonly="true" style="border:none"/></td>
</tr>
<tr>
<td>雷數:</td>
<td><input type="text" id="bombernum" value="0" readonly="true" style="border:none"/></td>
</tr>
</table>
<hr />
<div >
<p>有問題的人歡迎聯繫我</p>
<p>艾尚編程工作室(郭經理):18795465900</p>
</div>
</div>
</div>
</body>
</html>
<script type="text/javascript">
/*
* 加載完頁面後執行
* 郭勝
*/
window.onload = function(){
init(15,20,40);
}
var $id = function(idname){return document.getElementById(idname);}
var s;
var yougess;
var bombnum;
/*
* 顯示時間
* 郭勝
*/
function showtime(){
$id("time").value = Number($id("time").value)+1;
}
/*
* 數據驗證
* 郭勝
*/
$id("cols").onblur = function(){
if(!isNaN($id("cols").value)){//是否是數字
if(Number($id("cols").value)>30 || Number($id("cols").value)<0){
alert("數字必須在0~30之間!記住!記住!記住!");
$id("cols").value = 20;
}
}else{
alert("是不是瞎?是不是瞎?是不是瞎?輸入數字!是數字!TMD是數字啊!!!");
$id("cols").value = 20;
}
}
/*
* 數據驗證
* 郭勝
*/
$id("rows").onblur = function(){
if(!isNaN($id("rows").value)){//是否是數字
if(Number($id("rows").value)>20 || Number($id("rows").value)<0){
alert("數字必須在0~30之間!記住!記住!記住!");
$id("rows").value = 10;
}
}else{
alert("是不是瞎?是不是瞎?是不是瞎?輸入數字!是數字!TMD是數字啊!!!");
$id("rows").value = 10;
}
}
/*
* 數據驗證
* 郭勝
*/
$id("bomber").onblur = function(){
if(!isNaN($id("bomber").value)){//是否是數字
if(Number($id("bomber").value)> Number($id("rows").value)*Number($id("cols").value)*0.85 || Number($id("bomber").value)<0){
alert("數字必須在0~"+Number($id("rows").value)*Number($id("cols").value)*0.85+"之間!記住!記住!記住!");
$id("bomber").value = 50;
}
}else{
alert("是不是瞎?是不是瞎?是不是瞎?輸入數字!是數字!TMD是數字啊!!!");
$id("bomber").value = 50;
}
}
/*
* 自定義初值
*/
$id("custom").onclick = function(){
init(Number($id("cols").value),Number($id("rows").value),Number($id("bomber").value));
}
var nowI = -1, nowJ = -1, preI = -1, preJ = -1;
/*
* 初始化
*/
function init(cols,rows,bomb){
bombnum = bomb;
clearInterval(s);//清除上次的時間
$id("time").value = 0;//時間更新爲0
s = setInterval(showtime(),1000);
$id("bombernum").value = bombnum;
var gamedata = new doubleArray(rows,cols);
var i = bombnum;
while(i>0){//初始化炸彈信息,炸彈值爲-1
//Math.ceil向上取整,Math.floor,捨棄取整,向下取整
var randnum = Math.ceil(Math.random()*rows*cols);
if(Math.floor(randnum/cols)==randnum/cols){//列的整數倍
var tmpx = Math.floor(randnum/cols) -1;//不能超過行數
}else{
var tmpx = Math.floor(randnum/cols);
}
var tempy = randnum - tmpx * cols -1;
if(gamedata[tmpx][tempy] != -1){
gamedata[tmpx][tempy] = -1;
i--;
}
}
//初始化除了炸彈之外的數據
for(var i = 0;i<rows;i++){
for(var j = 0;j<cols;j++){
if(gamedata[i][j] != -1){
/*
* 值爲0:上下左右都沒有炸彈
* 值爲1:左下、正左、左上、正下、正上、右上、正右、右下則肯定有且只有一個炸彈
* 值爲2:左下、正左、左上、正下、正上、右上、正右、右下則肯定有且只有兩個炸彈
* 值爲3:左下、正左、左上、正下、正上、右上、正右、右下則肯定有且只有三個炸彈
* 值爲4:左下、正左、左上、正下、正上、右上、正右、右下則肯定有且只有四個炸彈
* 值爲5:左下、正左、左上、正下、正上、右上、正右、右下則肯定有且只有五個炸彈
* 值爲6:左下、正左、左上、正下、正上、右上、正右、右下則肯定有且只有六個炸彈
* 值爲7:左下、正左、左上、正下、正上、右上、正右、右下則肯定有且只有七個炸彈
* 值爲8:左下、正左、左上、正下、正上、右上、正右、右下則肯定有且只有八個炸彈
* 郭勝
*/
gamedata[i][j] = (exist(gamedata,i-1,j-1) == 1?1:0) //左下
+ (exist(gamedata,i-1,j) == 1?1:0) //正左
+ (exist(gamedata,i-1,j+1) == 1?1:0) //左上
+(exist(gamedata,i,j-1) == 1?1:0) //正下
+ (exist(gamedata,i,j+1) == 1?1:0) //正上
+(exist(gamedata,i+1,j-1) == 1?1:0) //右上
+(exist(gamedata,i+1,j) == 1?1:0)//正右
+(exist(gamedata,i+1,j+1) == 1?1:0);//右下
}
}
}
var ctx = $id("guoshengcanvas").getContext("2d");
//返回之前保存過的路徑狀態和屬性
ctx.restore();
//在給定的矩形內清除指定的像素
ctx.clearRect(0,0,1000,600);
//保存當前環境的狀態
ctx.save();
//重新映射畫布上的 (0,0) 位置
ctx.translate(500 - 15*cols,300-15*rows);
//起始一條路徑,或重置當前路徑
ctx.beginPath();
//繪製“被填充”的矩形
ctx.fillRect(0,0,30*cols,30*rows);
gamestart(ctx,gamedata);//開始遊戲
}
/*
* 開始遊戲
* 郭勝
*/
function gamestart(ctx,gamedata){
var rows = gamedata.length;
var cols = gamedata[0].length;
var placestate = new doubleArray(rows,cols);//各個點的狀態,翻轉與否
for(var i=0;i<rows;i++){//初始化
for(var j = 0;j<cols;j++){
placestate[i][j] = "0";
}
}
//完全初始化
for(var i=0;i<rows;i++){
for(var j=0;j<cols;j++){
startprint(ctx,gamedata,i,j);
}
}
//移動模擬
$id("guoshengcanvas").onmousemove = function(e){
havor(ctx,gamedata,placestate,e.offsetX,e.offsetY);
}
//按鍵模擬
$id("guoshengcanvas").onmousedown = function(e){
if(e.button == 0){
show(ctx,gamedata,placestate,e.offsetX,e.offsetY);
}else{//標記炸彈
addmark(ctx,gamedata,placestate,e.offsetX,e.offsetY);
}
}
}
/*
* 點擊之後顯示的結果
* 將座標值轉化爲確定的值
* 郭勝
*/
function show(ctx,gamedata,placestate,x,y){
var rows = gamedata.length;
var cols = gamedata[0].length;
if(x>500-15*cols && y>300-15*rows && x<500+15*cols && y<300+15*rows){
findspace(ctx,gamedata,placestate, Math.floor((y-(300 -15*rows))/30), Math.floor((x-(500-15*cols))/30) );
}
}
/*
* 尋找可以一起翻開的空格
* 郭勝
*/
function findspace(ctx ,gamedata,placestate,x,y){
//x,y是指整數位置
var rows = gamedata.length;
var cols = gamedata[0].length;
var X = y*30;
var Y = x*30;
//XY是標準的座標偏移量
ctx.fillStyle = "rgb(189,199,224)";
ctx.fillRect(X,Y,29,29);
placestate[x][y] = "1";//先翻開再說
var tmp = gamedata[x][y];
switch(tmp){
case 1: ctx.fillStyle = "rgb(60,80,182)"; break;
case 2: ctx.fillStyle = "rgb(35,100,6)"; break;
case 3: ctx.fillStyle = "rgb(174,4,9)"; break;
case 4: ctx.fillStyle = "rgb(8,8,130)"; break;
case 5: ctx.fillStyle = "rgb(95,12,18)"; break;
case 6: ctx.fillStyle = "rgb(255,128,0)"; break;
case 7: ctx.fillStyle = "rgb(152,33,254)"; break;
case 8: ctx.fillStyle = "rgb(51,84,62)"; break;
}
if(tmp == -1){//是炸彈
for(var i = 0;i<rows;i++){
for(var j = 0;j<cols;j++){
addbomber(ctx,gamedata,i,j);
}
}
clearInterval(s);
if(confirm("沒有一點熊用,這麼簡單的遊戲還輸了!!!") == true){
init(15,20,40);
return false;
}else{
return false;
}
}else{//不是炸彈,則畫出數字
ctx.font = "28px Adobe Gothic Std B";
ctx.fillText(tmp,X+7,Y+23);
}
//雙重循環,循環本次位置的左上,左下,右上,右下
for(var i = -1;i<= 1;i++){
for(var j= -1;j<=1;j++){
if(i != 0 || j != 0){
if(exist(gamedata,x+i,y+j) != "notexist"){//位置存在
if(exist(gamedata,x,y) != 0){//位置存在,且值不是12345678,保證不把炸彈翻出來,當前位置
if(placestate[x+i][y+j] == "0"){//未翻開,遞歸繼續
findspace(ctx,gamedata,placestate,x+i,y+j)
}
}else{//下一個位置未翻看並且下一個位置的值爲0,代表着該位置的周圍八個位置都沒有炸彈,下個位置
if(placestate[x+i][y+j] == "0" && exist(gamedata,x+i,y+j) == "none"){
findspace(ctx,gamedata,placestate,x+i,y+j)
}
}
}
}
}
}
return false;
}
/*
* 繪製炸彈
* 郭勝
*/
function addbomber(ctx,gamedata,i,j){
var rows = gamedata.length;
var cols = gamedata[0].length;
ctx.fillStyle = "red";
ctx.save();
ctx.translate(j*30,i*30);//重新定位座標
if(gamedata[i][j] == -1){
ctx.save();
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.shadowBlur = 2;
ctx.shadowColor = "rgba(0,0,0,0.5)";
ctx.translate(15,15);//重新定位圓點座標
ctx.beginPath();
ctx.arc(0,0,10,0,Math.PI*2,false);
ctx.fill();
ctx.restore();
}
ctx.restore();
}
/*
* 添加標記
* 郭勝
*/
function addmark(ctx,gamedata,placestate,x,y){
var rows = gamedata.length;
var cols = gamedata[0].length;
var i = Math.floor((y-(300-15*rows))/30);//畫布中方塊的位置
var j = Math.floor((x-(500-15*cols))/30);//畫布中方塊的位置
ctx.fillStyle = "green";
ctx.save();
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.shadowBlur = 2;
ctx.shadowColor = "rgba(0,0,0,0.5)";
ctx.translate(j*30,i*30);
if(placestate[i][j] == "0"){//未翻轉
ctx.translate(15,15);
ctx.beginPath();
ctx.arc(0,0,10,0,Math.PI*2,false);
ctx.fill();
}
ctx.restore();
placestate[i][j] = "1";
if(gamedata[i][j] == -1){
bombnum --;
}
if(bombnum == 0){
clearInterval(s);
if(confirm("臭小子,你用了"+$id("time").value+"秒贏了遊戲,不要驕傲!要不要再來一次,鞏固一下基礎?") == true){
init(15,20,40);
}
}
}
/*
* 懸浮之後樣式的變化
* 郭勝
* x,y是相對瀏覽器中的座標
* 要計算出畫布中的座標
* 畫布相對於瀏覽器的起始座標是(500-15*cols),300 - 15*rows,但是對於畫布則是(0,0)
*
*/
function havor(ctx,gamedata,placestate,x,y){
var rows = gamedata.length;
var cols = gamedata[0].length;
if(x>500 - 15*cols && y>300-15*rows &&x<500+15*cols && y<300+15*rows){//判斷鼠標點擊所在的左邊是否在遊戲主界面內
ctx.fillStyle = "rgb(255,128,0)";
//計算出鼠標所在的畫布中的方塊的起始座標
nowJ = Math.floor((y-(300-15*rows))/30)*30;//新位置的絕對座標
nowI = Math.floor((x-(500 - 15*cols))/30)*30;//新位置的絕對座標
if(nowI != preI || nowJ != preJ){
if(placestate[Math.round(nowJ/30)][Math.round(nowI/30)] == "0"){//判斷該位置是否已翻開,0爲未翻開
ctx.fillRect(nowI,nowJ,29,29);
}
//將原來的沒翻開的方塊還原
if(preI != -1 && placestate[Math.round(preJ/30)][Math.round(preI/30)] == "0"){
//設置顏色漸變
var radgrad = ctx.createRadialGradient(30,30,1,45,45,(rows>cols?rows:cols)*30);
radgrad.addColorStop(0,'#C4E1FF');
radgrad.addColorStop(0.9,'rgb(36,66,147)');
ctx.fillStyle = radgrad;
ctx.fillRect(preI,preJ,29,29);
}
preI = nowI;//老位置的絕對座標
preJ = nowJ;//老位置的絕對座標
}
}
}
/*
* 圖形上特定位置初始化
* 郭勝
*/
function startprint(ctx,gamedata,x,y){
var rows = gamedata.length;
var cols = gamedata[0].length;
//創建放射狀/環形的漸變(用在畫布內容上)createRadialGradient()
var radgrad = ctx.createRadialGradient(30,30,1,45,45,(rows>cols?rows:cols)*30);
radgrad.addColorStop(0,'#C4E1FF');
radgrad.addColorStop(0.9,'rgb(36,66,147)');
//設置或返回用於填充繪畫的顏色、漸變或模式
ctx.fillStyle = radgrad;
ctx.fillRect(30*y,30*x,29,29);
}
/*
* 檢測位置是否存在,並判斷有沒有雷
* 郭勝
*/
function exist(gamedata,x,y){
var rows = gamedata.length;
var cols = gamedata[0].length;
if(x>= 0 && y>=0 && x<rows && y<cols){
if(gamedata[x][y] == -1){//存在,並且是炸彈,返回1
return Number(1);
}else if(gamedata[x][y] == 0){//存在,值爲0,安全值,留給遞歸查詢出來
return "none";
}else{//存在,其它情況即:12345678
return Number(0);
}
}else{
return "notexist";
}
}
/*
* 創建二維數組
* 郭勝
*/
function doubleArray(m,n){
var arr = new Array(m);//先創建一個一維數組arr
for(var i= 0;i<m;i++){
var arrtmp = new Array(n);
arr[i] = arrtmp;//爲arr每個元素再創建一個數組arrtmp
}
return arr;//返回二維數組
}
</script>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.