すのものの「いろいろ」(その173)

キャラクタベースのスロットマシン>ドラムが中間位置でも表示するよう改良

左に、どの筋に賭けているのかを示す印をつけてみた。 (ただし、手抜きをしているため、すべての筋に強制的に賭けさせられるようになっている。)

      o
       \
      o-$ $ %

      o-* * *

      o-% $ &
       /
      o
こうするためには前の
        $ $ %
        * * *
        % $ &
では行がつまりすぎている。 しかし、表示だけを上のように変えてみると、 空いている行に何も表示されないのが変である。 上のような位置で止まる直前には
      o
       \
      o-$ $
            *
      o-* *
            &
      o-% $
       /
      o
となっていなければおかしい。 こうなるよう改造してみた。

/* コマンドラインオプション -nw をつけて起動するとウェイトなしになります。 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define ESCSEQ      /* カーソル移動のエスケープシーケンスが使えるとき定義 */
#define DEBUG       /* デバッグしたいとき定義(削ると表示が減ってすっきりする) */

#define N 1000
#define SIZE 16     /* ドラム一回りにいくつの絵があるか */

char drum[3][SIZE] = {
    { '7', '=', ')', '&', '%', '=', ')', '%', '&', '%', '*', '$', ')', '*', '%', '&' },
    { '7', '=', '&', '%', '&', '%', '&', '$', '*', '$', '%', '*', '&', '$', ')', '&' },
    { '7', '$', '=', ')', '*', '&', '%', '*', '%', '&', '*', '%', ')', '%', '&', '*' }
/*
    { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' },
    { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' },
    { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }
*/
    /* こちらは、ドラム表示がバグってないか確かめる際に使うもの。*/
    /* 絶対に当たらない。……というわけではない! (7 があるのだ。)*/
};

long init(void);
int bet(int coins);
int play(long wait);
void print(void);
int check(int i, int j, int k);
void printrule(void);

int t;          /* 時刻 */
int vel[3];     /* ドラムの速度 */
int pos[3];     /* ドラムの位置(0, 1, ..., SIZE-1 に値をとる)*/
int frac[3];    /* ドラムの位置の、小数点以下の半端な部分 */
                /* N が 1000 のままだと、pos[0] が 3, frac[0] が 125 */
                /* のとき、実際の位置は 3.125 とみなされる。*/

int main(int argc, char* argv[]) {
    int coins, bets, get;
    long wait;

    if (argc > 1 && strcmp(argv[1]+1, "nw") == 0) {
        wait = 0;
    } else {
        wait = init();
    }
    for (coins = 100; coins > 0;    ) { /* コイン 100 枚からスタート */
        if ((bets = bet(coins)) == 0) { /* ユーザが終了を希望したとき */
            break;
        }
        if ((get = play(wait)) > 0) {   /* ここで実際のプレイ */
            printf("%d 枚のコインが当たりました.\n", get * bets / 5);
        } else {
            printf("残念でした.\n");
        }
        coins = coins - bets + get * bets / 5;  /* 儲けを加算(減算) */
        if (coins == 0) {
            printf("あなたは破産しました....\n");
        }
    }
    return 0;
}


/* どれだけ wait を入れたらいいか調べるため、開始時に呼ばれる。*/
long init(void) {
    time_t start;
    long wait;

    printf("少々お待ちください...\n");
    printrule();
    start = time(NULL);
    while (difftime(time(NULL), start) == 0) {
        ;
    }
    start = time(NULL);
    for (wait = 0; difftime(time(NULL), start) < 1; wait++) {
        if (wait == -1) {
            printf("カウンタが一周してしまいましたっ!\n");
            printf("ウェイトが正しくはいらないかも....\n");
        }
    }
#ifdef DEBUG
    printf("このシステムは関数 time() を1秒間に %ld 回呼び出すことがわかりました.\n", wait);
#endif
    return wait;
}


/* ユーザに、賭けるコインの枚数を決めさせる */
int bet(int coins) {
    int bet;

    while (1) {
        printf("%d 枚のコインを持っています.\n", coins);
        printf("何枚賭けますか? (0 で終了、負の数で倍率を印字)>");
        scanf("%d", &bet);
        if (bet < 0) {
            printrule();
        } else if (bet > coins) {
            printf("そんなに持っていませんよ.\n");
        } else if (bet % 5 != 0) {
            printf("5 箇所すべてに賭けていただくため、5 の倍数でお願いします.\n");
        } else {
            break;
        }
    }
    return bet;
}


