====== 前回までの話(すごろくの演習問題のつづき) ====== ==== 演習問題:すごろくを作ってみよう ==== すごろく int goal_dist = 10; 盤面の構成 S_ _ _ _ _ _ _ _ _ _G 1 2 3 4 5 6 7 8 9 10コマ Oが自分の駒(スタート状態) SO _ _ _ _ _ _ _ _ _G 3コマ目に自分がいる S_ _ O _ _ _ _ _ _ _G ゴールした状態 S_ _ _ _ _ _ _ _ _ OG ⓪初期盤面表示 ①サイコロ振る(賽の目表示)  rand() % 6 + 1 ②盤面表示(自駒を進める) ③ゴールしたか? (goal_distを自分の駒が過ぎたか?)   YES:おめでとうの表示 NO:2に戻る === 乱数とサイコロ === さいころは以下のように作ることができそう。\\ - 乱数の初期化(プログラム中ではじめの方で1度だけ行われればよい) - 乱数の発生(1~6) - あとは変数に好きにぶっこんで使う! //乱数の初期化(1回だけやる) srand((unsigned int)time(nullptr)); int saikoro; //1~6の乱数を作ってsaikoroに代入 saikoro = rand() % 6 + 1; さいころを10回振るサンプルソースコード\\ #include using std::cout; using std::cin; using std::endl; int main() { //const つけると定数になります。定数は変えられない数 const int goal_dist = 10; //乱数の初期化(1回だけやる) srand((unsigned int)time(nullptr)); //さいころを10回振る繰り返し for (int i = 0; i < 10; i++) { cout << rand() % 6 + 1 << endl; } return 0; } ==== すごろくの設計 ==== - 初期盤面の表示 - サイコロを振る - コマを進める - ゴールした? * YES:ループを抜ける * NO :2に戻る - おめでとうのメッセージ表示→終了 ==== 盤面の表示から考えてみる ==== 盤面は以下のように表される。\\ S: スタート地点 G: ゴール地点 O: 自分のコマ SO _ _ _ _ _ _ _ _ _G 初めに、自分のコマなしで盤面のみ表示してみる。\\ == ソースコード:盤面の表示 == #include using std::cout; using std::cin; using std::endl; int main() { //const つけると定数になります。定数は変えられない数 //すごろくのマスの数を表す const int goal_dist = 10; //乱数の初期化(1回だけやる) srand((unsigned int)time(nullptr)); //盤面を表示するブロック cout << "S"; for (int i = 1; i <= goal_dist; i++) { cout << "_"; } cout << "G"; return 0; } == 実行結果:盤面の表示 == S__________G * このままだと、"\_"が全部つながってしまって、自分が何コマ目にいるか分かりづらい。 * スペースを空けるなど工夫してみよう * 例:S_ _ _ _ _ _ _ _ _ _G * スペースの表示の仕方とGの表示の仕方でちょっと条件判断がひつようになるよね ==== 盤面に自分のコマを表示 ==== 自分のコマが今どこにいるかという変数を考える。\\ //盤面上の位置を1~goal_distで表す int piece = 1; この変数を使って、現在の盤面を表示するときに、\\ マスの位置=自コマの位置なら、"O"\\ それ以外なら、"_"を表示するように改良する。\\ == ソースコード:自コマの表示 == #include using std::cout; using std::cin; using std::endl; int main() { //const つけると定数になります。定数は変えられない数 //すごろくのマスの数を表す const int goal_dist = 10; //乱数の初期化(1回だけやる) srand((unsigned int)time(nullptr)); //すごろくのコマを表す(1がスタート、goal_distがゴール) int piece = 4;//特に意味はないが4マス目にいることにする //盤面を表示するブロック cout << "S";//スタートを表示 for (int i = 1; i <= goal_dist; i++) { //iがpieceと同じときは"O"それ以外はマス"_"を表示 if (i == piece) {cout << "O";} //自コマを表示するブロック else {cout << "_";} //マスを表示するブロック //goal_dist回目はスペースじゃなくGoalを表示 if (i != goal_dist) {cout << " ";} //最後以外はスペースを入れる else {cout << "G";} //最後はスペースじゃなくゴール(G) } return 0; } == 実行結果:自コマの表示 == goal_dist = 10で\\ piece = 1 のとき\\ SO _ _ _ _ _ _ _ _ _G goal_dist = 10で\\ piece = 4 のとき\\ S_ _ _ O _ _ _ _ _ _G * goal\_distを変えると盤面のマスの数が変化するよね? * 自分のマスの位置とgoal\_distを変更して、表示がどう変化するかいろいろ試してみよう ==== せめて、すごろくらしく ==== 最後に、すごろくとして完成させる!\\ - 初期盤面の表示 - サイコロを振る - コマを進める - ゴールした? * YES:ループを抜ける * NO :2に戻る - おめでとうのメッセージ表示→終了 どのようにループを組み合わせれば、サイコロを振ってゴールまでコマを進められるかな?\\ 繰り返しの条件、つまりゴールの条件 初めは、ゴールを超えたら、ゴール! { サイコロ振る コマ進める //盤面を表示する繰り返し 現在の盤面が表示される SO _ _ _ _ _ _ _ _ _G } ループ抜けたら、ゴールしてるはずだから。。。 cout << "ゴール!おめでとう!" << endl; 追加: さいころがピッタリじゃないとゴールできない 進めなかったり、戻ったりを追加 * ゲームとして考えてみると、すごろくはゲーム開始後必ず一度はサイコロを振って駒を進める処理を行う * 。。。という事は、前判定?後判定?どちらが適していますか? * 応用として、今回盤面の表示は、初期盤面と、ゲーム中の盤面表示と、同じループブロックを2回も書きました * 現代的なプログラムでは同じことを2回書くのは無駄とされています。 * こんな時はどうすればいいのか調べてみよう