! ================================================================== ! RoboSteering ver1.08 ! ! (十進BASIC ソース): 全文コピーして実行してください。 ! ! 「コンピュータに意図した通りの処理を行わせるための論理的思考力」の開発が目的です。 ! Hour of Code ( http://hourofcode.jp/ )の「ブロック」(アイコン化されたコマンド)を ! ならべてプログラムを作る仕組みを、十進BASIC でも実装してみようと考えました。 ! ブロックを並べる形式を取り入れていますが、キーボードでの操作が必要です。 ! 商用でなければ、自由に利用したり、解析してみてください。 ! !   十進BASIC は、以下のURIより入手してください。 !   http://hp.vector.co.jp/authors/VA008683/ ! ! ! ! !  あなたはロボット(○)の操縦士です。黄色のマスを目指してロボットを操縦してください !   リアルタイムにロボットを「遠隔操縦」することができます。   ← キーボードから直接操作 !   Work Space にコマンドを並べて「自動操縦」することができます。← プログラムを記述して操作 ! ! ! (註)遠隔操縦モード(ゲームモード)での入力は、シフトキーと、方向キー(矢印キー)または、 !    テンキー(半角数字)の 2, 4, 6, 8 です。0 でやり直しになります。 ! ! (註2)「自動操縦モード」のプログラム記述のためには、プログラムが中断されている必要があります。 ! ! ! 2018.05.05 opened ! 2018.05.05 updated ! S. Nakajima ! ================================================================== LET d = 0 ! マップ初期データの指定。デフォルトは 0 です。1 以降で後方のデータを使用できます。 CALL Init ! 配列宣言などの初期動作 省略不可、1回のみ呼び出し。 CALL Init2 ! 初期画面の表示など 画面切り替え時そのつど呼び出し。 ! ========== 遠隔操縦[キーボードから操作を入力] ========= ! CALL ScreenMaker !  遠隔操縦用の画面データ作成をする場合、上行の ! を外して有効にしてください。 CALL ChoiceGame ! はじめに遠隔操縦(ゲームモード)と自動操縦(プログラムモード)のどちらで遊ぶか聞いてきます。 ! 授業時など、上行先頭に ! をつけて無効にすると、自動操縦モードのみで動作するようになります。 ! ========== 自動操縦 [プログラムから操作を入力] ========= IF CONFIRM$("黄色いマスがゴールです。WorkSpace にロボットを動かすコマンドが書けましたか。") = "NO" THEN PAUSE "Work Space 内を編集して、コマンドを並べるために、いちどプログラムを中断します。" STOP END IF ! Work Space 内にコマンドが正しく書けたと思ったら、プログラムを実行してみましょう。 ! #################################################################################### ! ======== Work Space =========== !  ↑ ● ここから。コマンドを並べてロボットの動きのプログラムを記述しましょう。 ! ● はじめは、「プログラムの実行」をしながら、短い動きの結果を確認しながら、 ! ● 少しずつ後ろにコマンドを追加していって完成させると良いかもしれません。 ! ● コンピュータは、人間と違って融通がききません。誤字脱字に気をつけて! ! ! ※ Work Space 内のすべてのコマンドは、ざっくり消してしまっても大丈夫です。 FOR k = 1 TO 2 ! 2回繰り返します。 CALL MoveForward ! 前へ進みます。 NEXT k CALL TurnRight ! 右を向きます。 FOR k = 1 TO 5 ! 5回繰り返します。 CALL MoveForward ! 前へ進みます。 CALL TurnLeft ! 左を向きます。 NEXT k FOR k = 1 TO 2 ! 2回繰り返します。 CALL MoveForward ! 前へ進みます。 NEXT k CALL TurnLeft ! 左を向きます。 FOR k = 1 TO 2 ! 2回繰り返します。 CALL MoveForward ! 前へ進みます。 NEXT k CALL Detection ! 最後にゴールできたかどうかの判定をします。ゴールなら終了です。 !  ↓ ● ここまで ! #################################################################################### ! === Manual ===================== ! ! ● 以下のコマンド(サブルーチン)を Call で呼び出せます。 ! コピーペーストする場合は、その行をペースト後、先頭の ! を外してください。 ! ! 例: Call MoveForward ! ! MoveForward ! ロボットを1歩前へ進めます。前方に 壁、箱、木、水、火があるときは進めません。 ! TurnRight ! ロボットの向きを90度右へ回転します ! TurnLeft ! ロボットの向きを90度左へ回転します ! ! PushBox ! 前方に箱があるとき、一つ奥へ押し、自身も前進します。 ! CutTree ! 前方に木があり木材を持っていないとき、切り倒しマップを空け、木材を得ます。自身も前進します。 ! GetWater ! 前方に水があり水を持っていないとき、水を得て、マップを空けます。自身も前進します。 ! CoverWater ! 前方に水があり木材を持っているとき、水に蓋をしてマップを空けます。自身も前進します。 ! PourWater ! 前方に火があり水を持っているとき、消火してマップを空けます。自身も前進します。 ! ! 一度に持てる資源(木材、水)は、いずれか1個のみ、使用も一度に1回です。 ! ! MeasTime ! ゴール判定とペアで、ゴールまでの所要時間の計測を行います。先頭に置いてください。省略可能。 ! Detection ! ゴール判定をします。黄色のマスがゴールです。 ! ! 木材も水も持たずに(茶色の状態で)ゴールしてください。 ! ! 単純にゴールを踏んだだけでは、判定行為は行われません。 ! ! 判定のためにはゴールのマスを踏んだ状態でこのコマンドがコールされる必要があります。 ! !   このサブルーチンを Call して、ゴール判定に失敗してもなにも起きません。 ! ! ※ ロボットの周辺に合わせた複雑な動きをさせるために、以下のコマンドも用意しました。 ! ! SearchFront ! ロボットの前方(など)をサーチし、以下の2つの変数に値を返します。 ! SearchRight ! SearchResult にマップデータの数値 0 〜 8 ! SearchLeft ! Destination$("empty", "occupied") ! SearchBack ! 前に進むことができるのは、前方の数値が 0(空), 6(ゴール), 7(空), 8(氷) ! SearchHere ! のときで、これらに対応した文字列は "empty" となります。 ! ! ThrowDice ! サイコロを振ります。結果は、die1、die2、die3 にランダムで 1 〜 6 を割り当てます。 ! ! 条件文と組み合わせて使うと、ランダムな動きをプログラムできます。 ! ! ! ● 同じ処理を繰り返すために、計数ループを使用することができます。 !  ※ 単純ループ Do 〜 Loop も使用できます。 ! その場合、適切にループから抜け出さないと無限に繰り返します。 ! ! 例: ! For k = 1 To 3 ! ← あらかじめ決めた回数(この場合 3 回)繰り返します。 ! Call MoveForward ! Next k ! ← Next の後ろには、計数のための変数名(ここでは k)を書きます。 ! ! ! ! ● 条件による判断(条件分岐)が可能です。 ! ● 自分でサブルーチンを組んで、複雑な処理を短いコマンドとして使用できます(Call で呼び出せます)。 ! WorkSpace 内の何処に書いても大丈夫ですが、始めか最後にまとめて置いておくと見やすいです。 !  ※ すでに定義されているサブルーチン名と重複しないようにお気を付けください。 ! ! 例: SUB Command1 ! 前に進めるときは進む。前に何か障害物があるなら右回りで前に障害物の無い方向を向く。 CALL SearchFront IF Destination$ ="empty" THEN CALL MoveForward ELSE FOR k = 1 TO 4 ! 4回で一周なので、これ以上繰り返す必要はありません。 CALL TurnRight CALL SearchFront IF Destination$ ="empty" THEN EXIT FOR NEXT k END IF END SUB SUB Command2 ! 右手に付けた壁を離さないようにして進む。右手法の1ステップ。 Call SearchRight If Destination$ ="empty" THEN Call TurnRight Call MoveForward Else For k = 1 To 3 Call SearchFront If Destination$ ="empty" THEN Call MoveForward Exit For Else Call TurnLeft End If Next k End If END SUB SUB RightHandMethod ! 右手法。ただし無限ループになっており、ゴール以外では止まりません。 DO CALL Command2 CALL Detection LOOP END SUB ! #################################################################################### ! === MapData ==================== DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ! データ指定時の番号 0 DATA 8, 4, 3, 0, 0, 0, 0, 4, 3, 8 ! デフォールトで使用するマップデータです。 DATA 8, 3, 0, 0, 0, 0, 3, 0, 0, 8 ! 必要に応じて書き換えてくださって結構です。 DATA 8, 0, 0, 0, 0, 0, 0, 0, 0, 8 DATA 8, 0, 0, 4, 0, 2, 0, 0, 0, 8 DATA 8, 0, 6, 0, 0, 2, 0, 0, 3, 8 DATA 8, 3, 0, 0, 0, 2, 0, 0, 0, 8 DATA 8, 8, 8, 8, 8, 2, 0, 8, 8, 8 DATA 5, 5, 5, 5, 5, 5, 0, 5, 5, 5 DATA 0, 0, 0, 0, 0, 0, 9, 0, 0, 0 ! 0 なにもないところ 白 ! 1 障害物(壁) 黒 □ 干渉できない障害物です。 ! 2 障害物(箱) 青 □ 向こうへ押しやることが可能です。 ! 3 障害物(木) 緑 ▽ 切ることが可能。水溜まりに蓋をする材料になります。 ! 4 障害物(火) 赤 △ 水を持っていれば消火可能です。 ! 5 障害物(水) 水色 ○ 汲みとることが可能。木を持っていれば蓋ができます。 ! 6 ゴール  黄色 ☆ ! 7 未定義    ピンク□ ロボの動作は白マスと同じです。 ! 8 氷      灰色 □ 一番端まで止まらずに動く。箱を動かした跡は白に戻る。 ! 9 Robo の初期位置 ! =========== 初期設定等 =========== SUB Init ! 画面設定、変数の宣言、その他の初期設定。1回のみ呼び出し OPTION BASE 0 DIM Map(11,11) SET WINDOW 0.5, 10.5, 0.5, 10.5 SET TEXT HEIGHT 0.8 SET TEXT JUSTIFY "center", "half" OPTION ANGLE DEGREES CALL ColorVar LET MeasTimeFlag = 0 LET ScreenFlag = 0 CALL SkipScreen END SUB SUB Init2 ! はじめに行う動作、処理、そのつど呼び出し CLEAR CALL GetMap CALL DrawMap CALL ResetRobo CALL SetRobo END SUB SUB SkipScreen ! 初期画面をずらす FOR k = 1 TO 100*d READ dummy NEXT k END SUB ! === 以下 サブルーチン定義等 ==== SUB MoveForward ! 前方に障害物がない場合、ロボを前に1マス進める。 WAIT DELAY 0.2 CALL SearchFront IF Destination$ = "empty" THEN DO LET LPx = x LET LPy = y FOR FootSteps = 1 TO 20 SET DRAW MODE HIDDEN ! 画面への描画をいったんオフにする。 Call ClrRobo CALL LastPoint CALL SearchFront LET x = x + COS(t)/20 LET y = y + SIN(t)/20 CALL SetRobo SET DRAW MODE EXPLICIT WAIT DELAY 0.05 NEXT FootSteps CALL LastPoint CALL SearchFront LOOP WHILE map(x,y) = 8 AND ( SerchResult = 0 OR SerchResult = 6 OR SerchResult = 7 OR SerchResult = 8) ! 氷から前方障害物以外で繰り返し ELSE WAIT DELAY 2 END IF END SUB SUB LastPoint ! 移動後にもとのマップ色を置く。 IF map(LPx, LPy) = 6 THEN SET TEXT COLOR 6 PLOT TEXT ,AT LPx, LPy : "★" END IF IF map(LPx, LPy) = 7 THEN SET TEXT COLOR 7 PLOT TEXT ,AT LPx, LPy : "■" END IF IF map(LPx, LPy) = 8 THEN SET TEXT COLOR 8 PLOT TEXT ,AT LPx, LPy : "■" END IF END SUB SUB TurnRight ! ロボ進行方向右へ90度回転 LET t = MOD(t-90,360) CALL SetRobo WAIT DELAY 0.5 END Sub SUB TurnLeft ! ロボ進行方向左へ90度回転 WAIT DELAY 0.5 LET t = MOD(t+90,360) CALL SetRobo END SUB SUB TurnFrontSideBack ! ロボ進行方向左へ180度回転 WAIT DELAY 0.5 LET t = MOD(t+180,360) CALL SetRobo END SUB SUB PushBox ! 箱をひとつ向こうへ押しやる WAIT DELAY 0.3 CALL SearchFront IF SerchResult = 2 THEN CALL SearchFrontOfFront IF Destination$ = "empty" THEN LET map(x + COS(t), y + SIN(t)) = 0 SET TEXT COLOR 0 PLOT TEXT ,AT x + COS(t), y + SIN(t) : "■" LET map(x + 2* COS(t), y + 2* SIN(t)) = 2 SET TEXT COLOR 2 PLOT TEXT ,AT x + 2* COS(t), y + 2* SIN(t) : "■" CALL MoveForward END IF END IF END SUB SUB CutTree ! 前方の木を切って、木材を得る WAIT DELAY 0.5 CALL SearchFront IF RoboColor <> 3 AND SerchResult = 3 THEN LET map(x + COS(t), y + SIN(t)) = 0 SET TEXT COLOR 0 PLOT TEXT ,AT x + COS(t), y + SIN(t) : "■" CALL MoveForward LET RoboColor = 3 CALL SetRobo END IF END SUB SUB GetWater ! 前方の水を汲み、水を得る WAIT DELAY 0.5 CALL SearchFront IF RoboColor <> 5 AND SerchResult = 5 THEN LET map(x + COS(t), y + SIN(t)) = 0 SET TEXT COLOR 0 PLOT TEXT ,AT x + COS(t), y + SIN(t) : "■" CALL MoveForward LET RoboColor = 5 CALL SetRobo END IF END SUB SUB CoverWater ! 持っている木材で前方の水を覆い隠す WAIT DELAY 0.5 CALL SearchFront IF RoboColor = 3 AND SerchResult = 5 THEN LET map(x + COS(t), y + SIN(t)) = 0 SET TEXT COLOR 0 PLOT TEXT ,AT x + COS(t), y + SIN(t) : "■" CALL MoveForward LET RoboColor = 9 CALL SetRobo END IF END SUB SUB PourWater ! 持っている水で前方の火を消しとめる WAIT DELAY 0.5 CALL SearchFront IF RoboColor = 5 AND SerchResult = 4 THEN LET map(x + COS(t), y + SIN(t)) = 0 SET TEXT COLOR 0 PLOT TEXT ,AT x + COS(t), y + SIN(t) : "■" CALL MoveForward LET RoboColor = 9 CALL SetRobo END IF END SUB SUB MeasTime ! 所要時間を計測する場合に呼び出す。計時の起点とする。 LET MeasTimeFlag = 1 LET StartTime = TIME END SUB SUB Detection ! ゴールマスに居るかどうかの判定、付随するもろもろ。 IF Map(x,y) = 6 AND RoboColor = 9 THEN LET MadeGoal$ = "You've Got It!" CALL CountRemainingObstacle IF RemainingObstacle = 0 THEN LET MadeGoal$ = "Perfectly Done!" SET TEXT COLOR 7 PLOT TEXT ,AT 5.5, 5 : MadeGoal$ IF MeasTimeFlag = 1 THEN PLOT TEXT ,AT 5.5, 4 : STR$(TIME -StartTime) &"秒" END IF STOP END IF END SUB SUB CountRemainingObstacle ! マップデータから残っている障害物をカウント LET RemainingTree = 0 LET RemainingFire = 0 LET RemainingWater = 0 FOR mx = 1 TO 10 FOR my = 1 TO 10 IF map(mx, my) = 3 THEN LET RemainingTree = RemainingTree + 1 IF map(mx, my) = 4 THEN LET RemainingFire = RemainingFire + 1 IF map(mx, my) = 5 THEN LET RemainingWater = RemainingWater + 1 NEXT my NEXT mx LET RemainingObstacle = RemainingTree + RemainingFire + RemainingWater END SUB SUB SearchFront ! 前方のマップデータを読み取る。 LET SerchResult = map(x + COS(t), y + SIN(t)) IF SerchResult < 1 OR SerchResult > 5 THEN LET Destination$ = "empty" ELSE LET Destination$ = "occupied" END IF END SUB SUB SearchRight LET SerchResult = map(x + COS(t-90), y + SIN(t-90)) IF SerchResult < 1 OR SerchResult > 5 THEN LET Destination$ = "empty" ELSE LET Destination$ = "occupied" END IF END SUB SUB SearchLeft LET SerchResult = map(x + COS(t+90), y + SIN(t+90)) IF SerchResult < 1 OR SerchResult > 5 THEN LET Destination$ = "empty" ELSE LET Destination$ = "occupied" END IF END SUB SUB SearchBack LET SerchResult = map(x - COS(t), y - SIN(t)) IF SerchResult < 1 OR SerchResult > 5 THEN LET Destination$ = "empty" ELSE LET Destination$ = "occupied" END IF END SUB SUB SearchHere LET SerchResult = map(x, y) IF SerchResult < 1 OR SerchResult > 5 THEN LET Destination$ = "empty" ELSE LET Destination$ = "occupied" END IF END SUB SUB SearchFrontOfFront ! マップ一番外側で実施するとエラーになることに注意。PushBox専用のサブルーチンです。 LET SerchResult = map(x + 2* COS(t), y + 2* SIN(t)) IF SerchResult < 1 OR SerchResult > 6 THEN ! Box は、ゴールマスに移動できません。 LET Destination$ = "empty" ELSE LET Destination$ = "occupied" END IF END SUB SUB ThrowDice ! 3つのサイコロを振る。それぞれ、ランダムに1 〜 6 が与えられる。 RANDOMIZE LET Die1 = 1+INT(6*RND) LET Die2 = 1+INT(6*RND) LET Die3 = 1+INT(6*RND) END SUB ! ========== ロボット関係 ========== SUB ResetRobo ! ロボの初期状態の指定 LET t = 90 ! とりあえず上向き。 LET RoboColor = 9 ! 青色。ただし、持ち物によって変色(木材→緑色、水→水色)。 END SUB SUB SetRobo ! ロボを表示 SET TEXT COLOR RoboColor PLOT TEXT ,AT x,y : "●" CALL ShowDirection END sub SUB ClrRobo ! ロボを非表示 SET TEXT COLOR 0 ! 白色 SET TEXT HEIGHT 1.0 ! 少し大きい文字にしないと、輪郭が残ってしまう。 PLOT TEXT ,AT x,y : "●" SET TEXT HEIGHT 0.8 ! 元のサイズに戻しておく。 DRAW grid END SUB SUB ShowDirection ! ロボの向きを表示 SET TEXT COLOR 6 ! 黄色 SELECT CASE t CASE 0 LET Direction$ = "→" CASE 90 LET Direction$ = "↑" CASE 180 LET Direction$ = "←" CASE 270 LET Direction$ = "↓" CASE ELSE LET Direction$ = "" END SELECT PLOT TEXT ,AT x,y : Direction$ END SUB ! =========== マップ関係 =========== SUB GetMap ! マップデータを配列に取り込み LET x = 1 ! map data に始点を書き忘れた時用 LET y = 1 ! map data に始点を書き忘れた時用 FOR mapY = 10 TO 1 STEP -1 FOR mapX = 1 TO 10 READ map(mapX,mapY) IF map(mapX,mapY) = 9 THEN LET x = mapX LET y = mapY LET map(x,y) = 0 END IF NEXT mapX NEXT mapY LET map(x,y) = 0 ! map data に始点を書き忘れた時用 FOR mapX = 0 TO 11 ! 外周に壁を設定(画面から外に飛び出さないようにする) LET map(mapX,0) = 1 LET map(mapX,11) = 1 NEXT mapX FOR mapY = 1 TO 10 LET map(0,mapY) = 1 LET map(11,mapY) = 1 NEXT mapY END SUB SUB DrawMap FOR mapY = 10 TO 1 STEP -1 FOR mapX = 1 TO 10 IF map(mapX,mapY) > 0 THEN SET TEXT COLOR map(mapX,mapY) SELECT CASE map(mapX,mapY) CASE 3 ! 木 LET MapCharacter$ = "▼" CASE 4 ! 火 LET MapCharacter$ = "▲" CASE 5 ! 水 LET MapCharacter$ = "●" CASE 6 ! ゴール LET MapCharacter$ = "★" CASE ELSE LET MapCharacter$ = "■" END SELECT PLOT TEXT ,AT mapX,mapY : MapCharacter$ END IF NEXT mapX NEXT mapY DRAW grid END SUB SUB PrintMap ! チェック用。マップデータを印字する。 DRAW grid FOR mapY = 10 TO 1 STEP -1 FOR mapX = 1 TO 10 PRINT map(mapX,mapY); NEXT mapX PRINT NEXT mapY PRINT END SUB SUB ColorVar ! 色指定番号ごとの色の調整をしています。 ! モニタの種類により見難いなどの場合、以下の数値(R,G,B)を変えて下さい。 SET COLOR MIX(1) 0.2, 0.2, 0.4 ! 黒 SET COLOR MIX(2) 0.2, 0.0, 0.75 ! 青 SET COLOR MIX(3) 0.2, 0.8, 0.3 ! 緑 SET COLOR MIX(4) 1.0, 0.2, 0.0 ! 赤 SET COLOR MIX(5) 0.1, 0.8, 1.0 ! 水 SET COLOR MIX(6) 1.0, 0.9, 0.0 ! 黄 SET COLOR MIX(7) 1.0, 0.7, 1.0 ! 桃 SET COLOR MIX(8) 0.85,0.85,0.90 ! 灰色 うすめ SET COLOR MIX(9) 0.6, 0.3, 0.15 ! 茶 END SUB ! ========= 遠隔操縦モード ========= SUB ChoiceGame IF CONFIRM$("遠隔操縦[キーボード]モードで遊びますか。(自動操縦[プログラム]モードで遊ぶ場合「いいえ」を選んでください)。") = "YES" THEN CALL GameBody END SUB SUB GameBody Clear CALL PrintMission CALL CountData DO ! ============= ここから、画面ひとつ分、スタートからゴールまで ============= CALL ChooseData ! 画面選択 CALL Init2 ! はじめに行う動作、処理 DO ! ============= ここから、コマンド一つ分の動作 ============= Call DetectTheDirection ! 押下されているキーの判別 IF ShiftFlag = 0 THEN ! シフトキーが押されていないとき SELECT CASE inkey$ CASE "Up" ! ↑ または 8 で前進 CALL MoveForward PRINT "CALL MoveForward" ! このモードでは、Print文でログを残す。以下同様。 CASE "Right" ! → または 6 で右を向け CALL TurnRight PRINT "CALL TurnRight" CASE "Left" ! ← または 4 で左を向け CALL TurnLeft PRINT "CALL TurnLeft" CASE "Down" ! ↓ または 2 で回れ右せよ CALL TurnFrontSideBack PRINT "CALL TurnFrontSideBack" CASE "Break" ! 0 を押して、途中終了、画面選択に戻る PRINT "* Break *" EXIT DO END SELECT ELSE ! シフトキーが押されているとき IF inkey$ = "Up" THEN CALL SearchFront SELECT CASE SerchResult ! 前方の障害物により動作を変える。 CASE 2 CALL PushBox PRINT "CALL PushBox" CASE 3 CALL CutTree PRINT "CALL CutTree" CASE 4 CALL PourWater PRINT "CALL PourWater" CASE 5 IF RoboColor = 3 THEN CALL CoverWater PRINT "CALL CoverWater" ELSE CALL GetWater PRINT "CALL GetWater" END IF CASE ELSE ! 障害物がない場合はなにもしない END SELECT END IF End IF ! ゴール判定 IF Map(x,y) = 6 AND RoboColor = 9 THEN ! ゴール達成時 LET MadeGoal$ = "You've Got It!" CALL CountRemainingObstacle IF RemainingObstacle = 0 THEN LET MadeGoal$ = "Perfectly Done!" PRINT MadeGoal$ ELSE PRINT MadeGoal$ PRINT "残りの木は"; RemainingTree ; "本です" PRINT "残りの火は"; RemainingFire ; "個です" PRINT "残りの水は"; RemainingWater ; "個です" END IF SET TEXT COLOR 7 PLOT TEXT ,AT 5.5, 5 : MadeGoal$ EXIT DO ! 画面選択に戻る END IF ! ============= ここまで、コマンド一つ分の動作 ============= LOOP PRINT ! ============= ここまで、画面ひとつ分、スタートからゴールまで ============= LOOP ! プログラムの記述上、この Do 〜 Loop には出口がないので、次の行は無効。 STOP ! 遠隔操作モード終了時に、プログラムを強制的に終了する。 END SUB SUB PrintMission ! 目的の表示 PRINT " ミッション! ロボットを操作せよ! " PRINT PRINT "○ があなたのロボットです。ゴールを目指してください。" PRINT "ゴールは黄色のマスです。" PRINT "半角の 0 (ゼロ)を入力すると、その画面をあきらめます。" PRINT "カーソルキーで向きを変えたり、移動したりします。" PRINT "左右は相対方向なので気をつけてください。" PRINT PRINT " 灰色の氷 … 滑って止まれません。箱を重ねると消えます。" PRINT PRINT "その他の障害物のあるところは進めませんが、" PRINT "シフトを押しながらカーソルを押すと、" PRINT "以下の動作をすることができます。" PRINT PRINT " 青い箱 … 一つ奥に押し込む" PRINT " 緑の木 … 木を切って進む" PRINT " 水色の水 … 水を吸収して進む" PRINT " 水色の水 … 木材を持っていれば蓋をして進む" PRINT " 赤い炎 … 水を持っていれば消火して進む" PRINT PRINT "言い忘れましたが、ゴールするときには" PRINT "何も持っていない状態(茶色)でなければなりません。" PRINT "木材や水は、一度使用すると持っていない状態に戻ります。" PRINT "がんばって!!" PRINT PRINT " ※ 終了は、画面選択の小ウィンドウから、中止を選んでください。" PRINT PRINT END SUB SUB CountData ! Data文が、何セットあるのかのカウント RESTORE LET count = 0 do READ IF MISSING THEN EXIT DO : dummy LET count = count +1 LOOP LET NumberOfStage = count/100 IF INT(NumberOfStage) <> NumberOfStage THEN PRINT "データに不備があります" pause END IF END SUB SUB ChooseData ! 何セット目のデータを用いるのかの選択 IF NumberOfStage >= 2 THEN LET Text$ = "画面を選んでください。 (1 〜 " & STR$(NumberOfStage-1) & ") → " DO INPUT PROMPT TEXT$ : dn LOOP UNTIL dn=INT(dn) AND 0<=dn AND dn <= NumberOfStage-1 END IF RESTORE FOR k = 1 TO 100*dn READ dummy NEXT k END SUB SUB DetectTheDirection ! 上下左右の決定 カーソルキー使用 LET inkey$ = "" LET ShiftFlag = 0 DO CHARACTER INPUT CLEAR, NOWAIT :inkey$ ! キーボードから入力した文字列を格納する。バッファクリア、入力が無い場合も入力を待たない。 IF GetKeyState(37)>=0 AND GetKeyState(38)>=0 AND GetKeyState(39)>=0 AND GetKeyState(40)>=0 THEN ! 矢印キー(カーソルキー)の押下状態(リアルタイム)を調べる。非負で押下なし。 ! 連続判定を避けるため。矢印キー全てが押されていない状態を経由しないと、矢印キーを有効にしない。 ! 同時押しは、カーソルのみ、↑、→、←、↓ の順(並べ順の逆順)で優先する。 LET ShiftFlag = 0 LET MoveFlag = 0 END IF IF GetKeyState(16)<0 AND MoveFlag = 0 THEN ! shift キー押下 LET ShiftFlag = 1 END IF IF GetKeyState(40)<0 AND MoveFlag = 0 THEN ! ↓ キー押下 LET inkey$ ="2" LET MoveFlag = 1 END IF IF GetKeyState(37)<0 AND MoveFlag = 0 THEN ! ← キー押下 LET inkey$ ="4" LET MoveFlag = 1 END IF IF GetKeyState(39)<0 AND MoveFlag = 0 THEN ! → キー押下 LET inkey$ ="6" LET MoveFlag = 1 END IF IF GetKeyState(38)<0 AND MoveFlag = 0 THEN ! ↑ キー押下 LET inkey$ ="8" LET MoveFlag = 1 END IF LOOP UNTIL inkey$ = "0" OR inkey$ = "2" OR inkey$ = "4" OR inkey$ = "6" OR inkey$ = "8" IF inkey$ = "0" THEN LET inkey$ = "Break" IF inkey$ = "2" THEN LET inkey$ = "Down" IF inkey$ = "4" THEN LET inkey$ = "Left" IF inkey$ = "6" THEN LET inkey$ = "Right" IF inkey$ = "8" THEN LET inkey$ = "Up" END SUB ! ========= 画面データ作成 ========= SUB ScreenMaker CALL InitialScreen DO DO CALL PutColorOnCells CALL ReadFromImage IF CONFIRM$("この状態で出力しますか") = "YES" THEN EXIT DO LOOP CALL DataPutOut LOOP WHILE CONFIRM$("もう一度画面データを作成しますか") = "YES" STOP END SUB SUB InitialScreen clear SET WINDOW 0,13,0,13 DRAW grid SET WINDOW -1,12,-1,12 SET LINE COLOR 1 PLOT LINES : 0,0; 0,10; 10,10; 10,0; 0,0 SET WINDOW -0.5,12.5,-0.5,12.5 SET TEXT COLOR 1 PLOT TEXT , AT 1,12 : "■" PLOT TEXT , AT 1,11 : "壁" SET TEXT COLOR 2 PLOT TEXT , AT 2,12 : "■" PLOT TEXT , AT 2,11 : "箱" SET TEXT COLOR 3 PLOT TEXT , AT 3,12 : "■" PLOT TEXT , AT 3,11 : "木" SET TEXT COLOR 4 PLOT TEXT , AT 4,12 : "■" PLOT TEXT , AT 4,11 : "火" SET TEXT COLOR 5 PLOT TEXT , AT 5,12 : "■" PLOT TEXT , AT 5,11 : "水" SET TEXT COLOR 8 PLOT TEXT , AT 6,12 : "■" PLOT TEXT , AT 6,11 : "氷" SET TEXT COLOR 7 PLOT TEXT , AT 7,12 : "■" PLOT TEXT , AT 7,11 : "" SET TEXT COLOR 6 PLOT TEXT , AT 8,12 : "■" PLOT TEXT , AT 8,11 : "ゴ" SET TEXT COLOR 9 PLOT TEXT , AT 9,12 : "●" PLOT TEXT , AT 9,11 : "ろ" SET TEXT COLOR 1 PLOT TEXT , AT 10,12 : "□" PLOT TEXT , AT 10,11 : "消" PLOT TEXT , AT 11,12 : "◎" PLOT TEXT , AT 11,11 : "Ok" PLOT TEXT , AT 12,12 : "×" PLOT TEXT , AT 12,11 : "Re" IF ScreenFlag = 0 THEN CALL PrintScreenManual END SUB SUB PrintScreenManual PRINT PRINT "マウス左クリックで画面を編集します。" PRINT "一番上の行をクリックしてから、枠内をクリックしてください。" PRINT "「ゴ」はゴールです。必ず1か所以上ないと終了判定ができません。" PRINT "「ろ」はロボットの初期位置です。1か所を指定してください。" PRINT "「OK」で、チェック後、Data 文の生成モードになります。" PRINT "「Re」で、画面をすべてクリアします。" PRINT "木、火、水の全消しをするためには「水=火+木」の関係が必要です。" PRINT END SUB SUB PutColorOnCells LET InkeyColor = 0 DO MOUSE POLL MouseX, MouseY, MouseLeft, MouseRight IF MouseLeft =1 THEN LET MX = ROUND(MouseX,0) LET MY = ROUND(MouseY,0) IF MY = 12 THEN ! パレットメニュー位置 IF MX = 12 THEN IF ScreenFlag = 2 THEN LET ScreenFlag = 1 CALL InitialScreen END IF END IF IF MX = 11 THEN EXIT DO IF 1 <= MX AND MX <= 10 THEN ASK PIXEL VALUE (MX,MY) InkeyColor END IF END IF IF 1 <= MY AND MY <= 10 THEN ! 枠内である場合 IF 1 <= MX AND MX <= 10 THEN ! LET ScreenFlag = 2 SET TEXT COLOR InkeyColor PLOT TEXT ,AT mx, my : "■" END IF END IF END IF loop END SUB SUB ReadFromImage LET GoalFlag = 0 LET RoboFlag = 0 FOR x = 1 TO 10 FOR y = 1 TO 10 ASK PIXEL VALUE (x,y) map(x,y) IF map(x,y) = 6 THEN LET GoalFlag = GoalFlag + 1 END IF IF map(x,y) = 9 THEN LET RoboFlag = RoboFlag + 1 END IF NEXT y NEXT x IF GoalFlag = 0 THEN PAUSE "ゴールがありません" IF RoboFlag = 0 THEN PAUSE "ロボットがいません" IF RoboFlag > 1 THEN PAUSE "ロボットは1体にしてください" CALL CountRemainingObstacle IF RemainingWater <> RemainingTree + RemainingFire THEN pause "水の数が、火と木の合計と同じではありません" END IF END SUB SUB DataPutOut FOR Y = 10 TO 1 STEP -1 PRINT "Data"; FOR x = 1 TO 9 PRINT " " & STR$(map(x,y)) & ","; NEXT x PRINT map(10,y) NEXT y PRINT END SUB ! =========== 変更履歴 ============= ! 1.04 色指標の一部変更。壁と箱、ロボット色など。 ! 1.05 障害物の形状を□から△などに変更。ucd 対応(笑 ! MoveForward サブのに、表示オフと表示オンを追記。バタつきをなくすため。 ! 1.07 動作等に影響しない微修正 ! ! ====== 遠隔操縦用画面データ ====== ! データは、適宜追加、削除可能です。動作に影響しません。 ! ただし、データは 10 × 10 マス分(100個)で1セットです。 DATA 0, 0, 0, 1, 0, 0, 0, 0, 1, 0 ! 1 Data 0, 1, 0, 0, 0, 1, 0, 1, 0, 0 Data 0, 1, 1, 1, 0, 1, 0, 0, 1, 0 Data 0, 0, 0, 0, 1, 0, 0, 1, 0, 0 Data 1, 1, 1, 0, 1, 0, 1, 0, 1, 0 Data 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 Data 0, 1, 1, 1, 0, 1, 1, 1, 1, 0 Data 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 Data 1, 0, 1, 1, 1, 1, 1, 0, 1, 1 Data 6, 0, 0, 9, 0, 0, 0, 0, 0, 0 DATA 0, 0, 0, 2, 6, 2, 0, 0, 0, 0 ! 2 Data 0, 0, 0, 2, 0, 2, 0, 0, 0, 0 Data 0, 0, 0, 2, 0, 2, 0, 0, 0, 0 Data 0, 0, 0, 2, 4, 2, 0, 0, 0, 0 Data 0, 0, 0, 2, 0, 2, 0, 0, 0, 0 Data 0, 0, 0, 2, 6, 2, 0, 0, 0, 0 Data 0, 0, 0, 2, 0, 2, 0, 0, 0, 0 Data 0, 0, 0, 2, 5, 2, 0, 0, 0, 0 Data 0, 0, 0, 2, 0, 2, 0, 0, 0, 0 Data 0, 0, 0, 2, 9, 2, 0, 0, 0, 0 DATA 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ! 3 DATA 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 DATA 0, 0, 5, 0, 6, 0, 0, 0, 0, 0 DATA 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 DATA 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 DATA 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 DATA 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 DATA 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 DATA 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 DATA 0, 0, 3, 0, 9, 0, 0, 0, 0, 0 DATA 0, 4, 0, 0, 5, 0, 0, 0, 0, 0 ! 4 DATA 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 DATA 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 DATA 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 DATA 0, 6, 0, 0, 0, 0, 0, 0, 0, 0 DATA 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 DATA 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 DATA 0, 0, 0, 0, 0, 0, 0, 0, 6, 0 DATA 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 DATA 0, 0, 0, 0, 9, 0, 0, 0, 0, 0 DATA 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 ! 5 Data 0, 2, 0, 0, 0, 0, 0, 0, 0, 0 Data 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 Data 0, 0, 0, 2, 0, 0, 0, 0, 0, 0 Data 0, 0, 0, 0, 2, 0, 0, 0, 0, 0 Data 0, 0, 0, 0, 0, 2, 0, 0, 0, 0 DATA 0, 0, 0, 0, 0, 0, 2, 6, 0, 5 Data 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 Data 0, 0, 0, 0, 0, 0, 0, 0, 2, 0 DATA 3, 8, 8, 8, 8, 8, 8, 8, 9, 2 DATA 0, 0, 2, 0, 6, 0, 0, 0, 0, 0 ! 6 DATA 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 DATA 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 DATA 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 DATA 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 DATA 0, 0, 2, 2, 4, 2, 2, 2, 2, 2 DATA 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 DATA 0, 0, 0, 0, 0, 0, 0, 0, 5, 0 DATA 0, 0, 0, 2, 2, 2, 0, 0, 0, 0 DATA 0, 0, 0, 2, 9, 2, 0, 0, 0, 0 DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 6 ! 7 DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 DATA 8, 8, 8, 9, 8, 8, 8, 8, 8, 8 DATA 4, 8, 8, 8, 8, 8, 8, 8, 8, 5 ! 8 DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 DATA 8, 8, 8, 2, 8, 8, 8, 8, 8, 8 DATA 8, 8, 8, 8, 8, 8, 8, 8, 6, 8 DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 DATA 5, 8, 8, 9, 8, 8, 8, 8, 8, 3 DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ! 9 DATA 8, 8, 8, 3, 8, 8, 8, 8, 8, 8 DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 DATA 8, 8, 6, 8, 8, 8, 8, 8, 6, 8 DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 DATA 8, 5, 8, 8, 8, 8, 8, 8, 8, 4 DATA 8, 8, 8, 8, 8, 8, 5, 8, 8, 8 DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 DATA 8, 8, 8, 9, 8, 8, 8, 8, 8, 8 DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ! 10 Data 8, 4, 8, 8, 3, 8, 8, 8, 2, 8 Data 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 Data 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 Data 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 Data 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 Data 8, 8, 8, 8, 5, 8, 8, 8, 6, 8 Data 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 Data 8, 5, 8, 8, 8, 8, 8, 9, 2, 8 Data 8, 8, 8, 8, 2, 8, 8, 8, 8, 8 DATA 4, 4, 4, 4, 4, 4, 4, 5, 0, 0 ! 11 Data 6, 8, 8, 8, 8, 8, 8, 8, 8, 8 DATA 5, 5, 5, 5, 5, 5, 5, 5, 0, 0 DATA 2, 2, 2, 2, 2, 3, 5, 3, 0, 0 Data 8, 8, 8, 8, 8, 2, 2, 2, 2, 2 Data 0, 2, 2, 2, 0, 0, 0, 0, 0, 0 DATA 3, 0, 0, 5, 2, 0, 2, 2, 2, 2 DATA 0, 0, 0, 0, 2, 2, 2, 8, 8, 8 DATA 4, 2, 2, 2, 2, 9, 2, 8, 2, 2 DATA 8, 8, 8, 8, 8, 8, 2, 8, 2, 8 DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ! 12 Data 8, 0, 0, 0, 0, 2, 8, 0, 2, 5 Data 8, 0, 8, 8, 8, 2, 8, 0, 2, 2 Data 8, 0, 8, 0, 8, 2, 6, 0, 0, 0 Data 8, 0, 8, 0, 8, 2, 8, 2, 2, 2 Data 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 Data 8, 0, 8, 0, 8, 0, 8, 8, 2, 0 Data 8, 8, 8, 2, 8, 8, 8, 8, 2, 0 Data 3, 0, 0, 2, 0, 0, 8, 8, 2, 0 Data 8, 8, 8, 8, 8, 8, 8, 8, 8, 9 DATA 0, 6, 0, 0, 2, 2, 2, 2, 2, 6 ! 13 DATA 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 Data 2, 2, 2, 2, 2, 2, 6, 2, 0, 0 Data 0, 0, 2, 3, 5, 5, 4, 2, 0, 0 Data 0, 0, 2, 0, 2, 0, 0, 2, 0, 0 Data 0, 0, 2, 0, 0, 2, 0, 2, 0, 0 Data 0, 0, 2, 2, 2, 2, 0, 2, 0, 0 DATA 6, 6, 8, 8, 8, 8, 8, 2, 0, 0 Data 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 Data 9, 2, 0, 0, 0, 0, 0, 0, 0, 0 DATA 6, 8, 8, 8, 8, 8, 8, 8, 8, 8 ! 14 Data 4, 5, 4, 5, 4, 5, 4, 5, 4, 8 Data 3, 5, 3, 5, 3, 5, 3, 5, 5, 8 Data 4, 5, 4, 5, 4, 5, 4, 5, 4, 8 Data 3, 5, 3, 5, 3, 5, 3, 5, 5, 8 Data 4, 5, 4, 5, 4, 5, 4, 5, 4, 8 Data 5, 4, 3, 5, 5, 4, 3, 5, 5, 8 Data 5, 3, 4, 5, 4, 3, 5, 5, 5, 8 Data 3, 5, 5, 4, 5, 5, 3, 4, 3, 8 Data 9, 8, 8, 8, 8, 8, 8, 8, 8, 8 DATA 9, 2, 0, 1, 8, 5, 8, 8, 8, 4 ! 15 Data 8, 8, 0, 0, 8, 0, 8, 0, 8, 7 Data 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 Data 8, 0, 8, 0, 8, 0, 8, 0, 8, 8 Data 8, 0, 8, 0, 8, 0, 8, 0, 8, 8 Data 8, 0, 8, 0, 8, 0, 8, 0, 8, 8 Data 8, 0, 8, 0, 8, 0, 8, 0, 8, 8 Data 8, 0, 8, 0, 8, 0, 8, 0, 8, 8 Data 8, 0, 8, 0, 8, 0, 8, 0, 8, 8 Data 8, 8, 8, 3, 8, 8, 8, 5, 8, 6 DATA 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 ! 16 Data 8, 7, 5, 7, 8, 8, 7, 7, 7, 5 Data 7, 8, 8, 8, 8, 8, 8, 8, 7, 8 Data 7, 8, 4, 7, 8, 8, 8, 8, 7, 8 Data 7, 8, 8, 7, 8, 8, 3, 8, 7, 8 Data 8, 7, 7, 7, 8, 8, 8, 7, 8, 8 Data 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 Data 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 Data 8, 9, 8, 8, 8, 8, 8, 8, 6, 8 Data 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 END