/* 実際のプレイ。*/
int play(long wait) {
    int i;
    unsigned seed = (unsigned)time(NULL);

#ifdef DEBUG
    printf("乱数の種は %u です.\n", seed);
#endif
    srand(seed);

    pos[0] = pos[1] = pos[2] = rand() % SIZE;
    vel[0] = 1000;  /* 初速度を N 倍したものだが、数値は適当 */
    vel[1] = 1200;  /* 同上 */
    vel[2] = 1500;  /* 同上 */
    frac[0] = frac[1] = frac[2] = rand() % N;

    for (t = 0; vel[0] > 0 || vel[1] > 0 || vel[2] > 0; t++) {
        print();

        for (i = 0; i < 3; i++) {       /* 以下、ドラムを動かす */
            frac[i] += vel[i];
            pos[i] += (frac[i] / N);
            pos[i] %= SIZE;
            frac[i] %= N;
            vel[i] = vel[i] - rand() % 20;  /* ドラムの減速。適当 */
            if (vel[i] <= 0) {
                vel[i] = 0;
                if (frac[i] >= N/2) {    /* ドラムが中間位置で止まったとき */
                    /* putchar('\a'); */        /* ←デバッグ時の残骸(耳も使うのだ)*/
                    if (rand() % 8 == 0) {      /* 確率 1/8 でドラムが戻って止まる */
                        frac[i] = 0;
                    } else {                    /* それ以外のときはちょっと加速(適当)*/
                        vel[i] = 50 + rand() % 50;
                    }
                }
            }
        }
        for (i = 0; i < wait/16; i++) {     /* 16 に特別な意味はない。適当 */
            time(NULL);
        }
    }
    print();        /* 最終状態の印字 */

#ifdef ESCSEQ
#ifdef DEBUG
    printf("\033[11B");     /* 11 行下へ */
#else
    printf("\033[9B");      /* 9 行下へ */
#endif
#endif
    return check(0, 0, 0) + check(1, 1, 1) + check(2, 2, 2) + check(0, 1, 2) + check(2, 1, 0);
}


/* ドラムを印字 */
void print(void) {
    int i, j;

#ifdef DEBUG
    printf("    時刻   速度                位置\n");
    printf("%8d  ", t);
    printf("%4d %4d %4d   ", vel[0], vel[1], vel[2]);
    printf("%2d.%03d ", pos[0], frac[0]);
    printf("%2d.%03d ", pos[1], frac[1]);
    printf("%2d.%03d\n", pos[2], frac[2]);
#endif
    puts("      o");
    puts("       \\");

    for (j = 2; j >= 0; j--) {
        printf("      o-");             /* 最後に止まり得る位置 */
        for (i = 0; i < 3; i++) {
            printf("%c", frac[i] < N/2 ? drum[i][(pos[i]+j)%SIZE] : ' ');
            printf("%s", i < 2 ? " " : "");
        }
        putchar('\n');
        if (j > 0) {                    /* 中間の位置 */
            printf("        ");
            for (i = 0; i < 3; i++) {
                printf("%c", frac[i] >= N/2 ? drum[i][(pos[i]+j)%SIZE] : ' ');
                printf("%s", i < 2 ? " " : "");
            }
            putchar('\n');
        }
    }

    puts("       /");
    puts("      o");
#ifndef ESCSEQ
#ifndef DEBUG
    putchar('\n');
#endif
#endif
#ifdef ESCSEQ
#ifdef DEBUG
    printf("\033[11A");     /* 11 行上へ */
#else
    printf("\033[9A");      /* 9 行上へ */
#endif
#endif
}


/* 当たりをチェック */
int check(int i, int j, int k) {
    int get = 0;
    char x[3];

    x[0] = drum[0][(pos[0] + i) % SIZE];
    x[1] = drum[1][(pos[1] + j) % SIZE];
    x[2] = drum[2][(pos[2] + k) % SIZE];

    if (x[0] == '7' && x[1] == '7' && x[2] == '7') {
        get += 1000;
    }
    if (x[0] == '=' && x[1] == '=' && x[2] == '=') {
        get += 500;
    }
    if (x[0] == '$' && x[1] == '$' && x[2] == '$') {
        get += 200;
    }
    if (x[0] == ')' && x[1] == ')' && x[2] == ')') {
        get += 100;
    }
    if (x[0] == '*' && x[1] == '*' && x[2] == '*') {
        get += 50;
    }
    if (x[0] == '&' && x[1] == '&' && x[2] == '&') {
        get += 20;
    }
    if (x[0] == '%' && x[1] == '%' && x[2] == '%') {
        get += 10;
    } else if (x[0] == '%' && x[1] == '%') {
        get += 5;
    }
    return get;
}


/* ルールを印字 */
void printrule(void) {
    printf("\t7 7 7 ... 1000 倍\n");
    printf("\t= = = ...  500 倍\n");
    printf("\t$ $ $ ...  200 倍\n");
    printf("\t) ) ) ...  100 倍\n");
    printf("\t* * * ...   50 倍\n");
    printf("\t& & & ...   20 倍\n");
    printf("\t%% %% %% ...   10 倍\n");
    printf("\t%% %%   ...    5 倍\n");
}

付) 結局つけなかった機能だが、 途中で再度 srand() を呼んで乱数の種の初期化を行なうようにしておくと、 ドラムが回ったあとでも Ctrl+S でゲームを中断することにより、 結果を変えることができるようになる。 ただし、そんなタイミングで押したらどう変わるかはわからない。 (「動き始めたら見ているだけですか」 と学生に聞かれたので考えてみた機能である。)

2007-12-15 (6) 22:12:19 +0900

「中断」と書いたが、一時的に止めて、Ctrl+Q などで再開することである。

2008-01-18 (5) 01:26:33 +0900

スロットマシンのことを縁起をかついで「アタロット」って言っている人…

…、世の中にはいるだろうな。

2007-12-15 (6) 02:46:37 +0900

きょうの困った>スロットマシンのドラムって、どっちに回るんだっけ?

プログラムを書きかけて、開発中のものを学生に遊んでもらっているとき、 ふと気になった。わからない。学生に聞いてみたが、両方の説があった。 Wikipedia でもわからない。

