思路:
生成圖片矩陣
點擊格子
如果 第一次 且 新遊戲:
生成除該格子外的雷圖
統計數字
如果 該格子是雷:
爆炸
否則:
如果 格子數字是0:
深度搜索0區域,加入展示區域
如果格子已經打開:
忽略
如果格子標識旁邊有雷
把該格子加入展示區域
打開展示區域
代碼(typescript版本)
/**
* 地圖數字描述
* 0 空格子,可批量打開
* -1 雷區
* -2 被打開的格子
* >0 描述周圍雷區個數
*/
class SaoLei {
public map: any[] = [];
public showRec: any[] = [];
public initWidth: number = 10;//控制橫座標個數
public initHeight: number = 50;//控制縱座標個數
public boomNum: number = 50;//設置隨機雷數目
public dirx = [-1, 0, 1, -1, 1, -1, 0, 1]; //八方向x座標,用以統計旁邊有雷的個數
public diry = [-1, -1, -1, 0, 0, 1, 1, 1];//八方向y座標,用以統計旁邊有雷的個數
public shows: number[] = []; //展示區域集合
public deepOpen: number[] = []; //深搜節點集合
public deepDirX = [-1, 1, 0, 0]; //四方向x座標,用以深搜可批量打開區域
public deepDirY = [0, 0, -1, 1];//四方向y座標,用以深搜可批量打開區域
public bcreateBoom: boolean = false; //是否生成雷圖標識
public booms: number[] = [] //雷區座標
public constructor() {
}
/**
* 全部初始化爲0
* i ->y
* j ->x
*/
public init() {
// console.log("init");
for (let i = 0; i < this.initHeight; i++) {
this.map[i] = [];
for (let j = 0; j < this.initWidth; j++) {
this.map[i][j] = 0;
this.showRec[i][j] = 0;
}
}
// console.log("init finish");
}
/**
* 除(X,Y)不可是雷,避免一點開就爆炸
*/
private createBoom(x, y) {
/**
* 把座標轉化成id,公式是x+y*this.initWidth
*/
this.booms = [];
let limit = x * this.initWidth + y;
this.booms = this.getRandom(0, this.initWidth * this.initHeight, limit, this.boomNum);
// console.log("target", target);
for (let t of this.booms) {
//id逆向爲對應的座標
let tx = Math.floor(t / this.initWidth);
let ty = Math.floor(t % this.initWidth);
this.map[tx][ty] = -1;
}
this.bcreateBoom = true;
this.calcMapnum();
this.clickMap(x, y);
}
/**
* 點擊地圖響應
*/
public clickMap(x, y) {
// console.log("click");
if (!this.bcreateBoom) {//如果還沒有創建雷圖
this.createBoom(x, y);//創建雷圖
return;
}
if (this.showRec[x][y] == 1) {//已經被打開了
return;
}
this.shows = [];
if (this.map[x][y] == -1) {
//遊戲結束響應
} else if (this.map[x][y] > 0) {
this.shows.push(x + y * this.initWidth);
} else if (this.map[x][y] == 0) {
this.deepOpen.push(x + y * this.initWidth);
this.getShows();
}
for (let show of this.shows) {
let sx = Math.floor(show / this.initWidth);
let sy = Math.floor(show % this.initWidth);
this.showRec[sx][sy] = 1;
}
console.log(this.map);
}
/**
* 深搜可以批量打開的格子
*/
private getShows() {
while (this.deepOpen.length) {
let open = this.deepOpen.shift();
this.shows.push(open);
let ox = Math.floor(open / this.initWidth);
let oy = Math.floor(open % this.initWidth);
for (let k = 0; k < this.deepDirX.length; k++) {
let nearX = ox + this.deepDirX[k];
let nearY = oy + this.deepDirY[k];
if (!this.bOutOfBoundary(nearX, nearY)) {//是否超出邊界
let target = nearX + nearY * this.initWidth;
if (this.map[nearX][nearY] == 0) { //爲0的時候才考慮要不要加入
if (this.showRec[nearX][nearY] == 0) {//沒有打開的,實際上深度情況下可以不考慮這部分
if (this.shows.indexOf(target) == -1) {//沒有遍歷過
if (this.deepOpen.indexOf(target) == -1) {//沒有在隊列中
this.deepOpen.push(target);
}
}
}
}
}
}
}
}
/**
* 根據創建好的雷圖,計算每個格子的數值
*/
public calcMapnum() {
for (let boom of this.booms) {
let bx = Math.floor(boom / this.initWidth);
let by = Math.floor(boom % this.initWidth);
if (this.map[bx][by] == -1) {//-1代表雷
//如果有雷,則旁邊8個非雷的格子個數都加1
for (let k = 0; k < this.dirx.length; k++) {
let nearX = bx + this.dirx[k];
let nearY = by + this.diry[k];
if (!this.bOutOfBoundary(nearX, nearY)) {//是否超出邊界
if (this.map[nearX][nearY] != -1) {
this.map[nearX][nearY]++;
}
}
}
}
}
}
/**
* 是否超出邊界
*/
private bOutOfBoundary(x, y) {
if (x >= 0 && x < this.initHeight && y >= 0 && y < this.initWidth) {
return false;
}
return true;
}
/**
* 獲取隨機數值
*/
private getRandom(start, end, limit, num) {
//獲取隨機數源
let data = [];
for (let i = start; i < end; i++) {
if (i != limit && num > 0) {
data.push(i);
}
}
let DataLen = data.length
let target = [];
for (let i = 0; i < num; i++) {
let randomInd = Math.floor(Math.random() * DataLen);
let temp = data[randomInd];
data[randomInd] = data[DataLen - 1];
target.push(temp);
DataLen--;
}
return target;
}
}
說明1:只是寫了遊戲邏輯代碼,沒有寫界面,具體的可以根據map的狀態去實現界面邏輯,爲什麼要這樣?懶~
說明2:重申沒有做標識方面的工作,如果要實現,實際上就維護另一個標識矩陣,然後再click裏面判定這個格子的狀態,再實現對應的邏輯就好,爲什麼不順便寫了?懶~
說明3:代碼未必正確,review代碼的時候發現有不合邏輯的時候,會更新一遍,如果發現說這玩意怎麼寫得這麼渣渣,有各種問題的時候,別急,別慌,看下是不是最新的代碼,是的話。。。那也莫得法子~建議下方留言通知改正,感謝大佬!
說明4:僅做了簡單測試,實際發現有什麼bug的話,可探討解決,不負責維護~(卒)