解説動画
解答コード
// 反対方向の連想配列は、17-8と同じものを使います
// let dic_opposite: { [key: number]: number } = {
// [RIGHT]: LEFT, // 右の反対:左
// [LEFT]: RIGHT, // 左の反対:右
// [UP]: DOWN, // 上の反対:下
// [DOWN]: UP, // 下の反対:上
// [FORWARD]: BACK, // 前の反対:後ろ
// [BACK]: FORWARD // 後ろの反対:前
// };
// エージェントの状態を保持する連想配列
let dic_agentStatus179: { [key: string]: number } = {
"col": 0, // エージェントの現在の列位置
"row": 0, // エージェントの現在の行位置
"item": 0, // エージェントが修理に使うアイテムのID
"moveDirection": RIGHT, // エージェントの移動方向
"fixDirection": FORWARD // エージェントが修復する方向
};
// 壁エリアの状態を保持する連想配列
let dic_wallAreaStatus179: { [key: string]: number } = {
"item": 935, // 壁の材料
"maxCol": 8, // 列の最大値
"maxRow": 4, // 行の最大値
"fixDirection": FORWARD, // 修復する方向
"positiveColDirection": RIGHT, // 列の順方向
"positiveRowDirection": UP // 行の順方向
};
// 床エリアの状態を保持する連想配列
let dic_floorAreaStatus179: { [key: string]: number } = {
"item": 5, // 床の材料
"maxCol": 8, // 列の最大値
"maxRow": 9, // 行の最大値
"fixDirection": DOWN, // 修復する方向
"positiveColDirection": RIGHT, // 列の順方向
"positiveRowDirection": BACK // 行の順方向
};
// エージェントをエリア内で移動させる関数
function move179(agentStatus: { [key: string]: number }, areaStatus: { [key: string]: number }) {
// エージェントの現在の位置と移動方向を取得します
let row = agentStatus["row"]; // エージェントの現在の行位置
let col = agentStatus["col"]; // エージェントの現在の列位置
let moveDirection = agentStatus["moveDirection"]; // エージェントの移動方向
// 列の順方向を取得します
let positiveColDirection = areaStatus["positiveColDirection"];
// 列の逆方向を取得します
let negativeColDirection = dic_opposite[positiveColDirection];
// 方向転換が必要かどうかを判定します
let shouldTurn = false;
// エージェントが列を順方向に進んでいて、エリアの列の最後にいる場合は、方向転換が必要です
if (moveDirection == positiveColDirection && col == areaStatus["maxCol"]) {
shouldTurn = true;
}
// エージェントが列を逆方向に進んでいて、エリアの列の最初にいる場合は、方向転換が必要です
if (moveDirection == negativeColDirection && col == 0) {
shouldTurn = true;
}
// 移動を続けるかどうかを判定します
let shouldContinue = true;
// エージェントがエリアの行の最後にいる場合
if (row == areaStatus["maxRow"]) {
// かつ、方向転換が必要の場合は、移動してもエリア外に出てしまうので、ここで移動を終了します
if (shouldTurn) {
shouldContinue = false;
}
}
// 移動終了の場合は、false を返して終了します
if (shouldContinue == false) {
return false;
}
// エージェントを移動します
if (shouldTurn) {
// 方向転換をする場合の移動方法:
// 行を移動します
agent.move(areaStatus["positiveRowDirection"], 1);
row += 1;
// エージェントが移動する向きを反対にします
moveDirection = dic_opposite[moveDirection];
} else {
// 方向転換をしない場合の移動方法:
// 列を移動します
agent.move(moveDirection, 1);
if (moveDirection == positiveColDirection) {
// 列の順方向へ移動する場合はエージェントの列位置に 1 を加えます
col += 1;
} else {
// 列の逆方向へ移動する場合はエージェントの列位置から 1 を除きます
col -= 1;
}
}
// エージェントの状態を更新します
agentStatus["row"] = row;
agentStatus["col"] = col;
agentStatus["moveDirection"] = moveDirection;
// 移動したので、true を返して終了します
return true;
}
// エージェント状態の初期化を行う関数
function initialize179(agentStatus: { [key: string]: number }, areaStatus: { [key: string]: number }) {
agentStatus["col"] = 0;
agentStatus["row"] = 0;
agentStatus["item"] = areaStatus["item"];
agentStatus["moveDirection"] = areaStatus["positiveColDirection"];
agentStatus["fixDirection"] = areaStatus["fixDirection"];
}
// エージェントをスタート地点に戻す関数
function returnToOrigin179(agentStatus: { [key: string]: number }, areaStatus: { [key: string]: number }) {
let backColDirection = dic_opposite[areaStatus["positiveColDirection"]];
let backRowDirection = dic_opposite[areaStatus["positiveRowDirection"]];
while (true) {
let shouldContinue = false;
if (agentStatus["col"] > 0) {
agent.move(backColDirection, 1);
agentStatus["col"] -= 1;
shouldContinue = true;
}
if (agentStatus["row"] > 0) {
agent.move(backRowDirection, 1);
agentStatus["row"] -= 1;
shouldContinue = true;
}
if (shouldContinue == false) {
break;
}
}
}
// エージェントが注目する方向のブロックを修復する関数
function fix179(agentStatus: { [key: string]: number }) {
// エージェントが注目する方向のブロックを調べて、穴が開いていなければ、何もしません
let blockId = agent.inspect(AgentInspection.Block, agentStatus["fixDirection"]);
if (blockId > 0) {
// 何もしないときは false を返します
return false;
}
// 穴が開いているときは、その方向にブロックを置きます
agent.setItem(agentStatus["item"], 1, 1);
agent.place(agentStatus["fixDirection"]);
// ブロックを置いたときは true を返します
return true;
}
// エージェントがエリア内を移動しながら修復を行う関数
function fixArea179(agentStatus: { [key: string]: number }, areaStatus: { [key: string]: number }) {
// 修復した箇所の数を数える変数
let fixedCount = 0;
// エリア内を移動しながら修復を行います
while (true) {
let fixed = fix179(agentStatus);
if (fixed) {
fixedCount += 1;
}
let shouldContinue = move179(agentStatus, areaStatus);
if (shouldContinue == false) {
break;
}
}
// 修復した箇所の数を返します
return fixedCount;
}
// チャットコマンド「17-9」で壁と床の修復を開始します
player.onChat("17-9", function () {
player.say("=== 壁と床の修復開始 ===");
let wallFixed = 0;
let floorFixed = 0;
// 壁を直します
initialize179(dic_agentStatus179, dic_wallAreaStatus179);
wallFixed = fixArea179(dic_agentStatus179, dic_wallAreaStatus179);
// スタート地点へ戻ります
returnToOrigin179(dic_agentStatus179, dic_wallAreaStatus179);
// 床を直します
initialize179(dic_agentStatus179, dic_floorAreaStatus179);
floorFixed = fixArea179(dic_agentStatus179, dic_floorAreaStatus179);
// 修復した箇所の数を表示します
player.say("壁の穴: " + wallFixed + "箇所");
player.say("床の穴: " + floorFixed + "箇所");
player.say("修復完了");
});