前項のプログラムは、手前に回るように作ってある。 すなわち、文字は上から下に流れる。

2007-12-15 (6) 02:44:40 +0900

キャラクタベースのスロットマシンのプログラム

前から、書きたいと思っていた。 《スロット風に数字が“回る”プログラムの準備版》 もその一つだが、これは文字がその場で変わるだけ。 そうではなく、 ドラムが回っているように見えるものを作りたいと思って何度かトライしたのだが、 うまくゆかなかった。 今回、C言語の授業で乱数を教えるついでにゲームを作ってみせてやろうと考え、 書き始めてみたら、なぜか、できた。 ただし、授業で教えていない char 型を出さないと不自然なものになってしまうので、 授業では公開せず、ここで公開することにした。 画面はこんな感じ。

少々お待ちください...
        7 7 7 ... 1000 倍
        = = = ...  500 倍
        $ $ $ ...  200 倍
        ) ) ) ...  100 倍
        * * * ...   50 倍
        & & & ...   20 倍
        % % % ...   10 倍
        % %   ...    5 倍
100 枚のコインを持っています.
何枚賭けますか? (0 で終了、負の数で倍率を印字)>5
        $ $ %
        * * *
        % $ &
50 枚のコインが当たりました.
145 枚のコインを持っています.
何枚賭けますか? (0 で終了、負の数で倍率を印字)>

ドラムには位置のほかに速度も設定し、ランダムに減速してゆく。 なぜか今回はその式やパラメータがうまくいったようで、 実際にドラムが回っているように見える。

画面制御エスケープシーケンスが使えるなら、 同じ位置にドラムを重ねて書いてゆくので、 その場で回っている感じがするのは当然だが、 そうでない場合も、ドラムの絵の3行を書いたところで 1/16 秒ほどのウェイトを置くようにしたらその場で回って見える。 (そういう絵が縦にいくつか並ぶ。)

/* コマンドラインオプション -nw をつけて起動するとウェイトなしになります。 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define ESCSEQ      /* カーソル移動のエスケープシーケンスが使えるとき定義 */
#define DEBUG       /* デバッグしたいとき定義(削ると表示が減ってすっきりする) */

#define N 1000
#define SIZE 16     /* ドラム一回りにいくつの絵があるか */

char drum[3][SIZE] = {
    { '7', '=', ')', '&', '%', '=', ')', '%', '&', '%', '*', '$', ')', '*', '%', '&' },
    { '7', '=', '&', '%', '&', '%', '&', '$', '*', '$', '%', '*', '&', '$', ')', '&' },
    { '7', '$', '=', ')', '*', '&', '%', '*', '%', '&', '*', '%', ')', '%', '&', '*' }
/*
    { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' },
    { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' },
    { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }
*/
    /* こちらは、ドラム表示がバグってないか確かめる際に使うもの。*/
    /* 絶対に当たらない。……というわけではない! (7 があるのだ。)*/
};

long init(void);
int bet(int coins);
int play(long wait);
void print(void);
int check(int i, int j, int k);
void printrule(void);

int t;          /* 時刻 */
int vel[3];     /* ドラムの速度 */
int pos[3];     /* ドラムの位置(0, 1, ..., SIZE-1 に値をとる)*/
int frac[3];    /* ドラムの位置の、小数点以下の半端な部分 */
                /* N が 1000 のままだと、pos[0] が 3, frac[0] が 125 */
                /* のとき、実際の位置は 3.125 とみなされる。*/

int main(int argc, char* argv[]) {
    int coins, bets, get;
    long wait;

    if (argc > 1 && strcmp(argv[1]+1, "nw") == 0) {
        wait = 0;
    } else {
        wait = init();
    }
    for (coins = 100; coins > 0;    ) { /* コイン 100 枚からスタート */
        if ((bets = bet(coins)) == 0) { /* ユーザが終了を希望したとき */
            break;
        }
        if ((get = play(wait)) > 0) {   /* ここで実際のプレイ */
            printf("%d 枚のコインが当たりました.\n", get * bets / 5);
        } else {
            printf("残念でした.\n");
        }
        coins = coins - bets + get * bets / 5;  /* 儲けを加算(減算) */
        if (coins == 0) {
            printf("あなたは破産しました....\n");
        }
    }
    return 0;
}


/* どれだけ wait を入れたらいいか調べるため、開始時に呼ばれる。*/
long init(void) {
    time_t start;
    long wait;

    printf("少々お待ちください...\n");
    printrule();
    start = time(NULL);
    while (difftime(time(NULL), start) == 0) {
        ;
    }
    start = time(NULL);
    for (wait = 0; difftime(time(NULL), start) < 1; wait++) {
        if (wait == -1) {
            printf("カウンタが一周してしまいましたっ!\n");
            printf("ウェイトが正しくはいらないかも....\n");
        }
    }
#ifdef DEBUG
    printf("このシステムは関数 time() を1秒間に %ld 回呼び出すことがわかりました.\n", wait);
#endif
    return wait;
}


/* ユーザに、賭けるコインの枚数を決めさせる */
int bet(int coins) {
    int bet;

    while (1) {
        printf("%d 枚のコインを持っています.\n", coins);
        printf("何枚賭けますか? (0 で終了、負の数で倍率を印字)>");
        scanf("%d", &bet);
        if (bet < 0) {
            printrule();
        } else if (bet > coins) {
            printf("そんなに持っていませんよ.\n");
        } else if (bet % 5 != 0) {
            printf("5 箇所すべてに賭けていただくため、5 の倍数でお願いします.\n");
        } else {
            break;
        }
    }
    return bet;
}


