From 0aa131b1ee6ab85acd5f5d623c6f45810b1f47b1 Mon Sep 17 00:00:00 2001 From: Suzu Tomo Date: Wed, 27 Dec 2023 21:57:55 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20Field=E3=82=AF=E3=83=A9=E3=82=B9?= =?UTF-8?q?=E3=81=AEtiles=E3=81=8C=E5=88=9D=E6=9C=9F=E5=8C=96=E6=99=82?= =?UTF-8?q?=E3=81=ABfill=E3=81=AB=E3=82=88=E3=81=A3=E3=81=A6=E5=90=8C?= =?UTF-8?q?=E4=B8=80=E3=82=A4=E3=83=B3=E3=82=B9=E3=82=BF=E3=83=B3=E3=82=B9?= =?UTF-8?q?=E3=81=A7=E7=94=9F=E6=88=90=E3=81=95=E3=82=8C=E3=81=A6=E3=81=84?= =?UTF-8?q?=E3=82=8B=E3=83=90=E3=82=B0=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Kakomimasu.ts | 43 +++++++++++---------- src/test/fillBase4_test.ts | 78 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 21 deletions(-) create mode 100644 src/test/fillBase4_test.ts diff --git a/src/Kakomimasu.ts b/src/Kakomimasu.ts index 49b48b8..9b1bcb9 100644 --- a/src/Kakomimasu.ts +++ b/src/Kakomimasu.ts @@ -242,10 +242,11 @@ class Field { this.nAgent = nAgent; this.nPlayer = nPlayer; this.points = points; - this.tiles = new Array(width * height).fill({ - type: Field.AREA, - player: null, - }); + this.tiles = new Array(width * height); + // fillで初期化すると参照が同じになってしまうので、一つずつ初期化 + for (let i = 0; i < width * height; i++) { + this.tiles[i] = { type: Field.AREA, player: null }; + } } static fromJSON(data: FieldJson) { @@ -297,46 +298,46 @@ class Field { const mask = new Array(field.length); for (let i = 0; i < mask.length; i++) mask[i] = 1; + // reduceはmaskの中身が全部0になるまで続けている while (mask.reduce((s, c) => s + c)) { const area = new Array(field.length); for (let pid = 0; pid < this.nPlayer; pid++) { for (let i = 0; i < field.length; i++) { - area[i] |= 1 << pid; + area[i] |= 1 << pid; // とりあえず全部自分の領地としてマーク? } // 外側の囲まれていないところを判定 + // 0,0(上で余白のマスをつけているため必ず中立マス)から探索を初め壁にぶつかるまで探索することで囲まれていない部分を判定している const chk = (x: number, y: number) => { const n = x + y * (w + 2); - if (x < 0 || x >= w + 2 || y < 0 || y >= h + 2) return; - else if ((area[n] & (1 << pid)) === 0) return; + if (x < 0 || x >= w + 2 || y < 0 || y >= h + 2) return; // ボードの外を判定しようとしていたらreturn + else if ((area[n] & (1 << pid)) === 0) return; // すでに囲まれていないと判定されたところはスキップ else if ( mask[n] !== 0 && field[n].type === Field.WALL && field[n].player === pid ) { return; } else { - area[n] &= ~(1 << pid); - chk(x - 1, y); - chk(x + 1, y); - chk(x - 1, y - 1); - chk(x, y - 1); - chk(x + 1, y - 1); - chk(x - 1, y + 1); - chk(x, y + 1); - chk(x + 1, y + 1); + area[n] &= ~(1 << pid); // 探索しているマスを「囲まれていない」と判定(ビットを下げる) + chk(x - 1, y); // 左のマスを探索 + chk(x + 1, y); // 右のマスを探索 + chk(x - 1, y - 1); // 左上のマスを探索 + chk(x, y - 1); // 上のマスを探索 + chk(x + 1, y - 1); // 右上のマスを探索 + chk(x - 1, y + 1); // 左下のマスを探索 + chk(x, y + 1); // 下のマスを探索 + chk(x + 1, y + 1); // 右下のマスを探索 } }; chk(0, 0); //console.log(mask, narea, pid); } - //console.log(area); - //console.log("mamamama"); //console.log(mask, area, "mask"); for (let i = 0; i < field.length; i++) { if (area[i] === 0) { - mask[i] = 0; - } else if ((area[i] & (area[i] - 1)) === 0) { // 2のべき乗かを判定 + mask[i] = 0; // どのプレイヤーの領地でもないと判定されたところはスキップするようにmaskを0に設定 + } else if ((area[i] & (area[i] - 1)) === 0) { // 2のべき乗かを判定(Trueならそのプレイヤーの領地として確定) field[i].player = Math.log2(area[i]); mask[i] = 0; } @@ -348,7 +349,7 @@ class Field { const n = i + j * w; const nexp = (i + 1) + (j + 1) * (w + 2); if (this.tiles[n].type !== Field.WALL) { - this.tiles[n].player = field[nexp].player; + this.tiles[n] = field[nexp]; } } } diff --git a/src/test/fillBase4_test.ts b/src/test/fillBase4_test.ts new file mode 100644 index 0000000..697302e --- /dev/null +++ b/src/test/fillBase4_test.ts @@ -0,0 +1,78 @@ +import { Board, Field } from "../Kakomimasu.ts"; +import { AssertionError } from "./deps.ts"; + +const cl = (...a: Parameters) => { + console.log(...a); //a; +}; //console.log(...a); + +Deno.test("fill1", () => { + const nAgent = 6; + const [width, height] = [3, 4]; + const board: Board = { + width, + height, + points: new Array(width * height), + nAgent, + }; + const field = new Field(board); + + const p = () => { + for (let i = 0; i < height; i++) { + const s = []; + for (let j = 0; j < width; j++) { + const n = field.tiles[j + i * width]; + s.push( + "_W".charAt(n.type) + (n.player === null ? "." : n.player).toString(), + ); + } + cl(s.join(" ")); + } + cl(); + }; + const set = (s: string) => { + s = s.replace(/\n/g, ""); + for (let i = 0; i < s.length; i++) { + const c = s.charAt(i); + if (c === "0") { + field.tiles[i] = { type: Field.WALL, player: 0 }; + } else if (c === "1") { + field.tiles[i] = { type: Field.WALL, player: 1 }; + } + } + }; + const chk = (s: string) => { + s = s.replace(/\n/g, ""); + for (let i = 0; i < s.length; i++) { + const c = s.charAt(i); + if (c !== ".") { + const n = parseInt(c); + const f = field.tiles[i]; + if (f.type !== Field.AREA || f.player !== n) { + throw new AssertionError(""); + } + } + } + }; + + p(); + + set(` +000 +0.0 +000 +... +`); + + p(); + + field.fillArea(); + + p(); + + chk(` +... +.0. +... +... +`); +});