VL-BASICの3DCGのしくみについて

 

 モデルモード(物体の位置決め)

GPU MATRIX(MODE, MODEL)    モデルモード 

GPU ROTATE                 3.移動した状態で回転

GPU TRANSLATE              2.移動する

GPU ROTATE                 1.その場で回転

GPU SPHERE                 SPHEREに近い方から適用される

行の下から上へと適用されるのは、

行列の計算順序が関係しています。

座標=TRpはTranslate、Rotate、sphereの順で

プログラムを書きますが、

Rの方がp(sphere)に近いので先に効果が

でるといったイメージです。

 

この動作は、OpenGLと同じです。

 

VL-BASICのROTATE、TRANSLATE、行列

などの3DCG用のコマンドは、

数値を変えたりして、どういう動作を

するかを体験しながら慣れていくのが

良いかと思います。

 

より詳しく理解するには、

このブログの

N88-BASICで3DCGの行列(matrix)

シリーズでを見て頂くのが良いかと

思います。

(説明が分かりにくいかもしれませんが

ご了承下さい。)

 

VL-BASIC(N88-BASIC互換?)ホームページへのリンク

ホームページに書いてあるパスワードを入力して、

Readme.txtを読んで、遊んで見て下さい。

 

 

 

Cで3囚人問題
 
N88-BASICで3囚人問題
をCで書いて見ました。
Cコンパイラなどは別途ご用意ください。
 
switch文は、abcが0ならa++;を実行、break;でswitch終了。
break;が無ければb++;も実行。
abcが0ならa++; 1ならb++: 2ならc++;を実行します。
switch文が無いN88-BASICではIF文を使います。
 
久しぶりのgoto文の使い方でアセンブラを思い出しました。

 

/*

---------------------------------------------------------------------

 3囚人問題(Three Prisoners problem)

 

 A,B,Cの3死刑囚の内1人が恩赦を受ける

 Aは看守にB,Cどちらかは死刑になるのだからどちらか教えてほしいと言う。

 看守はBは死刑になると教えてくれた。

 Aが助かる確率は上がったか、という問題。

 (選択はすべて等確率で起こるとする。)

---------------------------------------------------------------------

*/

#include <stdio.h>      /* printfを使用するため   */

#include <stdlib.h>     /* rand,srandを使用するため */

#include <time.h>       /* clockを使用するため   */

static  /* このファイル内部のみで使用できる関数の定義 */

double rnd(void)

{

    return ((double)rand()) / (((double)RAND_MAX)+1.0);

}

/* main関数から実行される */

void main(void)

{

    int a, b, c, i, abc;        /* 変数の定義     */

 

    srand(clock());             /* 乱数の種      */

    a = 0;                      /* Aが助った場合の数 */

    b = 0;                      /* Bが助った場合の数 */

    c = 0;                      /* Cが助った場合の数 */

    for (i = 1; i <= 100000; i++)   /* ゲーム回数  */

    {

nocount:

        abc = (int)(rnd() * 3);    /* 0-2:A-C恩赦  */

        /* A恩赦 → BCから看守がCを選択(1/2)はノーカウント */

        if (abc == 0) if (rnd() < 0.5) goto nocount;

        /* B恩赦 → 看守はCを選択するのでノーカウント */

        if (abc == 1) goto nocount;

        /* C恩赦 → 看守はBを選択するのでカウント */

        switch (abc)

        {

             case 0: a++; break;/* 看守がBを選択時のAの恩赦数 */

             case 1: b++; break;/* 看守がBを選択時のBの恩赦数 */

             case 2: c++; break;/* 看守がBを選択時のCの恩赦数 */

        }

        if ((i % 10000) == 0)

        {

            printf("A = %5d [%6.4f] , ", a, a / (double)i);

            printf("B = %5d [%6.4f] , ", b, b / (double)i);

            printf("C = %5d [%6.4f]\n" , c, c / (double)i);

        }

    }

    getchar();                  /* キー入力待ち */

}

 

three001n.bas

 