/* 実際のプレイ。*/
int play(long wait) {
    int i;
    unsigned seed = (unsigned)time(NULL);

#ifdef DEBUG
    printf("乱数の種は %u です.\n", seed);
#endif
    srand(seed);

    pos[0] = pos[1] = pos[2] = rand() % SIZE;
    vel[0] = 1000;  /* 初速度を N 倍したものだが、数値は適当 */
    vel[1] = 1200;  /* 同上 */
    vel[2] = 1500;  /* 同上 */
    frac[0] = frac[1] = frac[2] = rand() % N;

    for (t = 0; vel[0] > 0 || vel[1] > 0 || vel[2] > 0; t++) {
        print();

        for (i = 0; i < 3; i++) {       /* 以下、ドラムを動かす */
            frac[i] += vel[i];
            pos[i] += (frac[i] / N);
            pos[i] %= SIZE;
            frac[i] %= N;
            vel[i] = vel[i] - rand() % 20;  /* ドラムの減速。適当 */
            if (vel[i] < 0) {
                vel[i] = 0;
            }
        }
        for (i = 0; i < wait/16; i++) {     /* 16 に特別な意味はない。適当 */
            time(NULL);
        }
    }
    print();        /* 最終状態の印字 */

#ifdef ESCSEQ
#ifdef DEBUG
    printf("\033[5B");      /* 5 行下へ */
#else
    printf("\033[3B");      /* 3 行下へ */
#endif
#endif
    return check(0, 0, 0) + check(1, 1, 1) + check(2, 2, 2) + check(0, 1, 2) + check(2, 1, 0);
}


/* ドラムを印字 */
void print(void) {
#ifdef DEBUG
    printf("    時刻   速度                位置\n");
    printf("%8d  ", t);
    printf("%4d %4d %4d   ", vel[0], vel[1], vel[2]);
    printf("%2d.%03d ", pos[0], frac[0]);
    printf("%2d.%03d ", pos[1], frac[1]);
    printf("%2d.%03d\n", pos[2], frac[2]);
#endif
    printf("        %c %c %c\n", drum[0][(pos[0]+2)%SIZE], drum[1][(pos[1]+2)%SIZE], drum[2][(pos[2]+2)%SIZE]);
    printf("        %c %c %c\n", drum[0][(pos[0]+1)%SIZE], drum[1][(pos[1]+1)%SIZE], drum[2][(pos[2]+1)%SIZE]);
    printf("        %c %c %c\n", drum[0][pos[0]],          drum[1][pos[1]],          drum[2][pos[2]]);
#ifndef ESCSEQ
#ifndef DEBUG
    putchar('\n');
#endif
#endif
#ifdef ESCSEQ
#ifdef DEBUG
    printf("\033[5A");      /* 5 行上へ */
#else
    printf("\033[3A");      /* 3 行上へ */
#endif
#endif
}


/* 当たりをチェック */
int check(int i, int j, int k) {
    int get = 0;
    char x[3];

    x[0] = drum[0][(pos[0] + i) % SIZE];
    x[1] = drum[1][(pos[1] + j) % SIZE];
    x[2] = drum[2][(pos[2] + k) % SIZE];

    if (x[0] == '7' && x[1] == '7' && x[2] == '7') {
        get += 1000;
    }
    if (x[0] == '=' && x[1] == '=' && x[2] == '=') {
        get += 500;
    }
    if (x[0] == '$' && x[1] == '$' && x[2] == '$') {
        get += 200;
    }
    if (x[0] == ')' && x[1] == ')' && x[2] == ')') {
        get += 100;
    }
    if (x[0] == '*' && x[1] == '*' && x[2] == '*') {
        get += 50;
    }
    if (x[0] == '&' && x[1] == '&' && x[2] == '&') {
        get += 20;
    }
    if (x[0] == '%' && x[1] == '%' && x[2] == '%') {
        get += 10;
    } else if (x[0] == '%' && x[1] == '%') {
        get += 5;
    }
    return get;
}


/* ルールを印字 */
void printrule(void) {
    printf("\t7 7 7 ... 1000 倍\n");
    printf("\t= = = ...  500 倍\n");
    printf("\t$ $ $ ...  200 倍\n");
    printf("\t) ) ) ...  100 倍\n");
    printf("\t* * * ...   50 倍\n");
    printf("\t& & & ...   20 倍\n");
    printf("\t%% %% %% ...   10 倍\n");
    printf("\t%% %%   ...    5 倍\n");
}

2007-12-15 (6) 02:05:03 +0900

プログラムを、少々手直ししたものに置き換えた。

ドラムの柄は、 ファミコン用のゲーム「ドラゴンクエスト IV」のカジノにあった、 一番左のスロットマシンから引用した。

雰囲気は、同じくファミコン用のゲーム「ドラゴンクエスト II」 の福引き所にあった福引きの機械と似ていると思う。 確か、あれは一行しか表示されなかったが、 一行の中でキャラクタが上下にずれた状態で表示されたと記憶している。 それを三行でやったのがこれ、という感じ。

2007-12-15 (6) 22:06:49 +0900

