「Enum」を含む日記 RSS

はてなキーワード: Enumとは

2014-06-04

http://anond.hatelabo.jp/20140604161616

途中で編集してトラバ先を変えた?まあいいけど

否定派は三つならenumにするんじゃなかったんすか?

3つだからenumってことはなく、2つでenum、定数値だって問題ないよ。

bool?だって「true,false,null許容」が最適なら使われるべきだよ。

ただstate A,B,Cの3つを表現するのに、bool?が3値とれるからって理由で

trueはA, falseはB, nullならCみたいに本来の意味を変えて使うのはいかんな。

個人で書くコードならなんでもいいけど。

http://anond.hatelabo.jp/20140604161945

うーん、いまいちbool?否定派の意見わからん

「外部結合するフラグ値」をC#表現したいとき、どうして、enumを使わないといけないんだ?(true,false,nullしか入らないんだぜ)

bool?の方がお手軽で楽チンじゃん、定義を見れば一目で分かるし。

それをユーザー定義定義解釈するかどうかは、プログラム側の問題であって、3つ以上増えない「外部結合のフタグ値」を、bool?で定義した方が分かりやすいだろ。

http://anond.hatelabo.jp/20140604161616

すでにそうなっているものに文句を言ってもしょうがないだろ。

どうでもいいけど

Nullableの説明で

通常、値型は null 値(無効な値)を取れません。

http://ufcpp.net/study/csharp/sp2_nullable.html

とあるけど そもそも double型などはそもそも値だけではなく最初からNaNが使える。

数値とNaNの併用が可能な型。(Cの場合というのがある。)

まり用途に応じてEnumだったりdoubleだったりオブジェクトだったりを使い分ければいい。

フォーム型なんかの場合は元々オブジェクト指向になっていて、中身の実装がポインタポインタ=NULL とポインタ=BooleanObjectという実装だから出来る話。

ちなみに、未設定をCでやる場合enumではなく、ビット演算子を使うことになるかとは思う。3値ならenum C#ならNULLABLEでもいいんじゃね?

http://anond.hatelabo.jp/20140604161431

http://anond.hatelabo.jp/20140604153229

あれ、bool?否定派は三つならenumにするんじゃなかったんすか?

http://anond.hatelabo.jp/20140604154102

俺も横だから、ココにトラバつけるわ。

C#触ったことなから知らなかったけど、bool?(null 許容型)てのがあるんだね。

MSDNみてみたけど http://msdn.microsoft.com/ja-jp/library/1t3y8s4s.aspx

数値型と Boolean 型に null を割り当てる機能が便利なのは、値を割り当てられていない可能性がある要素を含むデータベースや他のデータ型を処理するときです。 たとえば、データベースの Boolean フィールドには、値 true または false を格納するか、未定義にすることが可能です。

ってことがnull許容型の理由みたいね

bool? であれば3つの状態を表すことができるかもしれないけど、やっぱりboolはtrueかfalseだよ。

MSDNにある通り、nullを許容するとしてもね。

3つ以上の状態を作りたいなら、それこそenumでもなんでも使えばいい。

bool?で宣言されてる変数を追って行って「3つの状態保持のために使ってまーす」ってコード見たら

ハァ?(゚Д゚) ってなるわ。nullはnullよ。

http://anond.hatelabo.jp/20140604155608

そういうのこそ、enum を使いたまえ、キミ!

http://anond.hatelabo.jp/20140604153229

>状態が3つになった時点でenumのほうがいいじゃん。

状態が四つ以上になることはありえないんだから、bool?の方が手間が省けていいじゃん。

これが、増える可能性があるようなものだったら、君の意見に賛成するけど。

http://anond.hatelabo.jp/20140604152234

状態が3つになった時点でenumのほうがいいじゃん。

ドライバ仕様でbool?が返ってくるとしたら定数にして

if(人事画面使えるかどうかフラグ == AVAILABLE)
「使えるよ! 開くよ!」
else if(人事画面使えるかどうかフラグ == UNAVAILABLE)
「権限がないから開けないよ!」
else if(人事画面使えるかどうかフラグ == UNDEFINED)
「ユーザーグループが未定義だよ!」

みたいにしたい

http://anond.hatelabo.jp/20140604133746

null=どちらでも良い

自明じゃないと言いたいんだ。どちらも駄目、とか不明、とかかもしれないし。

enumのほうが優れてると言いたいんだ。

1人で作るプログラムなら好きにすりゃいいが、仕事で書くプログラムは優れたやり方で統一したい。

2014-03-04

http://anond.hatelabo.jp/20140304185035

何の言語かしらないが、正しい定義を書けよ


const MODE_VIEW = 1;
const MODE_PRINT = 2;
const MODE_DOWNLOAD = 3;

/* 表示モード */
const MODE_1 = 1;

/* 印刷モード */
const MODE_2 = 2;

/* ダウンロードモード */
const MODE_3 = 3;

というか Cだと

enum ENUM_Mode{
    MODE_NONE=0,
    MODE_VIEW,
    MODE_PRINT,
    MODE_DOWNLOAD,
};

enumになってないと デバッガーで追い切れない?

※使わなくても、NONEは作って0にしておくのは小技

