Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

座標あてゲームを開発したい!

Posted at

はじめに

この記事では「座標あてゲーム」という推測ゲームを開発するまでに至る経緯、開発手順について説明していきます。筆者は超初心者であるため、優しい目で見ていただけるとありがたいです。

座標あてゲームの内容

このゲームはコンピュータが一定範囲内でランダムに選んだ座標を、プレイヤーが少しづつ範囲を限定して突き止めていくというものです。
まず座標をランダム決定後、プレイヤー最初のヒントをもとに座標を入力します。その座標に対して正誤判定をし、繰り返すことで値を絞りアンサーとなる座標を最終的に特定します。

作成してみる

乱数を生成する

これは乱数を生成するプログラムです。

#include <stdlib.h>
#include <time.h>

int r[3];

void random_point(void) {
    srand((unsigned int)time(NULL));

    for (int i = 0; i < 2; i++) {
        // 最小値:-20 取得個数:41個
        r[i] = -20 + rand() % 41;
    }
}

それぞれがどういった意味を持つか細かく分けて解説しましょう。

1.乱数生成の標準ライブラリ関数

#include <stdlib.h>
#include <time.h>

void random_point(void);
    srand((unsigned int)time(NULL));

これは乱数生成に必要な標準ライブラリ関数です。random_point関数はRAND_MAX(VisualStudioでは0x7fff)まで、すなわち「0~32767」の範囲で乱数を得る関数となります。

ただし、これだけでは乱数生成の元となる種が同じため毎回同じ値を生成してしまうため種の値も変えていく必要があります。そこでもう一つの関数を使っていきましょう。

2.時刻の利用

srand関数は乱数の種を指定するコードです。今回は時刻を利用したため引数を time(NULL) としました。

この引数はtime関数であり、C言語において時刻を取得する標準ライブラリ関数です。

ここで引数を時刻にした理由を説明しましょう。先ほど乱数の種を変えることの必要性を述べましたが、その乱数の種にも規則性があってはなりません。そのため乱数を延々と追っていくことになり、それは無限に続いて行ってしまうことになります。そこで、着目するのが時刻情報です。時刻は常に変化して定まることはないため乱数生成に生かせるのです。

3.乱数の範囲を設定する

for (int i = 0; i < 2; i++) {
        // 最小値:-20 取得個数:41個
        r[i] = -20 + rand() % 41;
    }

このプログラムでは「-20~20」の範囲で乱数を生成します。最小値-20から最大値20までの41個の値をとるということが理解できれば、「-20」と「41」の部分を変えるだけで自由に範囲を変えることが可能です。

あとは生成した値を座標にそれぞれ当てはめていくだけですね。

int a, x, y, x1, x2, x3, y1, y2, y3, s, t;

    // アンサー座標のランダム設定
    random_point();
    x = r[0];
    y = r[1];

    // 周囲の座標3つをさらにランダム設定
    random_around();
    x1 = r[0] + x;
    x2 = r[1] + x;
    x3 = r[2] + x;
    y1 = r[3] + y;
    y2 = r[4] + y;
    y3 = r[5] + y;

メインの乱数生成については以上です。ここから後は文章の表示と判定です。

ゲームの流れ

スタート画面

// スタート画面
    puts(
        "座標ゲーム!\nアンサーとなる座標の周辺の異なる座標(x,y方向にそれぞれ-20~+20の範囲内)を3つ表示します。"
        "これをヒントにアンサーの座標を答えよ。");
    do {
        printf("ゲーム開始なら1(半角)を入力せよ: ");
        scanf("%d", &a);

        // ゲームスタートと同時に上の座標3つを表示

        if (a == 1) {
            printf("( %d,%d )と ( %d,%d ) と ( %d,%d ) \n", x1, y1, x2, y2, x3,
                   y3);
            break;
        }
    } while (a != 1);

出力:

座標ゲーム!
アンサーとなる座標の周辺の異なる座標(x,y方向にそれぞれ-20~+20の範囲内)を3つ表示します
。これをヒントにアンサーの座標を答えよ。
ゲーム開始なら1(半角)を入力せよ: 2
ゲーム開始なら1(半角)を入力せよ: 0
ゲーム開始なら1(半角)を入力せよ: 1
( 8,-25 )と ( 13,-29 ) と ( 25,-20 ) 
x座標: 

1(半角)が押されれば、周辺の座標3つを表示します。

判定

// 座標入力・判定
    do {
        printf("x座標: ");
        scanf("%d", &s);
        printf("y座標: ");
        scanf("%d", &t);

        // 判定
        if (s == x && t == y) {
            puts("perfect!!");
            break;
        } else if (s == x && t != y) {
            puts("x座標〇,y座標✕    あとはy座標!\n");
        } else if (s != x && t == y) {
            puts("x座標✕,y座標〇    あとはx座標!\n");
        } else {
            puts("x座標✕,y座標✕    回数こなせばいける!\n");
        }
    } while (s != x || t != y);

出力:

x座標: 15
y座標: -26
x座標✕,y座標✕    回数こなせばいける!

x座標: 16
y座標: -23
x座標〇,y座標✕    あとはy座標!

x座標: 16
y座標: -27
x座標〇,y座標✕    あとはy座標!

x座標: 16
y座標: -20
perfect!!

繰り返しのプログラムを使った非常に簡単なものです。難しいところはないはず。

さいごに

無知の状態から始めたが、乱数の生成方法についての理解が深まる良い機会になりました。今回は平面上で文字だけの情報になってしまいましたが、ここから更に空間バージョンも増やして難易度の幅を広げていきたいです。そして座標が視覚化できるようにすることもゲームをやりやすくするために必要ですから、改良をこれからも進めていく予定です。
もっと簡単にできるプログラムもあったでしょうが、これからの成長に期待!ということでどうぞよろしくお願いします。

さあ!明日は最終日!

参考にさせていただいたサイト

0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?