Garbage Collection

塵も積もれば山

目次

Blog 利用状況

ニュース

C++とかC#とか数学ネタを投下していく予定です。

[その他のページ]
日々の四方山話を綴った日記出水の日記帳

書庫

日記カテゴリ

[C#]forever for

IEnumrableが使えば使うほど楽しいです。

例としてマインスイーパーを作るとします。

class Cell{
  public bool isMine();
}

class Field{
  public Cell GetCell(int x, int y){
    if (x < 0 || maxx <= x) return null;
    if (y < 0 || maxx <= y) return null;
    return cell[x,y];
  }
}

GetCellでセルクラスを取得できますが、範囲外を取得しようとするとnullを返します。
isMine()は爆弾がセルにあればtrue,なければfalseを返します。

こういうとき、周りの8マスを調べて爆弾の値をとりたい、と考えるとどう書けばいいでしょうか。

class Field{
  public IEnumrable<Cell> Get8Round(int x, int y){
    yield return GetCell(x - 1, y - 1);
    yield return GetCell(x    , y - 1);
    yield return GetCell(x + 1, y - 1);
    yield return GetCell(x - 1, y    );
    yield return GetCell(x + 1, y    );
    yield return GetCell(x - 1, y + 1);
    yield return GetCell(x    , y + 1);
    yield return GetCell(x + 1, y + 1);
  }
  
  public int GetMineNum(int x, int y){
    return Get8Round(x, y).Count(l => l != null && l.isMine());
  }
}

今回の肝は8近傍を返す関数というところにあります。
中身は泥臭い方法で実装していますが、一度作ってしまえばこれを使いまわせます。

周り8マスの集合を作り、nullでなくてisMine()がtrueの個数、という風に
頭で思いついた通りに打つだけでその通りにできるうえ、
インデックスやカウンター用の変数が出てこなくて済む、というのはありがたいです。

考えてみれば、for文を絡む部分はモジュール化しにくい部分でした。
8近傍を取る部分が出てくるたびにどこかにあるforをコピペして使っていました。
また、そのためにoffsetx[8], offsety[8]というものをグローバル領域に取ったりもしていました。

正直、for文というのは可読性がよくないように思います。
yieldを使えば簡単にモジュール化できるうえ、IEnumrableに便利な関数が増えているので、
for文をあまり使わないコーディングスタイルもありではないでしょうか。

投稿日時 : 2009年2月12日 22:00

Feedback

# re: [C#]forever for 2009/02/12 23:02 まさる

しかもLINQもありますものね。ますますfor文を書く機会が少なくなりそうです。

エントリ内のGetMineNumを、LINQを使ってやるとこんな感じですかね。

 public int GetMineNum(int x, int y){
  var q = from cell in Get8Round(x, y)
   where cell != null && cell.IsMine
   select cell;
  return q.Count;
 }

# re: [C#]forever for 2009/02/13 8:56 出水

LINQ構文、今までのC#にない構文なのですぐ忘れるし、
これでないと書けない構文もなさそうなので個人的には必要ない気がします

直積集合とか作れたりするんですかね?

# re: [C#]forever for 2009/02/13 9:08 まさる

>直積集合
こういうことですか?

[コード]
 int[] arrA = { 1, 2, 3 };
 int[] arrB = { 4, 5, 6 };

 var q = from a in arrA
     from b in arrB
     select String.Format("{0},{1}", a, b);

 q.ToList().ForEach(Console.WriteLine);

[結果]
 1,4
 1,5
 1,6
 2,4
 2,5
 2,6
 3,4
 3,5
 3,6

# http://suglobo.com/ 2009/05/18 23:45 Appotodychosy

Questions and answers about Wholesale cell phone and Bjs wholesale club. http://suglobo.com/

# Illikebuisse sessj 2021/07/04 16:58 pharmacepticacom

does erectile dysfunction ever go away https://pharmaceptica.com/

# chloroquine malaria tablets 2022/12/25 11:13 MorrisReaks

https://www.hydroxychloroquinex.com/# hydroxychloroquine where to get it

タイトル
名前
Url
コメント