100 '---------------------------------------------------------------------
110 ' 3囚人問題(Three Prisoners problem)
120 '
130 ' A,B,Cの3死刑囚の内1人が恩赦を受ける
140 ' Aは看守にB,Cどちらかは死刑になるのだからどちらか教えてほしいと言う。
150 ' 看守はBは死刑になると教えてくれた。
160 ' Aが助かる確率は上がったか、という問題。
170 ' (選択はすべて等確率で起こるとする。)
180 '---------------------------------------------------------------------
190 RANDOMIZE VAL(RIGHT$(TIME$,2))   '--- 乱数の種
200 A = 0                            '--- Aが助った場合の数
210 B = 0                            '--- Bが助った場合の数
220 C = 0                            '--- Cが助った場合の数
230 FOR I=1 TO 100000                '--- ゲーム回数
240   *NOCOUNT
250   ABC = INT(RND(1) * 3)          '--- 0-2:A-C恩赦
260   '--- A恩赦 → BCから看守がCを選択(1/2)したときノーカウント
270   IF ABC = 0 THEN IF RND(1) < 0.5 THEN *NOCOUNT
280   '--- B恩赦 → 看守はCを選択するのでノーカウント
290   IF ABC = 1 THEN *NOCOUNT
300   '--- C恩赦 → 看守はBを選択するのでカウント
310   IF ABC = 0 THEN A = A + 1      '--- 看守がBを選択時のAの恩赦数
320   IF ABC = 1 THEN B = B + 1      '--- 看守がBを選択時のBの恩赦数
330   IF ABC = 2 THEN C = C + 1      '--- 看守がBを選択時のCの恩赦数
340   IF I MOD 10000 THEN *NOPRINT
350     PRINT USING "A = ##### [#.####] , "; A, A / I;
360     PRINT USING "B = ##### [#.####] , "; B, B / I;
370     PRINT USING "C = ##### [#.####]"   ; C, C / I
380   *NOPRINT

 

390 NEXT

 

 

NL-BASICは、下記リンクよりダウンロードできます。

NL-BASIC(N88-BASIC互換?)ホームページへのリンク

Readme.txtを読んで、遊んで見て下さい。

 

 

Cでモンティホール問題

 

N88-BASICでモンティホール問題

Cで書いて見ました。

Cコンパイラなどの環境は別途ご用意ください。

 

if (a == 0) sta++;

Cでは比較に=は使用できません。

C     ==  >=  <=  !=

BASIC =   >=  <=  <>

Cでは、i = i + 1; を、i += 1; や、i++;と書けます。

 

if ((i % 10000) == 0)

余りは、BASICはMOD、Cは%です。

 

printf("Change = %8d , Stay = %8d , ", cha, sta);

%8dは整数を少なくとも8桁表示する。

printf("Change/Stay = %7.5f\n", cha / (double)sta);

%7.5fは実数を小数点以下5桁で、

全体で少なくとも7文字(.含む)表示する。

cha / (double)sta

は、int/doubleとなり、doubleとして計算してくれる。

 

CとBASICのLISTです。

 

/*

---------------------------------------------------------------------

 モンティ・ホール問題(Monty Hall problem)

 

 当たりが1つの3doorから1つを選ぶ

 残り2つの内、外れを開けてもらえる

 残り1つに変えるか、そのままか、どちらが得

---------------------------------------------------------------------

*/

#include <stdio.h>      /* printfを使用するため   */

#include <stdlib.h>     /* rand,srandを使用するため */

#include <time.h>       /* clockを使用するため   */

static  /* このファイル内部のみで使用できる関数の定義 */

double rnd(void)

{

    return ((double)rand()) / (((double)RAND_MAX)+1.0);

}

/* main関数から実行される */

void main(void)

{

    int cha, sta, i, a, b;      /* 変数の定義    */

 

    srand(clock());             /* 乱数の種     */

    cha = 0;                    /* 変えて当たった数 */

    sta = 0;                    /* 変えず当たった数 */

    for (i = 1; i <= 100000; i++)   /* ゲーム回数  */

    {

        a = (int)(rnd() * 3);   /* a:0-2選択(0を当たりとする)  */

        b = (a)? 0 : (int)(rnd() * 2)+1;    /* b:0-2開いた残り */

        if (a == 0) sta++;      /* aのままで当たった数     */

        if (b == 0) cha++;      /* bに変えて当たった数     */

        if ((i % 10000) == 0)

        {

            printf("Change = %8d , Stay = %8d , ", cha, sta);

            printf("Change/Stay = %7.5f\n", cha / (double)sta);

        }

    }

    getchar();                  /* キー入力待ち */

}

 

monty001n.bas

 

100 '---------------------------------------------------------------------

110 ' モンティ・ホール問題(Monty Hall problem)

120 '

130 ' 当たりが1つの3doorから1つを選ぶ

140 ' 残り2つの内、外れを開けてもらえる

150 ' 残り1つに変えるか、そのままか、どちらが得

160 '---------------------------------------------------------------------

170 RANDOMIZE VAL(RIGHT$(TIME$,2)) '--- 乱数の種