※MODE_DOWNLOADは 和訳すれば ダウンロードモード(和訳なのか?)なのでコメントを書く必要性がそもそも無い。

 

なんつーか、コメント日本語を使うな!がコメント上達への第一歩だと思う。

2013-07-02

わーい、今日からやっと配属だという初日に、エクリプス環境設定で一人やらかす。

手順書読み飛ばしてた自分が悪いんだけど、ビルドが通らない理由が切なかった

enumの文字がエラーメッセージに表示されて、そういえばJava先生に、

昔のjavaってenumは使えなかったんだ、みたいな小話を聞いたのを思い出して

あ、コンパイラー設定かも..と見直したらJREバージョンが新しいままになってた(といっても1.6だけど)。

この新人大丈夫かな、って周囲の目もきつかったが、ボロい開発環境もひいたし、

もう、なんか疲れた。やってけるのかな。

2013-03-03

http://anond.hatelabo.jp/20130303135038

Java学習コストが低くHaskell学習コストが高い」みたいな話をよく見るけど、本当なのかねぇ。

初期のJavaならともかく、AutoBoxingの落とし穴とかワイルドカードの正しい使い方とか、

強力なenumの使い方とか、色々入ってる今のJavaがそこまで簡単には思えない。

機能豊富さというより機能抽象度の高さが問題ってことなのかな。

2011-01-09

http://anond.hatelabo.jp/20110109000805

最近は、24インチ 30インチディスプレイなんて安いんだから、横80ではなく横120ぐらいは平気で使える。

classname::enumname という毎回指定でも エディタインテリジェントに保管してくれるから問題ない。

個人的には、毎回、スコープを明示して欲しい

 

基本的に 外部ツールがチェックしてくれるんだから

class{

enum{

{

};

で問題ないと思われ

言い方を変えれば、class内部以外でenum定義することなんて最近はあるのか?グローバルなenumなんて余り無いと思うが・・・

クラス内部では、省略できるし、外部からクラス内部の値を呼ぶときは、どのクラスのこのenumって外部だよって意味で毎回書いたほうが安全だろ?

 

スコープの省略は基本、オススメできない。

using namespace std

ですら、書かないほうが安全 毎回std::って書かないと、うっかり、stringクラス定義する人がいないとは限らんからね・・・

一斉に変更したい? エディタ正規表現で置換すればよろしい・・・

 

原則、外部のツールで解決できる問題は、外部のツールで解決すればいい。

言語仕様拡張されると、初心者に、その理屈を説明するという問題が出てきて、そういうのは初心者には無理。

他方、ツールを使えない初心者でも、毎回コピペや手で置換は出来る。

 

ソーシャルな人を使うという観点から、そういう言語拡張オススメできない。

2010-07-24

google発のProtocol Buffersについて

オブジェクトシリアライズツールであるプロトコルバッファについて書きます。

プロトコルバッファって何って方はこちらへ

Protocol Buffers 本家

http://code.google.com/apis/protocolbuffers/

XMLはもう不要!? Googleシリアライズツール「Protocol Buffer」

http://journal.mycom.co.jp/articles/2008/07/18/protocolbuffer/index.html

Protocol Buffers (Protocol Buffers の内部解説記事。とても参考になります)

http://dodgson.org/omo/t/?date=20080712

内容

プロトコルバッファは異種言語間でオブジェクトのやりとりをするための規格です。

独自の言語によりオブジェクトインターフェースを規定することで、多言語対応を行っています。

例えばこんな感じ。

  • address.proto
package tutorial;

message Person {
  required string name = 1;
  required int32 id = 2;        // Unique ID number for this person.
  optional string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }

