○×ゲームを作る (2) 2次元配列を使う

さて、前回で○を描けるようになりました。ですが、前回の段階では、どこに○が描かれているかについての情報はどこにも保存されていませんでした。この情報は今後、リーチや勝敗の判定をおこなう時に必要になりますので、この機能を作っていきます。今回は、2次元配列を使います。

配列を使うと、データを列のようにつなげて一度に複数つくることができます。
Processingでは、例えば “map”  という名前の整数の(1次元の)配列を以下のように作成できます。

int map[];

これを2次元にしたい場合、[] をもう一つ加えます。

int map[][];

2次元配列を使うと、縦○マス×横○マスの表のようなかたちでデータを作ることができます。○×ゲームでは、3×3の9マスが必要ですので、それに合わせて3×3の2次元配列を作ります。

上記の2次元配列において、最初の値(初期値)をあらかじめ 1 としておきたい場合は、以下のようにします(初期値は0でもよいのですが、後から掛け算で計算をしたいと考えています。初期値を0にしてしまうと、何をかけても解が 0 になってしまいますので、ここでは 1  としておきました)。

int map[][] = {{1,1,1}, {1,1,1}, {1,1,1}};

なお配列では、最初の値は「 0 番目」として数えます。値が3つある場合は、0 番目から、1 番目、2 番目、と数えます。「3 番目」の値は存在しないので注意してください。
おや、この 0, 1, 2 という数には見覚えがありますね。前回、○を描いたマスの場所を示すための X, Y という変数(値を入れておく箱)を用意していました。X は左から何番目(横の位置)、Y は上から何番目(縦の位置)を表しています。X, Y の値はちょうど、0, 1, 2 になっていました。この X, Y を使って、○を描いた場所の値を 2 に上書きするようにしましょう。

map という名前の2次元配列において、 X, Y の個所を 2 に上書きしたい場合、以下のように記述します。一つ目の括弧の中に Y を、二つ目の括弧に X を書きます。

map[Y][X] = 2;

この時、map[X][Y] と X を先に書いてしまいそうになります。今回の例では、プログラム全体で書き方を統一すればこのように記述しても問題ありません。そのように記載している本もあります。しかし、それは縦と横の要素数が同一であるためです。縦と横の要素数が異なる場合は問題が発生します。ためしに 横3 × 縦5 の縦と横の要素数が異なる二次元配列を用意し、右下の値(0)を表示させたいとします。

int map[][]={{1,1,1}, {1,1,1}, {1,1,1}, {1,1,1}, {1,1,0}};
void setup(){
  size(100, 100);
}
void draw(){
  text(map[2][4], width/2, height/2); // map[X][Y]と書く
}

すると、ArrayIndexOutOfBoundsException: (行番号) というようなエラーが表示されます。これは、横は 0 から 2 番目、縦は 0 から 4 番目までのデータしかないのに、その範囲の外を参照しているよ!という意味です。これを map[4][2] と修正するとエラーは解消されます。

さて、ここまでのコードをまとめると以下のようになります。見た目は前回までと変わりません。

int X, Y;
int map[][] = {{1,1,1}, {1,1,1}, {1,1,1}};

void setup(){
  size(600, 600);
  background(255);
  line(0, 200, 600, 200);
  line(0, 400, 600, 400);
  line(200, 0, 200, 600);
  line(400, 0, 400, 600);
}

void draw(){
  if(mousePressed){
    X = mouseX / 200;
    Y = mouseY / 200;
    fill(255);
    ellipse(X*200+100, Y*200+100, 150, 150);
    map[Y][X] = 2;
  }
}

 

次に、ステージ上で何も描かれていないときだけ○を描いていい、と制約を加えたいと思います。これを判定するためには、map上の値が 1 の時だけ○を描ける、というふうにすればOKです。こうすることで、すでに○または×がある個所をクリックしても記号が重ねて描かれないようにします。

if(mousePressed){
  X = mouseX / 200;
  Y = mouseY / 200;
  if(map[Y][X] == 1){
    fill(255);
    ellipse(X*200+100, Y*200+100, 150, 150);
    map[Y][X] = 2;
  }
}

 

ではまた次回~

Leave a Reply

Your email address will not be published. Required fields are marked *