文字と元の絵との関係を説明しよう。 「7」が「7」なのは言うまでもあるまい。 「=」は「バー」。 「$」は「太陽」。 日本のパソコンでは米ドルのマークに見えるので似ていないが、 本来はこのコードには一般通貨記号が当てられていて、それは小さな丸の 右上、右下、左上、左下から短い棒が出ている、通称“太陽マーク”だ、 と読んだ記憶があるからである。 「)」は形から「月」。 「*」は「星」。 「&」は「水」(水滴)。 「%」はちょっとこじつけでチェリー。小さな丸は実、斜線は枝だと思うことにする。

2007-12-17 (1) 01:41:29 +0900

以前のソースファイルが出てきたので見てみた。 うまくゆかなかった原因は、 上に示したプログラムのように空ループを回すのではなく、 同じ内容を何度も表示させることでスピード調整をしていたことにある。 画面上をカーソルが何度も行き来するため、 ドラムが回っているように見えなかったのだ。

上に書いた太陽マークは html では &curren; と書けば 「¤」と出るのだった。

2007-12-30 (0) 23:19:46 +0900

Win95 の DOS 窓で「cursor 戻れ」の escape sequence と tab が相性悪し

NEC PC-9821 Xa7 上で Windows 95. [Version 4.00.950] を動かし、 Borland C++ 3.1 でプログラムを書いていたのだが、 画面制御エスケープシーケンス関連で納得のゆかない点があり、悩んでいた。

実験して気づいたこと。