  repeated PhoneNumber phone = 4;
}

// Our address book file is just one of these.
message AddressBook {
  repeated Person person = 1;
}

以上のようなprotoファイルから各言語ソースコード、または何らかのデータ操作ライブラリを使いオブジェクトの処理を行います。

googleによってC++, Java, Python用のライブラリ作成されましたが、他の言語対応したサードパーティー製のライブラリがいくらでもあるので、実質的にほぼすべての言語で使えると言っても過言ではありません。

以下はこのライブラリを使ってみた感想などです。

整数型はVarintという可変長型でバイナリに保存される

数字が多きければ大きいほど、長いバイト長で保存されます。ただし、負数の場合符号ビットが立つ関係で、ほとんど常に変換後のバイト数が最長バイト数(10)になってしまいます。フィールドの型をsint32, sint64で宣言しると、各数値にzig-zags変換が行われるため、負数であってもその値の絶対値で使用バイト数が決まるようになります。

保存されるデータは各メッセージID/型/値のみ

バイナリに保存されるデータは各メッセージID/型/値のみです。なので、同じ定義の二つのメッセージ型は、プロトコルバッファ上では全く同じように扱うことが出来ます。例えば、片方からシリアライズしたデータを、もう片方の型でデシリアライズすることが可能です。

またオブジェクト連続シリアライズ/デシリアライズすることもできます。

継承されたクラスマッピング

すでに存在する継承関係のあるクラスを、Protocol Buffersでシリアライズ/デシリアライズしたい場合は次のようにします。

(Base, Derived はすでに存在するとします)

(ソースコード中になぜか日本語が書けないので、コメントはすべて英語になっています)

message PbBase {
        require int32 id = 1;
        require int32 value = 2;

        require Derived derived = 10; // - Point !!!
}

message PbDerived {
        require string string_value = 1;
}

継承元のメッセージ定義に、継承先のメッセージを持たせます。Base継承するクラスシリアライズ/デシリアライズしたい場合は、PbBaseメッセージを中心に処理を行うことで、比較的簡単に処理を実装することが出来ます。

例えばこんな感じ

Base *Base_DeserializeFrom(PbBase &pbobj)
{
    // Arrange the classes which inherits from Base.
    if (pbobj.has_derived()) {
        return new Derived(pbobj);
    }
    else
    ...
}

class Base {
    ...
    virtual void Base::SerializeTo(PbBase &pbobj) {
        // Set the fields of 'pbobj',
    }
    ...
};

class Derived {
    ...
    virtual void Base::SerializeTo(PbBase &pbobj)
    {
        PbDerived *derived = pbobj.mutable_derived();

        Base::SerializeTo(pbobj);
        // Set the fields of 'derived',
        ...
    }
    ...
};

protoファイルを以下のように書くと、メッセージの扱いが非常に難しくなります。

message PbBase {
        require int32 id = 1;
        require int32 value = 2;
}

message PbDerived {
        required PbBase base = 1; // - Here is the point !!!
        require string string_value = 2;
}

2008-10-30

http://anond.hatelabo.jp/20081025202001

いまさらだがFizzBuzz

1から100まで、3の倍数5の倍数云々って、全部定数の計算じゃね?

というところに気付き、自称メタプログラマー(略してメタグラマー)俺の血が騒いだ。

定数計算なら、それは実行時ではなくコンパイル時に行なわれるべきだ……。

というわけでC++テンプレートメタプログラミング召喚。

#include <iostream>

const int FIZZ_NUM = 3;
const int BUZZ_NUM = 5;
const int BEGIN_NUM = 1;
const int END_NUM = 101;

template<int N> struct Fizz {
    enum {PRINT = 0, NEXT = N + 1};
    static void print() {}
};

template<int N> struct Buzz {
    enum {PRINT = 0, NEXT = N + 1};
    static void print() {}
};

template<int N, bool ForB> struct Number {static void print() {std::cout << N;}};

template<> struct Fizz<FIZZ_NUM> {
    enum {PRINT = 1, NEXT = 1};
    static void print() {std::cout << "Fizz";}
};

template<> struct Buzz<BUZZ_NUM> {
    enum {PRINT = 1, NEXT = 1};
    static void print() {std::cout << "Buzz";}
};

template<int N> struct Number<N, true> {static void print() {}};

template<int N, int F, int B> struct FizzBuzz {
    static void print() {
        typedef ::Fizz<F> Fizz;
        typedef ::Buzz<B> Buzz;
        
        Fizz::print();
        Buzz::print();
        Number<N, Fizz::PRINT || Buzz::PRINT>::print();
        std::cout << std::endl;
        
        FizzBuzz<N + 1, Fizz::NEXT, Buzz::NEXT>::print();
    }
};

template<int F, int B> struct FizzBuzz<END_NUM, F, B> {static void print() {}};

int main(int argc, char **argv)
{
    FizzBuzz<BEGIN_NUM, 1, 1>::print();
    return 0;
}

ifなし%なしループ系なし、しかも実行時オーバーヘッドなし!(多分)

あ、これを見て理解する人間オーバーヘッドは無視ね。

ああ、久しぶりにC++を触ったけど、やっぱC++テンプレートってダメダメだな。20世紀の遺物といわざるを得ない。

君がもし21世紀モテイケメンメタグラマーなら、21世紀プログラミング言語D言語を使うべきだ!

驚くべきことに、D言語コンパイル時に関数が実行でき、その結果をソースコードとして取り込める!

ただし実行できるのは簡単な関数だけだけど……。

以下、それを使ったD言語によるメタプログラミング的実装。

import std.stdio;

// これでFizzBuzzを全部出力するコードを作るぜ!
string makeFizzBuzzCode() {
    string code;
    for(int i = 1; i <= 100; ++i) {
        // 効率? コンパイル時にそんな配慮は要らん!
        if(i % 3 == 0 &amp;&amp; i % 5 == 0) {
            code ~= "writefln(\"FizzBuzz\");\n";
        } else if(i % 3 == 0) {
            code ~= "writefln(\"Fizz\");\n";
        } else if(i % 5 == 0) {
            code ~= "writefln(\"Buzz\");\n";
        } else {
            code ~= "writefln(" ~ static_itoa(i) ~ ");\n";
        }
    }
    return code;
}

int main(string[] args) {
    // おまけで生成されたコードも見せるよ。
    pragma(msg, makeFizzBuzzCode());
    
    // 生成したコードを埋め込む。コピペみたいな感覚
    mixin(makeFizzBuzzCode);
    return 0;
}

// 以下ユーティリティ。このぐらい標準で欲しいな……。

/// 整数文字列変換(コンパイル時)
string static_itoa(int n) {
    if(n == 0) {
        return "0";
    }
    
    // 10で割りながら余りを文字にして追加。桁が逆転した文字列になる。
    string s;
    for(; n; n /= 10) {
        s ~= ("0123456789")[n % 10];
    }
    
    // 桁位置を正常にする。相変わらず効率無視。
    return static_reverse(s);
}

/// 配列リバースコンパイル時)
/// 実行時ならarray.reverseが使えるんだけどね……。
T[] static_reverse(T)(T[] s) {
    T[] result;
    foreach_reverse(c; s) {
        result ~= c;
    }
    return result;
}

// 心配なので静的ユニットテスト(笑)
unittest {
    static assert(static_itoa(0) == "0");
    static assert(static_itoa(10) == "10");
    static assert(static_itoa(999) == "999");
    static assert(static_itoa(9999) == "9999");
    static assert(static_itoa(12345) == "12345");
    static assert(static_itoa(314159265) == "314159265");
}

コンパイル結果

$ dmd -unittest fizz_buzz.d
writefln(1);
writefln(2);
writefln("Fizz");
writefln(4);
writefln("Buzz");
writefln("Fizz");
writefln(7);
writefln(8);
writefln("Fizz");
writefln("Buzz");
writefln(11);
writefln("Fizz");
writefln(13);
writefln(14);
writefln("FizzBu(ry

出力結果は略。

さすがD言語C++JavaC#にできない事を平然とやってのけるッ

そこにシビれる!あこがれるゥ!

というか、

writefln(1);
writefln(2);
writefln("Fizz");
writefln(4);

もうwritefln(出力関数)要らなくね?

修正。

// これでFizzBuzzを全部出力するぜ!
string makeFizzBuzzCode() {
    string code;
    for(int i = 1; i <= 100; ++i) {
        // 効率? コンパイル時にそんな配慮は要らん!
        if(i % 3 == 0 &amp;&amp; i % 5 == 0) {
            code ~= "FizzBuzz\n";
        } else if(i % 3 == 0) {
            code ~= "Fizz\n";
        } else if(i % 5 == 0) {
            code ~= "Buzz\n";
        } else {
            code ~= static_itoa(i) ~ "\n";
        }
    }
    return code;
}

int main(string[] args) {
    // もうコンパイル時のメッセージしか出さない。(笑)
    pragma(msg, makeFizzBuzzCode());
    return 0;
}

コンパイル結果。

$ dmd -unittest fizz_buzz.d
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBu(ry

実行するまでもなく結果が出力された。つまり実行時間ゼロ、ということは……

世 界 最 速

以上、世界最速なD言語宣伝でした。

みんな使おうD言語

D言語リファレンス日本語

http://www.kmonos.net/alang/d/1.0/index.html(1.0。こっちの方が安定してる?)

http://www.kmonos.net/alang/d/2.0/index.html(もっと凄い2.0)

D言語本家配布元(無料コンパイラが入手できます)

http://www.digitalmars.com/

それにしても、ちゃんとD言語シンタックスハイライトを実装しているはてなは偉い。(笑)

2008-08-31

http://anond.hatelabo.jp/20080831170515

日常会話でコードなんて口にするわけないだろwww馬鹿かww

プログラマ同士の会話だったらコードを口にすることもあるし

物理数学周りの人間同士だったら微分方程式で会話することもあるが

一般人の前でそれをやるわけがない。そんなことしても意味がない。

http://anond.hatelabo.jp/20080831165936

ところで、

gotoを使うのはいいんだろうか…。

HumanクラスLifeメソッドということで

typedef enum{
HAPPY_END,
BAD_END
}END_OF_LIFE

とかやった上で

return HAPPY_END

とかの方がいいかなと思いますが。ペーペーですが。

2008-08-29

http://anond.hatelabo.jp/20080829041925

javaなんておさわりでしか触ったことが無いけど、どれもわからん。面接とおらんわw

Enum と 可変長引数 はなんとなく察せられるが、拡張for構文 はなんのこっちゃ?

http://journal.mycom.co.jp/column/java/016/index.html

for (int target : integers) {

これをみるかぎり、foreachみたいなもんか?

可変長引数はみてみたが、Javaみたいにチームで開発するんだったらまあいいんじゃないかな。

基本設計をするひとがうんこだと全員死ねるけど。

http://www.stackasterisk.jp/tech/java/jdk505_01.jsp

C#の可変個引数地獄に落ちたほうがいいとおもうけど。

http://anond.hatelabo.jp/20080824080254

特に、Java 5以降の機能

辺りを全く知らなかったり。

Java触ったことないけど、可変長引数なんて追加実装してるんだ。

可変長引数なんて諸悪の根源です><空気かと思ってたけど、

言語によって状況はだいぶ違うのね。

2008-08-24

経験年数2年半のJavaプログラマがちょっと書くよ。

はてな界隈では、Javaって、あんま人気無いみたいだけど、ちょっと書かせてよ。

SIerお仕事してると、派遣とか常駐とか言う形で、色んな会社に行って、違う会社の人とお仕事するんだけど、「経験年数n年(n>3)です」っていう人達が、恐ろしく使えなくてびっくりすることがしばしば。

特に、Java 5以降の機能

辺りを全く知らなかったり。 って言うか、Javaの極々基本的な知識である

  • equals/hashCodeの実装
  • Serializableの実装
  • Iteratorの実装

が全く出来ないんだよね…。

そういうのを知らなくても(出来なくても)業務をこなせちゃう(?)のが、Java言語特性だとは思わないけど、こういう人達だらけなんだよね…。 PMが新しい人を採用しようとして、ここら辺の知識を割りと厳し目にテストしたら、候補が10人居たのに全滅で、プロジェクトスタートが遅れてしまったりして、もう大変。

他人のJavaスキルを知るために、自分がする質問は

  • Interfaceって何のためにあるんですか?
  • ListやMapループで回して値を取る時Iterator使うのは何故?
  • staticなメソッドを作るときはどんな時?

かな。

2008-01-11

enum {
    ERROR,
};

で引っかかって一時間時間無駄にしちゃった……。

2007-07-12

迷路成プログラムVC++2005でやってみた。

http://anond.hatelabo.jp/20070711013155 こちらの宿題を作ってみました。

http://anond.hatelabo.jp/20070711080519 で参加を宣言した者です。

#include "stdafx.h"
#include <time.h>
#include <conio.h>
#include <list>

using namespace std;

enum MMError {
	MME_None = 0,
	MME_SizeError,
	MME_MemoryAllocError,
	MME_NotInitialized,
};

enum MMKind {
	MMK_None = 0,
	MMK_Space,		// 通路
	MMK_Filled,		// 埋まってるところ。掘れる。
	MMK_Wall,		// 壁。掘れないところ。
};

//
// 迷路実体管理用クラス定義
//
class CMazeMatrix
{
public:
	CMazeMatrix();
	virtual ~CMazeMatrix();

public:
	virtual bool	Initialize(int nXSize, int nYSize);	// 初期化すると同時に、外壁まで作ってしまう。
	virtual MMKind	GetAt(int nXPos, int nYPos);
	virtual bool	SetAt(int nXPos, int nYPos, MMKind kind);

	MMError	GetLastError() {return m_lastError;}


protected:
	inline	int calcIndex(int nXPos, int nYPos) {return nYPos * m_nXSize + nXPos;}
	bool	finalize();

protected:
	MMKind	*m_pMaze;
	int		m_nXSize;
	int		m_nYSize;

	MMError	m_lastError;
};

//
// 実体管理用クラス実体
//
CMazeMatrix::CMazeMatrix()
{
	m_pMaze = NULL;
	m_nXSize = 0;
	m_nYSize = 0;
	m_lastError = MME_None;
}

CMazeMatrix::~CMazeMatrix()
{
	finalize();
}


bool CMazeMatrix::Initialize(int nXSize, int nYSize)
{
	finalize();

	int nSize = nXSize * nYSize;
	if ((__int64)nSize != (__int64)nXSize * (__int64)nYSize) {
		m_lastError = MME_SizeError;
		return false;
	}
	m_pMaze = new MMKind[nSize];
	if (m_pMaze == NULL) {
		m_lastError = MME_MemoryAllocError;
		return false;
	}

	m_nXSize = nXSize;
	m_nYSize = nYSize;

	int nCnt;
	for (nCnt = 0; nCnt < nSize; nCnt++) 
		m_pMaze[nCnt] = MMK_Filled;

	for (nCnt = 0; nCnt < m_nXSize; nCnt++) {
		m_pMaze[calcIndex(nCnt, 0)] = MMK_Wall;
		m_pMaze[calcIndex(nCnt, m_nYSize - 1)] = MMK_Wall;

	}

	for (nCnt = 0; nCnt < m_nYSize; nCnt++) {
		m_pMaze[calcIndex(0, nCnt)] = MMK_Wall;
		m_pMaze[calcIndex(m_nXSize - 1, nCnt)] = MMK_Wall;
	}
	return true;
}

MMKind	CMazeMatrix::GetAt(int nXPos, int nYPos)
{
#ifdef _DEBUG
	if (nXPos < 0 || nXPos >= m_nXSize ||
		nYPos < 0 || nYPos >= m_nYSize)
	{
		m_lastError = MME_SizeError;
		return MMK_None;
	}
#endif
	return m_pMaze[calcIndex(nXPos, nYPos)];
}

bool	CMazeMatrix::SetAt(int nXPos, int nYPos, MMKind kind)
{
#ifdef _DEBUG
	if (nXPos < 0 || nXPos >= m_nXSize ||
		nYPos < 0 || nYPos >= m_nYSize)
	{
		m_lastError = MME_SizeError;
		return false;
	}
#endif
	m_pMaze[calcIndex(nXPos, nYPos)] = kind;
	return true;
}

bool	CMazeMatrix::finalize()
{
	if (m_pMaze != NULL) {
		delete [] m_pMaze;
		m_pMaze = NULL;
	}
	return true;
}


//
// 迷路作成用クラス定義
//
class CMazeMaker
{
public:
	CMazeMaker();
	virtual ~CMazeMaker();

public:
	bool	Initialize(int nXSize, int nYSize);

	// 力業。ループで回す。メモリは食わない。
	// 美しくない。
	bool	Generate1();

	// 掘った箇所をスタックに積んで、掘れなくなったらスタックを戻す。
	// 綺麗だけれど、迷路のサイズを増やすとスタックオーバーフローが起こる。
	bool	Generate2();

	// Generate2をlistに置き換えたもの。
	// stdを使ってしまったのが心残り。
	bool	Generate3();

	MMError	GetLastError() {return m_lastError;}

protected:
	bool	finalize();
	bool	checkPos(int nXPos, int nYPos, int nXAdd, int nYAdd);
	int		process(int nXPos, int nYPos);
	void	dig(int nXPos, int nYPos);
	bool	makeStartGoal();
	virtual	CMazeMatrix* matrixAllocate();

protected:
	int		m_nXSize;
	int		m_nYSize;
	CMazeMatrix *m_pMatrix;
	MMError	m_lastError;
};


CMazeMaker::CMazeMaker()
{
	m_nXSize = 0;
	m_nYSize = 0;
	m_pMatrix = NULL;
	m_lastError = MME_None;
}

CMazeMaker::~CMazeMaker()
{
	finalize();
}

bool CMazeMaker::Initialize(int nXSize, int nYSize)
{
	finalize();

	m_pMatrix = matrixAllocate();

	if (m_pMatrix == NULL) {
		m_lastError = MME_MemoryAllocError;
		return false;
	}

	if (m_pMatrix->Initialize(nXSize, nYSize) == false) {
		m_lastError = m_pMatrix->GetLastError();
		return false;
	}

	m_nXSize = nXSize;
	m_nYSize = nYSize;

	return true;
}

CMazeMatrix* CMazeMaker::matrixAllocate()
{
	return new CMazeMatrix;
}

bool CMazeMaker::finalize()
{
	if (m_pMatrix != NULL) {
		delete m_pMatrix;
		m_pMatrix = NULL;
	}
	return true;
}


// スタート位置と、ゴールの位置を作成。外壁部分に穴を開ける。
// 今回のアルゴリズムでは、外壁のすぐ内側が通路になっていないことがあるので
// その場合には箇所を移動させる。
// どこをとっても通路が見あたらない場合には、エラーとする。
// (乱数の発生具合がとても意地悪な場合を考えると、可能性は少なくとも0ではない。)
//
bool CMazeMaker::makeStartGoal()
{
	// スタート地点を左の壁の上の方に
	int nCnt = 0;
	for (nCnt = 1; nCnt < m_nYSize - 1; nCnt++) {
		if (m_pMatrix->GetAt(1, nCnt) == MMK_Space) {
			m_pMatrix->SetAt(0, nCnt, MMK_Space);
			break;
		}
	}
	if (nCnt == m_nXSize - 1) {
		return false;
	}

	// ゴール地点を右の壁の下の方に
	for (nCnt = m_nYSize; nCnt > 0; nCnt--) {
		if (m_pMatrix->GetAt(m_nXSize - 2, nCnt) == MMK_Space) {
			m_pMatrix->SetAt(m_nXSize - 1, nCnt, MMK_Space);
			break;
		}
	}
	if (nCnt == 0) {
		return false;
	}
	return true;
}


// 現在位置nXPos, nYPosからみて、nXAdd、nYAddを足した位置に移動できるかをチェック
// 移動先が埋まっている状態で、さらに三方が通路以外に覆われているなら、OKとする

bool CMazeMaker::checkPos(int nXPos, int nYPos, int nXAdd, int nYAdd)
{
	if (m_pMatrix->GetAt(nXPos + nXAdd, nYPos + nYAdd) != MMK_Filled) 
		return false;

	if (nXAdd == 0) {
		if (m_pMatrix->GetAt(nXPos - 1, nYPos + nYAdd * 2) != MMK_Space &amp;&amp;
			m_pMatrix->GetAt(nXPos    , nYPos + nYAdd * 2) != MMK_Space &amp;&amp;
			m_pMatrix->GetAt(nXPos + 1, nYPos + nYAdd * 2) != MMK_Space &amp;&amp;
			m_pMatrix->GetAt(nXPos - 1, nYPos + nYAdd ) != MMK_Space &amp;&amp;
			m_pMatrix->GetAt(nXPos + 1, nYPos + nYAdd ) != MMK_Space)
		{
			return true;
		}
	} else {
		if (m_pMatrix->GetAt(nXPos + nXAdd * 2, nYPos - 1) != MMK_Space &amp;&amp;
			m_pMatrix->GetAt(nXPos + nXAdd * 2, nYPos    ) != MMK_Space &amp;&amp;
			m_pMatrix->GetAt(nXPos + nXAdd * 2, nYPos + 1) != MMK_Space &amp;&amp;
			m_pMatrix->GetAt(nXPos + nXAdd , nYPos - 1) != MMK_Space &amp;&amp;
			m_pMatrix->GetAt(nXPos + nXAdd , nYPos + 1) != MMK_Space)
		{
			return true;
		}
	}
	return false;
}


static const int moveInfo[4][2] = {
	{-1, 0},
	{0, -1},
	{1, 0},
	{0, 1},
};

int CMazeMaker::process(int nXPos, int nYPos)
{
	int digCount=0;
	int aryMove[4] = {0};	

	if (m_pMatrix->GetAt(nXPos, nYPos) != MMK_Space) {
		return 0;
	}
	while (1) {
		int nMoveCount = 0;

		for (int nCnt = 0; nCnt < 4; nCnt++) {
			if (checkPos(nXPos, nYPos, moveInfo[nCnt][0], moveInfo[nCnt][1]) == true) {
				aryMove[nMoveCount] = nCnt;
				nMoveCount++;
			}
		}
		if (nMoveCount == 0) {
			break;
		}
		
		int nMove = ((rand() >> 1) % nMoveCount);
		nXPos = nXPos + moveInfo[aryMove[nMove]][0];
		nYPos = nYPos + moveInfo[aryMove[nMove]][1];
		m_pMatrix->SetAt(nXPos, nYPos, MMK_Space);
		digCount++;
	}
	return digCount;
}


bool CMazeMaker::Generate1()
{
	// 開始点は1, 1から。(ループの先頭
	m_pMatrix->SetAt(1, 1, MMK_Space);

	::srand((unsigned int)time(NULL));
	
	int nXCnt;
	int nYCnt;

	for (nXCnt = 1; nXCnt < m_nXSize - 1; nXCnt++) {
		for (nYCnt = 1; nYCnt < m_nYSize - 1; nYCnt++) {
			while (process(nXCnt, nYCnt) != 0) {}
		}
	}
	return makeStartGoal();
}


void CMazeMaker::dig(int nXPos, int nYPos)
{
	m_pMatrix->SetAt(nXPos, nYPos, MMK_Space);

	int aryMove[4] = {0};	

	while (1) {
		int nMoveCount = 0;

		for (int nCnt = 0; nCnt < 4; nCnt++) {
			if (checkPos(nXPos, nYPos, moveInfo[nCnt][0], moveInfo[nCnt][1]) == true) {
				aryMove[nMoveCount] = nCnt;
				nMoveCount++;
			}
		}
		if (nMoveCount == 0) {
			break;
		}
		
		int nMove = ((rand() >> 1) % nMoveCount);

		dig(nXPos + moveInfo[aryMove[nMove]][0], nYPos + moveInfo[aryMove[nMove]][1]);
	}
}

bool CMazeMaker::Generate2()
{
	::srand((unsigned int)time(NULL));
	int nXStart = ((rand() >> 1) % (m_nXSize - 2)) + 1;
	int nYStart = ((rand() >> 1) % (m_nYSize - 2)) + 1;
	dig(nXStart, nYStart);
	return makeStartGoal();
}

struct PosInfo {
	int xPos;
	int yPos;
};

bool CMazeMaker::Generate3()
{
	::srand((unsigned int)time(NULL));
	int nXStart = ((rand() >> 1) % (m_nXSize - 2)) + 1;
	int nYStart = ((rand() >> 1) % (m_nYSize - 2)) + 1;

	m_pMatrix->SetAt(nXStart, nYStart, MMK_Space);

	list<PosInfo> posList;

	PosInfo info = {nXStart, nYStart};
	posList.push_back(info);

	while (posList.size() != 0) {
		int nXPos = (posList.rbegin())->xPos;
		int nYPos = (posList.rbegin())->yPos;

		int aryMove[4] = {0};	

		int nMoveCount = 0;

		for (int nCnt = 0; nCnt < 4; nCnt++) {
			if (checkPos(nXPos, nYPos, moveInfo[nCnt][0], moveInfo[nCnt][1]) == true) {
				aryMove[nMoveCount] = nCnt;
				nMoveCount++;
			}
		}
		if (nMoveCount == 0) {
			posList.pop_back();
			continue;
		}
		
		int nMove = ((rand() >> 1) % nMoveCount);

		info.xPos = nXPos + moveInfo[aryMove[nMove]][0];
		info.yPos = nYPos + moveInfo[aryMove[nMove]][1];

		m_pMatrix->SetAt(info.xPos, info.yPos, MMK_Space);

		posList.push_back(info);
	}

	return makeStartGoal();
}

//
// コンソール出力用
class CMazeMakerConsole : public CMazeMaker
{
public:
	CMazeMakerConsole(){};
	virtual ~CMazeMakerConsole(){};

public:
	void Output();
};

void CMazeMakerConsole::Output()
{
	for (int nYCnt = 0; nYCnt < m_nYSize; nYCnt++) {
		for (int nXCnt = 0; nXCnt < m_nXSize; nXCnt++) {
			if (m_pMatrix->GetAt(nXCnt, nYCnt) == MMK_Space) {
				printf(".");
			} else {
				printf("#");
			}
		}
		puts("");
	}
	_getch();
}

// 
//
int _tmain(int argc, _TCHAR* argv[])
{
	CMazeMakerConsole maker;

	do {
		if (false == maker.Initialize(75, 50)) {
			puts("Initialize Error");
			return 0;
		}
	} while (false == maker.Generate3()); //失敗するのは、スタート、ゴールが作れなかった場合。偶然そういうことになることもあるので、そうなったら作り直す。


	maker.Output();

	return 0;
}

最初に昔の記憶を頼りにCMazeMaker::Generate1()を作ったけれど、美しくなかったのでGenerate2()を作成。迷路のサイズを増やすとスタックオーバーフローになるので、Generate3()を作成。一応、満足。

###########################################################################
.....##...#.#.##.....##......#....#...#.#.#.........#.##.........##.#.....#
#.#.##..#.#......###..###.##.#.##.#.###...#.#####.#....##.######....##.##.#
#.#..##.#.#.##.###.##.....##...#....#...#.....##..#.##.#..##...####..#..#.#
#.##..###.#..#..##..###.#..###.#.####.###.#####..####..#.##..#....##.##.#.#
#..##.....##.##..##...#.##..#######...#.#.#...#.##....##.#..###.#..#.##.###
#.####.#####.###.###.##..####.......###.###.#.###..##.#..#.##...##.#..#...#
#....###......#..#.#....##....########..##..#..#..#####.######.##..##.##.##
#.##..##.######.##...####..#####....#..##..###.#.##.##..#......#..###..#..#
#..##.#...##....#..#.#..#.##.#...#.##.##..##.....#.....####.####.##.##.##.#
##..#...#..#.#######...##....#.#####..#..#########.##.##.#..##...##..#....#
###.########.##...##########.#...##..##.##.##...####..#....##..###..#####.#
#.#..##...##..#.#.....##.....##.##..##..#...###.#.#..###.####.##...##.....#
#.##.#..#..##.#.#####.#..#####..#..##..##.#.....#...##.#.#....####.#..#####
#..#.#.###.#..#.....#...##.....##.##..##..##.##.#.###....####.#.#..#.###..#
#.##.#.##....######.########.###..#..###.##..#....#.##.#...#..#...##...##.#
#..#.#..###.##.#....#..#.....##..###..#...#.#######....#.#.#.##.#.####.##.#
##.#.##.##...#.#.#####...#####..##.##.##.##......#####.###.#.#..#..#.#..#.#
##....#..###...#....#..#.....#.##...#.#...#.#.##.....#..##.#...###...##...#
#..#####...########.####.##.##....#...#######..#####.####..#####.########.#
#.##.#.###..#.....#....###...###########...###..##...#....##.........##...#
#..#....###...#.#.####..#..#.....#.#.....#..#..##..###.#.##..#######.#..###
##.####...#######...###.##.#.###.#...######.####..##...#.#..##...#...#.##.#
#....####...#...###...#..#.#..####.#....#.....#..##..#.###.##..#.#.###.#..#
####...#..#.#.#..####.##.####......####.#####.##..#.##...#..####.#.#...#.##
##.###.#.##.#.##.#.#...#....##.######.#.##..#.###.######.##...#..#...###..#
#..##..#.####.##.#...#.####..#........#..##....##...##....###...######...##
#.##..##..##..#..##.####..##.#.######.##..####..#.#..##.###.#.#..#.##..#..#
#.##.####.#..##.##..##...###.###...#...##.##.##.####.#..#...####.#..#.###.#
#.#...#...#.###..##..#.#...#..#..#...#..#..#.##..##..#.##.#..##..##.#...###
#...#...#.#...##..##...#.####.####.#######.#..##.#..##..#.##..##..#...#...#
#.###########.###..#####....#...##.#..#....##..#...####.#..##..##.#######.#
#....#....##..#.##....###.#####..#...##.######.#####.##.##.###....#.....#.#
###.##.#.##..##..####..#..#...##.###.##......#...##.....##..########.##.#.#
#.#.#..#..#.####.#..##...##.#.#..#....######.#.#....#.#..##.#...##...#....#
#...#.###...#......####.##..#...###.###...##.#.######.#.##..#.#..##.####.##
#.#.#.#.#####.###.##....#..######.#.##..#..#.#..#.....#..##...##.#...#....#
#.###.#...##...#..#..####.##.#.##.#.#..##.##.##.#.###.##..######.#.#.####.#
#..##.#.#..#.#.####.###.#..#......#...#####..#..#...####.##..#.#.###.##...#
##..#...##.#.#.#........##.#.#.#.####..#....#######..##...##...#..#...###.#
###.######.#.#...####.#..#.#.###.#..##.#.####....###..###..##.###.###...#.#
#...#...#..#####...##.####.#..#....##..#..#...##...##...##......#..####.#.#
#.###.#...##...#####..##...##.#.##.#..###.#.######..##.###########.#....#.#
#..#..##.##..#.#...#.##..######..###.##.#....###.##.##...#.......#.#.#.####
#.##.###..#.##...#.###..##....##........#.##..#...#..#.#.#.###.#.#.###....#
#..#...##.#..#####..##.####.#.##.############...#.##.#.#.#...#.###..##.##.#
##.###..###.##...##.#..#....#..###....##....#######..#.###.###...##..###..#
#...###..#...##.###.#.##.#####...#.##.#..##.#...#...##..#...###.####.#...##
#.#...##...#......#......#.....#...#....##....#...#..##...#...#........#...
###########################################################################

ちなみに http://anond.hatelabo.jp/20070711194709 これを聞いたのは自分。

かなりたくさん書けることがわかりました。

ログイン ユーザー登録
ようこそ ゲスト さん