プログラミングの学習を、Webゲーム感覚で気軽に始められるサービス【CodeCombat】の攻略記事です。(無課金でも楽しめるステージのみを紹介しています…)
今回は、サーバン砂漠編Part2ということで「金を蓄える」から「潜伏者」までのステージを1つずつ攻略していきます!
金を蓄える
このステージでは「金」を収集し、25以上溜まったらストップして「合計数」を報告するプログラミングを行う必要があります。
そのため、まずは「金の数量」を取得できるアクセサリーと、処理を中断できる「break」コマンドが使える「PROGRAMMATICON Ⅲ」を装備しましょう。
「金」の数量は「value」で取得でき、処理の途中に「break」を書くことで中断することができます。
//「金」の合計数を保持する var totalGold = 0; loop { // 周囲の「金」があるかをチェックする var coin = this.findNearestItem(); if(coin) { // 「金」の位置まで進んでゲットする this.moveXY(coin.pos.x, coin.pos.y); // 取得した「金」の数を、合計値に加算する totalGold += coin.value; } if (totalGold >= 25) { // 「金」の数が25以上になった時点で処理を中断する break; } } // 「金」の合計を報告しに行く this.moveXY(58, 33); this.say(totalGold);
「break」を使って処理を中断すると、「loop」処理からも抜けることになるので覚えておきましょう。
デコイドリル
「デコイ」と呼ばれるロボットのようなユニットを召喚し、その合計数を報告するためのプログラミングを行うステージとなります。
まずは、デコイを生成できるようにする新しい「ハンマー」を装備します。
「デコイ」は、「垣根」や「トラップ」のように「buildXY()」から生成できるようになります。
ちなみに、「デコイ」1体につき「25金」必要なので、現在の「金」取得数を「gold」コマンドから調べるようにしましょう。
// 「デコイ」合計数を保持する var decoysBuilt = 0; loop { // 「金」の存在チェック var coin = this.findNearestItem(); if(coin) { // 「金」の収集をする this.moveXY(coin.pos.x, coin.pos.y); if(this.gold >= 25) { // 「25金」溜まったら、「デコイ」を生成する this.buildXY("decoy", this.pos.x, this.pos.y); // 「デコイ」の生成数を加算する decoysBuilt ++; // 「デコイ」を4体作ったら処理を中断する if(decoysBuilt == 4) break; } } } this.say("デコイを作るのが終わった!"); // 「デコイ」の合計数を報告しに行く this.moveXY(14, 36); this.say(decoysBuilt);
Bookkeeper
時間の経過によって、「3つ」の違う処理をプログラミングし、1つの処理が完了する度に報告する必要があるステージです。
「ループ処理」を3つ行うので、ちょっとコードが長くなってしまいますが、やっていることは単純なのでリラックスしてトライしてみましょう!
// 1回目の報告用に使う合計値 var totalEnemy1 = 0; // 2回目の報告用に使う合計値 var totalEnemy2 = 0; // 1回目のループ処理 loop { var enemy = this.findNearestEnemy(); // 15秒経過したらループを抜ける if(this.now() >= 15) { break; } else if(enemy) { this.attack(enemy); // 敵を倒したら合計値に加算する if(enemy.health <= 0) { totalEnemy1 += 1; } } } // 倒した敵の合計を報告する this.moveXY(59,33); this.say(totalEnemy1); // 2回目のループ処理 loop { var gold = this.findNearestItem(); // 30秒経過したらループを抜ける if(this.now() >= 30) { break; } else if(gold) { this.moveXY(gold.pos.x, gold.pos.y); } } // 取得した金の合計を報告する this.moveXY(59, 33); this.say(this.gold); // 3回目のループ処理 loop { var enemy2 = this.findNearestEnemy(); // 45秒経過したらループを抜ける if(this.now() >= 45) { break; } else if(enemy2) { this.attack(enemy2); if(enemy2.health <= 0) { totalEnemy2 += 1; } } } // 倒した敵の合計を報告する this.moveXY(59, 33); this.say(totalEnemy2);
1回目と3回目のループ処理は同じなので、関数を作って実行させるのも有効です。
Continuous Alchemy
このステージでは、「continue」コマンドを使って処理をキャンセルしながら進めていくことになります。
「break」は処理を中断する時に使いましたが、「continue」は処理をキャンセルしループの先頭へ自動的に戻ります。そのため、「continue」以降の処理はキャンセルされて、再度ループの先頭から処理が開始されます。
loop { // 「敵」と「アイテム」の存在確認 var enemy = this.findNearestEnemy(); var item = this.findNearestItem(); // もし「敵」がいなかったら処理をキャンセル if(!enemy) { continue; } // もし「アイテム」が無かったら処理をキャンセル if(!item) { this.say("Give me a drink!"); continue; } // もし「アイテム」が毒だったら処理をキャンセル if(item.type == "poison") { continue; } else { // 「アイテム」が「水」の場合のみ取りに行く this.moveXY(item.pos.x, item.pos.y); } // 元の位置へ移動する this.moveXY(34, 47); }
このプログラムを簡単に説明すると、アイテムが「水」の場合のみ取得する…というモノで、実際に「水」以外はすべて処理がキャンセルされているのが分かるかと思います。
砂漠での戦い
今までループ処理は「loop{}」を使ってましたが、このステージでは「while(){}」を使って繰り返し処理を行うようになっています。
「loop{}」と違い、「while(){}」は条件を挿入できるので、例えば「○○が5回以下になったら…」ループ処理をストップするような使い方ができます。
そこで、このステージでは5人の兵士に「攻撃依頼」をした後に、自分も攻撃に参加するというプログラムを書いていくことになります。
// 攻撃依頼の合計数を保持する var order = 0; // 5回攻撃依頼をしたらループをやめる while (order < 5) { // 10mずつ下へ移動し、兵士に攻撃依頼する this.moveXY(this.pos.x, this.pos.y - 10); this.say("Attack!"); // 攻撃依頼の回数を加算する order++; } // 依頼が終わったら、自分も攻撃に参加する loop { var enemy = this.findNearestEnemy(); if(enemy) { this.attack(enemy); } }
注意が必要なのは、「order++」で必ず回数を加算するという点でしょう。
「order」の値が「while」の条件式になっているので、加算しなければ無限ループに突入してしまうからです。
埃
大量に出現する「敵」を10体倒したら、「待ち伏せ場所」に移動するというプログラミングを行う必要があります。
前ステージと同様に、こちらも「while」で対応可能ですね。
// 合計攻撃数を保持する var attacks = 0; // 10体倒したらループをやめる while (attacks < 10) { var enemy = this.findNearestEnemy(); this.attack(enemy); // 倒した敵の数を合計に加算する attacks += 1; } // 10体倒したら、待ち伏せの場所へ移動する this.say("I should retreat!"); //∆ Don't just stand there blabbering! this.moveXY(79, 32);
サルヴの救助者
このステージでは、味方兵士の「名前」を呼ぶことで陣地へ移動させ、すべての味方が移動したあとに自分も移動し、最後に「垣根」を作って「敵」の侵入を阻止することになります。
そのため、まずは「垣根」を作れるハンマーを装備しましょう。
ポイントは、「配列」を使って名前を呼ぶ点です。
あらかじめ配列へ味方兵士の名前を登録しておくことで、順番に読み込んでいくことが出来るようになります。
// 味方兵士の名前を登録しておく var friendNames = ['Joan', 'Ronan', 'Nikita', 'Augustus']; // 配列の名前を0番目から読み込むための変数 var friendIndex = 0; // 「配列.length」で登録数を取得できる while (friendIndex < friendNames.length) { // 0番目から読み込むために、[ ]を使う var friendName = friendNames[friendIndex]; // 味方兵士を陣地へと移動させる this.say(friendName + ', go home!'); // 1つずつ加算することで、配列の値を順番に読み込む friendIndex++; } // 敵の侵入を防ぐために、「垣根」を作る this.moveXY(29, 30); this.buildXY("fence", 34, 30);
配列は、0から順番に数値を「[ ]」内に入れることで取得できるので、「for()」を使ったプログラミングも多いです。
Don't Rush, Be Quiet
大量の爆弾が降ってくる中を、指定された移動量で進みながらアイテムを取得していくステージです。
「0〜30」「0〜40」までの数字だけを返す関数を2つ作って、それを移動量にすることで爆弾に当たらないように進むことが出来るようになっています。
// 「0〜30」までの数字を返す関数 function mod30(n) { if (n >= 30) { return n - 30; } else { return n; } } // 「0〜40」までの数字を返す関数 function mod40(n) { // Use an if-statement to return the correct value. if(n >= 40) { return n - 40; } else { return n; } } // 2つの関数を使って移動量に変換する while (true) { var time = this.now(); var x = mod30(time) + 25; var y = mod40(time) + 10; this.moveXY(x, y); }
指定された数字だけを返す関数は、ゲーム制作などにも応用できるので丸ごと覚えておくと良いでしょう。
潜伏者
巨大な「ヤク」と、「シャーマン」と言う敵が混在するステージなのですが、目的は「シャーマン」だけを攻撃して倒すというもの。
そこで、新しい「メガネ」を装備すると、「findEnemies()」でステージ中に存在する「敵」の名前を登録した配列を取得することができます。
あとは、この配列から「シャーマン」だけをピックアップして攻撃すればOK!
// ステージ中に存在する敵の配列を取得する var enemies = this.findEnemies(); var enemyIndex = 0; // 取得した配列数だけループさせる while (enemyIndex < enemies.length) { // 配列の0番目から順番に名前を取得していく var enemy = enemies[enemyIndex]; // 名前が「シャーマン」の時だけ攻撃する if (enemy.type == 'shaman') { // 敵の体力が無くなるまで攻撃 while (enemy.health > 0) { this.attack(enemy); } } enemyIndex++; }
配列を扱うようになると、とにかく順番に値を読んでいく処理をよく書くようになるので、書き方をよーく覚えておきましょう!
「サーバン砂漠編Part3」に続く…