1234567890^[[80Dab
^[ は実際には ESC) というテキストファイルを作って type すると、 行頭から 1234567890 を印字したあとカーソルを 80 カラム戻して ab と印字するので
ab34567890
となる。これは予想通り。 それに対し、
1234567890^[[80Dタブaタブb
タブは実際にはタブ) だと
  a       b
となる。なぜか 3 カラム目に a, そこから 7 カラムあけて b である。

これが原因で、印字位置がおかしくなっていたのだと思われる。

edlin のタブの展開がおかしい》 と関係あるか?

2007-12-15 (6) 01:43:01 +0900

理由がわかったような気がする。 「1234567890」で 10 カラム。そこから 80 カラムだけカーソルを戻した。 80 は 8 の倍数なので、 いまタブ停止位置から 2 カラム目にいると思い込んでいるのでは。 だとしたら、タブはスペース 6 個に展開されるはずか。 ちょっとまだ解明しきれていないな。

2008-01-18 (5) 01:31:14 +0900

NHKフランス語会話>十二月 5 日(水曜日)放送分

前半については 《NHKフランス語会話>六月 06 日(水曜日)放送分》 も参照。

今週の冒頭、キーフレーズをいうのはカップルだが、 やはり、最初は音声が出ない。

動詞 aller の現在形をきちんと言えた右宗さんに先生が「よくできました!」。 とっても感情がこもっていた。 私も、一度でいいから言われてみたい。

右宗さんが on は(ここでは)「私たち」の意味なのにどうして 「on va」では動詞が三人称単数の形になっているのか、と質問するところ。 割とアップになってゆっくり「on va」と発音するので、 そのときの口の形がよくわかる。どうも [b] になっているようだ。 そのあとの練習問題のほうがもっとよくわかる。 ただ、vais のときは [v] のようでもある。

ジェニファーさんの発音コーナーで cahier の訳語を「ノート」としていたが、 「帳面」のほうが誤解が少ないだろう。 “ノートをとる”の意味ではないのだから。

中級編。 ジェニファーさんの字幕に「夕べずいぶん遅くまで本を読んでたから」とあるが、 この「夕べ」は hier soir の訳語なので「昨夜」と書くのが普通ではあるまいか。 あるいは「昨夜(さくや)」「昨晩」という訳語を当てるか。 (「夕べ」は soirée の訳語だろう。)

ジェニファーさんが 「Il doit y avoir beaucoup de monde.」を言いかけて止まり、言い直す。 どう間違えたのか考えてみたのだが、 doit と y とをリエゾンさせ、 [t] の音を出すため舌の先を歯茎の裏につけたところで止まっているように思う。 (ここはリエゾンさせてもいいところだと思うけど、 番組の方針としてはしない?)

後半。 ジェニファーさんが長い髪をさらさらにして、 男の子みたいにかわいいー。 (少女マンガに登場する美青年みたい。)

2007-12-12 (3) 21:45:34 +0900

「戦争を知らない子供たち」が「おとなになって歩きはじめる」のはなぜ?

戦争の際に敵国が使った兵器の影響で、 戦争が終わってから生まれたにも関わらず、 発育が遅れ、 大人になるまで歩くことができなかったという意味では、 と気になりだしたら、明るく歌えなくなってしまった。

2007-12-09 (0) 19:30:38 +0900

ウルトラセブンがマージャンするときはチルソナイト製の牌を使うんだろうな

TVアニメ「サザエさん」の途中で流れるコマーシャルに、 ウルトラセブンがマージャンをしているのがある。 ウルトラセブンには透視能力があるので一般の牌なら透視できてしまうはず。 「緑の恐怖」に登場した架空の特殊金属、 チルソナイトか何かでできているのだろう。

なお、 ウルトラセブンが人間のことばを話すのでいっしょに打っている人間が驚くが、 毎回見ていた僕らの世代は驚かない。

2007-12-09 (0) 19:17:09 +0900

冬こそ夏時間を!の会>そうすれば暗くなる前に仕事を終えて家に帰れる

冬至が近いので、日が暮れるのが早い。 きょうは日曜日なのでいつものように町へ行き、 18時からのTVアニメ「ちびまる子ちゃん」に間に合うよう帰ってきたが、 ほかの季節とは比べものにならないほど暗い。 そこでふと思ってしまったのが、 「私自身は反対だが、夏時間制度を導入していればもっと明るいのに」 ということだ。 これは大間違い。 たとえ夏時間を導入しても、いまはその実施期間中ではないから、 時刻は変わらない。

中には、「痴漢は夏に多く出るし、まさか朝には出ないだろうから、 冬季こそ時計を二時間ぐらい早めて、 学校はいまの午前6時半ごろを始業とし、 午後4時には家に帰りつけるようにしよう、 なんて考えている人がいるかもしれない。 (フランスは緯度が高いので冬の朝はなかなか明るくならず、 そのため、朝に痴漢が出ることがある、と聞いたことがある。)

2007-12-09 (0) 17:50:02 +0900

ここから先はこれからアップロードする。

2007-12-13 (4) 03:04:52 +0900

回文>「下痢糞、栗毛」(げりくそくりげ)

「下痢糞」は「げりぐそ」と連濁が起こるような気もする。

2007-12-09 (0) 00:47:03 +0900

回文>「麒麟児、人力」(きりんじじんりき)

「人力」は人力車の略(かも)。

2007-12-09 (0) 00:45:40 +0900

回文>「キリンに五人力」(きりんにごにんりき)

本文ナシ

2007-12-09 (0) 00:44:31 +0900

回文>「酒の池、次兄の袈裟」(さけのいけじけいのけさ)

回文>「紀国屋文左衛門燃え、残部や肉の木」》 に関連(しているかもしれない)。

2007-12-09 (0) 00:40:21 +0900

回文>「海老名は花冷え」(えびなははなびえ)

本文ナシ

2007-12-09 (0) 00:38:30 +0900

左手で字を書く>初等幾何学の図を書いてみると「まだまだ」と気づく

初等幾何学の証明に出てくるような図を書いてみると、 まだまだへろへろであることに気づく。 特に、「\」のような傾きの線がへたである。

文字はそれなりに書けるようになってきたが、 右手のようにきちんと線をコントロールできてはいない、ということのようだ。 字画が少し曲がっても「まあ、見られるからいいか」と満足していたわけだ。

これを克服すべく、「点を打ってからそれらを結んで四角形を書き、 さらに対角線もひく」という練習をしている。 四角形そのものはかなりうまく書けるようになってきたので、 それはいきなり書いて、対角線の練習をするのもよさそうだ。 「四角形+対角線」のうえに「ヘ」の字を載せると家の絵になるが、 これは一筆書きで書けるので早書きの練習にもなりそう。

2007-12-09 (0) 00:31:20 +0900

実家から口語訳の中形聖書を持ってきた / 代わりに大形を置いてきた

このサイズが一番読みやすいような気がして、 先日、仕事で実家に泊まった際に、実家に置いておいた中形を持ってきた。 教会に備えつけのも、このサイズが多かったようだ。

代わりに、大形聖書を置いてきた。 本が大きくなったとか、本だなが小さくなったと思うといけないので、 事情を説明して。

通読が、なぜかサムエル下 11 のバテシバ事件の直前で止まっていたが、 一気に進んでいまは列王紀下を読んでいる。

大型の封筒をばらしてカバーをかけた。

2007-12-06 (4) 01:48:51 +0900

「情報」と「情報処理」が違うのは「敗戦投手」と「敗戦処理投手」が違う…

…のと同じようなもの。

大学の授業科目の分類を「情報系」「情報処理系」などと呼んだりする。 前者は情報科学という学問が思い浮かぶのに対し、 後者はスキルを重視する実習型科目が思い浮かぶ。 後者を軽視するわけではないが、前者と混同してはいけないだろう。

ほかに、「処理」の有無でニュアンスが違ってくるものとして考えついたのが 「敗戦投手」「敗戦処理投手」である。 後者は、実力の劣るピッチャーがつとめるもの。 もう試合の決着はついているから、まず敗戦投手にはならない。 敗戦投手になるのは、勝利投手になる可能性もあった投手であって、 それなりに期待されているピッチャーである。

2007-12-06 (4) 01:36:10 +0900

「お忍び」を「押し伸び」と思うやつはいないか

本文ナシ

2007-12-06 (4) 01:35:09 +0900

そばとスパゲティーの合い盛りがあるとうっかり後者も音を立てて食いそうだ

そんなメニュー、まずないだろうが。

2007-12-06 (4) 01:33:33 +0900

ABC文体(もどき)>「k³は」(計算上は)

本文ナシ

2007-12-06 (4) 01:31:19 +0900

ABC文体(もどき)>「k²学」(形而上学)

本文ナシ

2007-12-06 (4) 01:27:19 +0900

回文>「全裸体、至らんぜ」(ぜんらたいいたらんぜ)

「至らん全裸体」(いたらんぜんらたい)も可。

2007-12-06 (4) 01:26:20 +0900

回文>「海苔屋さえ餌やりの」(のりやさええさやりの)

逆にして「餌やりの海苔屋さえ」(えさやりののりやさえ)としてもよい。

2007-12-06 (4) 01:24:39 +0900

ΑΒΓ文体>「ρχ」(老獪)

本文ナシ

2007-12-06 (4) 01:23:15 +0900

社会全体で「単に『5時』といえば『午後5時』」のような規則を決めたら

前項に関連。

現実問題として、普通のオフィスでは 「午前5時」に予定がはいることはまれだろうし、 「午後8時」に予定がはいることもまれであってほしい。 (残業はあるだろうが。)

社会全体で「単に『5時』といえば『午後5時』」と決めておけば、 使いやすい12時制で、「午前」「午後」を省いて短く言うことができる。 現行では、業界によって規則が違うように思うので、 それを統一しよう、というのである。 (午前5時のほうは「午前5時」などと言えばよい。)

私の感覚では、 「午前8時」台から「午後7時」台までを「8時」……「7時」としたいところだ。 家を出るのはそれ以前になるだろうが、 それは家庭内でのみ話題になる時刻だから問題ないと考える。

付)これまた、考えてみただけである。

2007-12-06 (4) 01:11:53 +0900

時刻を A1, A2, A3, ..., A9, 10, 11, 12, P1, P2, P3, ..., P9 時と書く案

私は手帳に書くときは24時制を使っているが、 会話では12時制が使われることが多い。 しかし、12時制で「午前10時」のように書くと長くなる。 午前8時を「A8 時」などと書くことにより、 実際に予定がはいる可能性のある時刻だけを、二文字で書けないだろうか、 と考えてみた。 (この A は AM の A である。午後なら PM の P とする。)

一つの案は、午前1時から順に A1, A2, A3, ..., A9, 10, 11, 12, P1, P2, P3, ..., P9 と書くものだ。午後10時、午後11時、正子の書き方は考えていないが、 そんな時間帯に予定がはいることはまずない。 (12 時を 0 時と呼べば「A0 時」「P0 時」と区別できるが、 12 時のほうがよく使われるし、真夜中に予定がはいるとも思えない。)

付) 考えてみただけで、使ってみる気はない。 現実には、 午前7時より前や午後7時よりあとに仕事の予定がはいることはまれだから、 単に「5時」のように言ってもまぎれない。

2007-12-06 (4) 00:59:17 +0900

握らなくても書ける、特殊な形のペンを作れないか?

前項にも少々関係するが、前項の内容に気づく前から思っていたこと。

現行のペンは、たいてい、握らなければ持てない。 しかし、握るのではなく、 何かの中に指を入れて保持するペンも考えられなくはない。 ペンの裏側に、親指、人差し指、中指のためのくぼみがあり、 そこに指を入れるとペン全体が手に覆いかぶさるようになる、 などの形が考えられよう。

この場合、 ペンを保持するためには力がいらないから、 すべての力を文字の形を美しくするためにつぎ込むことができると思う。

2007-12-06 (4) 00:38:55 +0900

身体障害者にも使いやすいよう配慮されている文具の中に、 このようなものがあった。 「す」の字の第二画のような形をしており、 穴に指を入れて握ることも可能になっている。

2008-01-18 (5) 01:42:34 +0900

左手でグリップ付きボールペンを使って、握る位置が右手と違うことを発見

左手で文字を書くのが苦にならなくなったし、 それなりの字は書けるので、計算用紙は主に左手で書いているのだが、 ふと、グリップ付きボールペンを使ってみて、 握る位置が右手と左手とで違っていることを発見した。 右手ではグリップの下の部分を持つのに対し、 左手ではグリップよりも下の、金属部分を握ることになってしまう。 右手と同じ位置を握ってみると、ペンが斜めになりすぎてインクが出ない。

それで気づいたのだが、いままでは、 左手は右手よりもつぶれたような持ち方になっていた。 たとえば、人差し指の付け根の関節の、紙面からの高さは、 明らかに左手のほうが低い。 右手に合わせて矯正してみたところ、 握り方はしっかりしたが、筆圧は弱くなったように思う。 つまり、 いままでは、握る力と紙に押し付ける力とがごっちゃになっていたようなのだ。 この、右手と同じ持ち方にしてみると、一画一画をきちんとコントロールできる。 いままで書けていたように書けなくなったと感じる部分もあるが、 それは練習で克服できそうだ。

付) 左右の手で、ペンの持ち方が完全に同じにはならないと思う。 左から右への横書きが多いから、 左手で書くとすでに書いた文字が手のかげになってしまう。 右手ではそれはほとんど起こらない。 それを防ぐためには、 左手でペンを持つ持ち方を変える必要があるかもしれない。 ペン先を手前に向けるなど、 右手とは全く違う持ち方をしている人もいる。

