EQQ.jp

Index


 

MinGW キャラクタベース

 

キャラクタベースの出力

コマンドプロンプトのようなキャラクタベースでプログラムを作る場合に、少しでも見栄えをよくしようとすると、画面の消去、カーソル位置制御、文字色の設定ぐらいは最低限ほしいところです。そこで、これらを実現する関数を作成し、ライフゲームを動かします。

 

画面制御プログラム

以下の3つの関数を作成しました。

以下にソースを示します。このプログラムは、Linux のターミナルプログラムでも動作するように作られています。

 

#ifdef  _WINDOWS_H
#ifndef _WINDOWS_
#define _WINDOWS_
#endif
#endif

void    locate(int, int);
void    cls();
void    color(int, int);

void locate(int lx, int ly) {   // Move cursor at (lx,ly)
#ifdef _WINDOWS_
        static HANDLE h;
        COORD st;

        lx = (lx < 1) ? 0 : (lx - 1);
        ly = (ly < 1) ? 0 : (ly - 1);
        h=GetStdHandle(STD_OUTPUT_HANDLE);
        st.X = (short)lx;
        st.Y = (short)ly;
        SetConsoleCursorPosition(h, st);
#else
        if(lx < 1) lx = 1;
        if(ly < 1) ly = 1;
        printf("\033[%d;%dH", lx, ly);
        fflush(stdout);
#endif
}

void cls() {                    // Clear screen
#ifdef _WINDOWS_
        system("cls");
#else
        printf("\033[2J");
        printf("\033[1;1H");
        fflush(stdout);
#endif
}

// Black:0 Red:1 Green:2 Yellow:3 Blue:4 Magenta:5 Cyan:6 White:7
void color(int fgc, int bgc) {  // Change text foreground and background color
#ifdef _WINDOWS_
        int cl = 7;
        static HANDLE h;

        if(fgc < 0) fgc = 0;
        if(bgc < 0) bgc = 0;
        // Defined below at wincon.h
        // FOREGROUND_BLUE      1
        // FOREGROUND_GREEN     2
        // FOREGROUND_RED       4
        // FOREGROUND_INTENSITY 8
        // BACKGROUND_BLUE      16
        // BACKGROUND_GREEN     32
        // BACKGROUND_RED       64
        // BACKGROUND_INTENSITY 128
        if(fgc == 0) cl = 0;
        if(fgc == 1) cl = 4;
        if(fgc == 2) cl = 2;
        if(fgc == 3) cl = 6;
        if(fgc == 4) cl = 1;
        if(fgc == 5) cl = 5;
        if(fgc == 6) cl = 3;
        if(fgc == 7) cl = 7;
        if(fgc == 9) cl = 7;
        if(bgc == 0) cl += 0;
        if(bgc == 1) cl += 64;
        if(bgc == 2) cl += 32;
        if(bgc == 3) cl += 96;
        if(bgc == 4) cl += 16;
        if(bgc == 5) cl += 80;
        if(bgc == 6) cl += 48;
        if(bgc == 7) cl += 112;
        if(bgc == 9) cl += 0;
        h=GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleTextAttribute(h, cl);
#else
        if(fgc < 0) fgc = 0;
        if(bgc < 0) bgc = 0;
        printf("\033[3%1dm", fgc);
        printf("\033[4%1dm", bgc);
        fflush(stdout);
#endif
}

 

ライフゲームプログラム

上述した画面制御関数(ファイル名を cui.c とする)を利用したライフゲーム(ファイル名を life2c.c とする)を作成しました。2つのソースプログラムは同一のディレクトリに置いて下さい。

コンパイルは、MinGW の環境では、以下のように行います。

> cc life2c.c

 

 

以下に、ライフゲームのソースを示します。

#include        <stdio.h>
#include        <windows.h>
#include        "cui.c"

#define MAXSTEP 500     // Step
#define BMX     79      // Max x size of board
#define BMY     23      // Max y size of board

int     b[BMX+2][BMY+2];        // Board Empty:0 Marked:3

void inputboard() {
        int     x;
        int     y;

        for(y = 0; y < BMY+2; y++) {
                for(x = 0; x < BMX+2; x++) {
                        b[x][y] = 0;
                }
        }

        b[40][14] = 3;
        b[40][15] = 3;
        b[40][16] = 3;
        b[41][14] = 3;
        b[39][15] = 3;
}

void outputboard(int i) {
        int     x;
        int     y;
        char    buf[BMX+1];

        locate(1, 1);
        for(y = 1; y <= BMY; y++) {
                for(x = 1; x <= BMX; x++) {
                        if(b[x][y] == 0) {
                                buf[x-1] = ' ';
                        } else {
                                buf[x-1] = '*';
                        }
                }
                buf[BMX] = '\0';
                printf("%s\n", buf);
        }
        color(3, 0);
        printf("Step : %5d\n", i);
        color(9, 9);
}

void initscreen() {
        cls();
}

int countalive(int x, int y) {
        int cal = 0;

        if(b[x-1][y-1] > 1) cal ++;
        if(b[x-1][y] > 1) cal ++;
        if(b[x-1][y+1] > 1) cal ++;
        if(b[x][y-1] > 1) cal ++;
        if(b[x][y+1] > 1) cal ++;
        if(b[x+1][y-1] > 1) cal ++;
        if(b[x+1][y] > 1) cal ++;
        if(b[x+1][y+1] > 1) cal ++;
        return cal;
}

void nextstep() {
        int x;
        int y;
        int cal;

        for(y = 1; y <= BMY; y++) {
                for(x = 1; x <= BMX; x++) {
                        cal = countalive(x, y);
                        if(b[x][y] == 0) {
                                if(cal == 3) b[x][y] = 1;
                        } else if(b[x][y] == 3) {
                                if(cal < 2) b[x][y] = 2;
                                if(cal > 3) b[x][y] = 2;
                        } else {
                                printf("Unknown code of board[%d][%d]\n", x, y);
                        }
                }
        }
        for(y = 1; y <= BMY; y++) {
                for(x = 1; x <= BMX; x++) {
                        if(b[x][y] == 1) b[x][y] = 3;
                        if(b[x][y] == 2) b[x][y] = 0;
                }
        }
}

int main() {
        int i = 0;

        inputboard();
        initscreen();
        for(i = 1; i <= MAXSTEP; i++) {
                outputboard(i);
                nextstep();
        }
        return 0;
}

 

 

Life character