Hex処理系プログラミング

ヘックス座標系のサンプルプログラムを探してみたが、今ひとつ見つからない・・・
と言うことで、糞ソースかも知れないが需要もあるかも・・・と言う訳でソースを晒しておく。


横120文字×縦37文字のターミナルで実行すれば表示は壊れないはず・・・


一応ゲームになっていて、
1. 特定のポイントに到達するとクリア
2. 侵入不可の土地と海には侵入できない
3. 山には高さのパラメータがあり移動元→異動先の高低差が10を超えると移動できない。
4. 移動にはテンキーを使う、5は待機でそれ以外はキーボードの配置通りに移動する
5. 初期状態では侵入不可の土地以外は見えない
6. 移動の対象が侵入できない場合も含めて、異動先のエリアはどんな土地か表示される
といったかんじ・・・

#include <stdio.h>
#include <string.h>

#define         MAX_X                   16
#define         MAX_Y                   16

int main(int argc, char *argv[]);

struct Hex {
        char Display[16];//表示名
        char Name[1024]; //名称
        int Type;        //土地タイプ(0:侵入不可、1:平地、2:山地、3:川、4:海、森、林、鉱山、泉など)
        int Height;      //高さ
        int Open;        //既知の土地か否か(0:未知、1:既知)
};

//=====================================================================
// ● main関数
//=====================================================================
int main(int argc, char *argv[]){

        int i = 0;
        int j = 0;
        int k = 0;
        int l = 0;
        int x = 8;  //初期位置
        int y = 8;  //初期位置
        int mv_x = 0;
        int mv_y = 0;
        char Display[16];
        int  Status = 0;
        char z = 0;

        struct Hex Hex0 = { "不", "侵入不可", 0, 0,   1 };
        struct Hex Hex1 = { "平", "平地",     1, 1,   0 };
        struct Hex Hex2 = { "山", "山地",     2, 100, 0 };
        struct Hex Hex3 = { "川", "川",       3, -1,  0 };
        struct Hex Hex4 = { "海", "海",       4, -10, 0 };

        struct Hex Hex5 = { "山", "山地",     2, 10, 0 };
        struct Hex Hex6 = { "山", "山地",     2, 20, 0 };
        struct Hex Hex7 = { "山", "山地",     2, 30, 0 };
        struct Hex Hex8 = { "山", "山地",     2, 40, 0 };
        struct Hex Hex9 = { "P", "ポイント", 9, 50, 0 };

        struct Hex Map[MAX_X][MAX_Y];

        struct Hex MapOrg[MAX_X][MAX_Y] = {
            { Hex1, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0},
            { Hex1, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0},
            { Hex1, Hex0, Hex1, Hex1, Hex1, Hex1, Hex1, Hex1, Hex1, Hex1, Hex1, Hex9, Hex4, Hex4, Hex0, Hex0},
            { Hex0, Hex0, Hex1, Hex1, Hex1, Hex1, Hex1, Hex1, Hex1, Hex1, Hex1, Hex8, Hex4, Hex4, Hex0, Hex0},
            { Hex0, Hex0, Hex1, Hex1, Hex1, Hex1, Hex1, Hex1, Hex1, Hex1, Hex1, Hex7, Hex4, Hex4, Hex0, Hex0},
            { Hex0, Hex0, Hex1, Hex1, Hex1, Hex2, Hex2, Hex1, Hex1, Hex1, Hex1, Hex6, Hex3, Hex1, Hex0, Hex0},
            { Hex0, Hex0, Hex1, Hex1, Hex1, Hex2, Hex2, Hex1, Hex1, Hex1, Hex1, Hex5, Hex3, Hex1, Hex0, Hex0},
            { Hex0, Hex0, Hex1, Hex1, Hex1, Hex2, Hex2, Hex1, Hex1, Hex1, Hex1, Hex4, Hex1, Hex1, Hex0, Hex0},
            { Hex0, Hex0, Hex1, Hex1, Hex1, Hex1, Hex1, Hex1, Hex1, Hex1, Hex3, Hex1, Hex1, Hex1, Hex0, Hex0},
            { Hex0, Hex0, Hex1, Hex1, Hex1, Hex1, Hex1, Hex1, Hex1, Hex3, Hex1, Hex1, Hex1, Hex1, Hex0, Hex0},
            { Hex0, Hex0, Hex1, Hex1, Hex1, Hex1, Hex1, Hex3, Hex3, Hex1, Hex1, Hex1, Hex1, Hex1, Hex0, Hex0},
            { Hex0, Hex0, Hex1, Hex1, Hex1, Hex1, Hex1, Hex3, Hex1, Hex1, Hex1, Hex1, Hex1, Hex1, Hex0, Hex0},
            { Hex0, Hex0, Hex1, Hex1, Hex1, Hex1, Hex1, Hex3, Hex1, Hex1, Hex1, Hex1, Hex1, Hex1, Hex0, Hex0},
            { Hex0, Hex0, Hex1, Hex1, Hex1, Hex1, Hex1, Hex3, Hex1, Hex1, Hex1, Hex1, Hex1, Hex1, Hex0, Hex0},
            { Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0},
            { Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0, Hex0}
        };

        //座標系をx-y軸に合うよう回転する
        for (j=0;j<MAX_Y; j++){
                for (i=0;i<MAX_X; i++){
                        Map[i][j] = MapOrg[j][i];
                }
        }

        while (1){
                //移動地点入力
                /*
                 *  7  8  9
                 *  4  5  6
                 *  1  2  3
                 *    (i,j-1) (i+1, j-1)
                 *           \ /
                 *  (i-1,j)−(i,j)−(i+1, j)
                 *           / \
                 *      (i-1,j+1) (i,j+1)
                 */
                z = getchar();
                if      (z=='7'){ mv_x =  0; mv_y = -1; } else if (z=='8'){ mv_x = 0; mv_y = -1; } else if (z=='9'){ mv_x = 1; mv_y = -1;}
                else if (z=='4'){ mv_x = -1; mv_y =  0; } else if (z=='5'){ mv_x = 0; mv_y =  0; } else if (z=='6'){ mv_x = 1; mv_y =  0;}
                else if (z=='1'){ mv_x = -1; mv_y =  1; } else if (z=='2'){ mv_x = 0; mv_y =  1; } else if (z=='3'){ mv_x = 0; mv_y =  1;}
                z = getchar();//改行を取得

                //異動先の地形情報の表示を許可
                Map[x+mv_x][y+mv_y].Open = 1;

                //侵入不可の場合は戻してエラーを吐く
                if ( Map[x+mv_x][y+mv_y].Type == 0){
                        mv_x = 0;
                        mv_y = 0;
                        printf("侵入不可領域につき侵入できません。\n");
                }

                //ステータスが徒歩の場合は戻してエラーを吐く
                if ( Map[x+mv_x][y+mv_y].Type == 4 && Status == 0 ){
                        mv_x = 0;
                        mv_y = 0;
                        printf("海には徒歩では侵入できません。\n");
                }

                //侵入不可の場合は戻してエラーを吐く
                if ( abs( Map[x][y].Height - Map[x+mv_x][y+mv_y].Height) > 10 ){
                        mv_x = 0;
                        mv_y = 0;
                        printf("高低差が大きすぎて侵入できません。\n");
                }


                //移動する
                x = x + mv_x;
                y = y + mv_y;

                //表示する
                printf(" /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ \n");
                for (j=0;j<MAX_Y; j++){


                        for (l=0; l < j/2; l++){
                                printf("     ");
                        };

                        for (i=0;i<MAX_X; i++){
                                if ( Map[i][j].Open == 1){
                                        sprintf(Display, "%s", Map[i][j].Display);
                                } else {
                                        sprintf(Display, "?");
                                }
                                if ( i==x && j==y){
                                        printf("|(%2s)", Display);
                                }else{
                                        printf("| %2s ", Display);
                                };
                        };

                        printf("|\n");
                        for (l=0; l < j/2; l++){
                                printf("     ");
                        };

                        if ( j % 2 != 0){
                                printf("   \ /\ /\ /\ /\ /\ /\ /\ /\ /\/\ /\ /\ /\ /\ /\ /\ \n");
                        }else{
                                printf(" \/ \/ \/ \/ \/ \/ \/ \/ \/ \/\/ \/ \/ \/ \/ \/ \\n");
                                printf("   ");
                        };
                };
                printf(" ----------------------------------------------------------------------------------------------------------------------\n");

                //ポイント到達
                if ( Map[x][y].Type == 9){
                        printf("ポイント到達!クリアしました。\n");
                        exit(0);
                }

        };

}