付) じゃあ、私の右手の握り方は標準的かというと、そうとは限らない。 それなりにきちんとした文字は書けるので、それほどはずれてはいないと思うが。

2007-12-05 (3) 22:56:05 +0900

NHKフランス語会話>十一月 28 日(水曜日)放送分

前半については 《NHKフランス語会話>五月 30 日(水曜日)放送分》 も参照。

冒頭。 今週は二人のかわいらしい少女が今週のフレーズを言うが、 また、冒頭は音声が出なかった。 前期もこうだったっけ?

初級コーナーで文法の説明をする先生の右手人差し指にばんそうこうが巻かれているような。 (《NHKフランス語会話>五月 30 日(水曜日)放送分》 に書いたように中級コーナーでは拍手されるが、その際には見えていない。)

フランツさんのコーナー。 80 を quatre fois vingt と説明し、字幕に 4×20 と出たが、 「4倍した20」だから 20×4 のほうが正確かも。 ただ、これだと quatre-vingts にならないが。

2007-12-05 (3) 22:27:06 +0900

NHKフランス語会話>十一月 21 日(水曜日)放送分

前半は 《NHKフランス語会話>五月 23 日(水曜日)放送分》 も参照。

冒頭は毎回、街角で見かけた人がきょうのフレーズを言うもの。 今回、若いお嬢さんが「Comment est-il?」を三度言うが、 一度目は音声が出ない。 放送時に見ていたときは、 ヘッドホン端子とヘッドホンの間に入れているボリューム付延長コードのボリューム調節を誤ったかと思った。 ボリュームを上下反対に手にすれば、 音量を上げたつもりが下げることになるからだ。 (前の番組の間は音量をやや下げておいて、始まると上げるのである。)