180 CHA = 0                        '--- 変えて当たった数

190 STA = 0                        '--- 変えず当たった数

200 FOR I=1 TO 100000              '--- ゲーム回数

210   A = INT(RND(1) * 3)          '--- A:0-2選択(0を当たりとする)

220   IF A     THEN B = 0 ELSE B = INT(RND(1) * 2)+1 '--- B:0-2開いた残り

230   IF A = 0 THEN STA = STA + 1  '--- Aのままで当たった数

240   IF B = 0 THEN CHA = CHA + 1  '--- Bに変えて当たった数

250   IF I MOD 10000 THEN *NOPRINT

260     PRINT USING "Change = ######## , Stay = ######## , "; CHA; STA;

270     PRINT USING "Change/Stay = #.#####"; CHA / STA

280   *NOPRINT

290 NEXT

 

NL-BASICは、下記リンクよりダウンロードできます。

NL-BASIC(N88-BASIC互換?)ホームページへのリンク

Readme.txtを読んで、遊んで見て下さい。

 

 

Cで確率

 

N88-BASICで確率をCで書いてみました。

 

CとBASICのLISTです。

/* ... */はコメントですので参考にして下さい。

出来るだけBASICに寄せて書いています。

CプログラムはCut&pasteして下さい。

Cコンパイラー環境は各自で準備して下さい。

 

/*

---------------------------------------------------------------------

  コインを表が出るまで投げた回数nが奇数か偶数かを当てる確率

---------------------------------------------------------------------

*/ 

#include <stdio.h>      /* printfを使用するため   */

#include <stdlib.h>     /* rand,srandを使用するため */

#include <time.h>       /* clockを使用するため   */

static          /* このファイル内部のみで使用できる関数の定義 */

double rnd(void)/* 引数(パラメータ)なし、関数の値double(実数) */

{               /* 0以上1未満の乱数を返す          */

    return ((double)rand()) / (((double)RAND_MAX)+1.0);

}

/* main関数から実行される */

void main(void)

{

    int odd, even, max, i, n;       /* 変数の定義        */

 

    srand(clock());                 /* 乱数の種         */

    odd  = 0;                       /* 奇数回で終了したゲーム数 */

    even = 0;                       /* 偶数回で終了したゲーム数 */

    max  = 1;                       /* 投げた回数の最大値    */

    for (i = 1; i <= 100000; i++)   /* ゲーム回数        */

    {

        n = 0;                      /* 投げた回数        */

repeat:

        n++;                        /* 投げた回数(n = n + 1;)  */

        if (rnd() < 0.5) goto repeat;   /* 裏ならもう一度    */

        if (n % 2) odd++; else even++;

        if (n > max) max = n;       /* 投げた最大数       */

        if ((i % 10000) == 0)

        {

            printf("奇 = %8d , ", odd );

            printf("偶 = %8d , ", even);

            printf("奇/偶 = %8.5f\n", odd / (double)even);

        }

    }

    printf("max %d\n", max);

    getchar();                      /* キー入力待ち       */

}

 

coin001.bas

 

100 '---------------------------------------------------------------------

110 ' コインを表が出るまで投げた回数nが奇数か偶数かを当てる確率

120 '---------------------------------------------------------------------

130 RANDOMIZE VAL(RIGHT$(TIME$,2)) '--- 乱数の種

140 ODD  = 0                       '--- 奇数回で終了したゲーム数

150 EVEN = 0                       '--- 偶数回で終了したゲーム数

160 MAX  = 1                       '--- 投げた回数の最大値

170 FOR I=1 TO 10000               '--- ゲーム回数

180   N = 0                        '--- 投げた回数

190   *REPEAT

200     N = N + 1                  '--- 投げた回数

210   IF RND(1) < 0.5 THEN *REPEAT '--- 裏ならもう一度

220   IF N MOD 2 THEN ODD = ODD + 1 ELSE EVEN = EVEN + 1

230   IF N > MAX THEN MAX = N      '--- 投げた最大数

240   IF I MOD 1000 THEN *NOPRINT

250     PRINT USING "奇 =######## , "; ODD;

260     PRINT USING "偶 =######## , "; EVEN;

270     PRINT USING "奇/偶 =##.#####"; ODD / EVEN

280   *NOPRINT

290 NEXT

300 PRINT "max"; MAX

 

NL-BASICは下記リンクよりダウンロードできます。

NL-BASIC(N88-BASIC互換?)ホームページへのリンク

Readme.txtを読んで、遊んで見て下さい。