que の e が落ちて qu' になることの説明の際、 「qu'」のつづりを「キュ、ユ、アポストロフ」と読み上げられることが多いようだが、 音だけで言うなら「que が qu' になります」だし、 つづりで説明するなら「キュ、ユ、ウがキュ、ユ、アポストロフになります」だろう。 (もちろん、 このハイブリッドが最もわかりやすいのでこれを採用しておられるのだろうと思うが。)

NHKフランス語会話>五月 23 日(水曜日)放送分》 で指摘した、 中級コーナーの字幕は直っていなかった。 一つのカッコに複数の語もはいる、と考えれば間違いではないのだが。

付) 本項は一週間前にほとんど書きあがっていたが、 推敲の時間がとれなかったもので。

2007-12-05 (3) 21:07:51 +0900

matter-of-factly は語構成上は(たぶん) "matter-of-fact"ly

でも、ハイフネーションからは matter, of, factly がつながったように見える。 matter-of-factness も同様。

日本語のわかち書きを考える際の参考になるかと思って。

2007-11-28 (3) 20:53:31 +0900

「穴谷」って姓はあるかな? 「貴方(あなた)に」と同音、ってだけだけど

「あなたにあなたに夢中」って歌の文句を昔聞いたことがあるような。 Google で「穴谷」は約 3910 件。 でも人名ではないような。

2007-11-24 (6) 19:38:09 +0900

ここから先はこれからアップロードする。

2007-12-05 (3) 21:01:17 +0900

フランス語>cet は単独でも最後の t が発音されるとなぜわかるんだろう?

ふと気になったのだが、cet は、辞書によれば、 単独で発音した場合にも最後の t が発音される。 そのことはどうしてわかるんだろう? この語は、次に母音または無音の h で始まる語がくる場合にしか現れない。 だから、「cet の t は単独では発音されないが、 必ずリエゾンが起こるので、結果として発音されることになる」 という可能性もあるのでは?

(いい意味の単語ではないが)pet の t は発音されない。 met もそうだ。net の t は発音される。

2007-11-21 (3) 21:52:12 +0900

実際の文章の中で発音されるときは、この t は必ず発音される。 だから、cet を単独で発音するときも t は発音されるものとみなされる。 こう考えればよいのかな?

2008-01-17 (4) 00:49:55 +0900

NHKフランス語会話>十一月 14 日(水曜日)放送分

前半については 《NHKフランス語会話>五月 16 日(水曜日)放送分》 も参照のこと。

右宗さんは [r] の発音が苦手ということになっている。 それなのに、-er 動詞の例として rentrer をあげるなんて先生は意地悪だなあ、 と思ったのだが、ミカエルさんといっしょに rentrer の変化を練習するところでは、 きちんとのどの奥で [r] の音が出せている。 巻き舌になってしまうのは“お芝居”だったのか。

中級コーナー。 フランツさんの字幕に「Qui est Rao?」と出たが、 この R は [r] に発音されていないような気がする。 少なくともフランス語の [r] ではないような。

2007-11-21 (3) 21:51:32 +0900

きょうのサイゼリヤ>帰り際にトリフアイスクリームを

この季節に書かねばならないはがきのことを考えると、 あまり飲むのは賢明とは言えない。 昨夜は、酔いが覚めてから今年の年賀状の整理をし、 とある人が私の氏名を正字で書いてくれていたのに気づいてちょっとうれしかった。 (ただし、ふだんは正字・新字の別にはこだわらない。 アルファベットの「Q」を、「Oに点」で書くか、一筆書きのように書くか、 の違いのようなものだと考えているからである。)

トリフアイスクリームは 369 円もする。 本体定価 350 円の四色ボールペンは八掛けの店なら 280 円。 消費税の 14 円を加えても、294 円あれば買えてしまう。 それと比べると、ああ、ぜいたく。 このデザートは、かなり量があるので、二人で一つでちょうどよいぐらいだ。 そういえば、昨年の夏、とある事情で、 とある人とアイスクリームだったかシャーベットだかを分けて食べた記憶が……。

付) 本項は、 書き始めたときは酔っていたので何かもう少しおもしろいことが書けそうな気がしていたのだが、 書いてみたらつまらなくなってしまった。

2007-11-20 (2) 19:22:42 +0900


すのもの Sunomono