Lying Devils

日々いろんなことを呟いていく。そんな感じ?

【C言語】今日の謎【未解決】

前書き

 春休みになって色々だらけてて最近暇です。本当は運転免許所とかを取らなきゃいけないんですけど時期的なものを逃した感があってもう色々としんどい感じになっててどうしよう見たいな感じです。

 いつもはApexばっかやってるのでその時間を有効活用したいと思ってます。

本題

 以下の様なプログラムを作ったんですよね。(github未上げ状態なので直書きします)

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

int roll(int x, int y, int mode){

 int count;
 int x2 = x;
 int num = 0;

 srand((unsigned int)time(NULL));

 for(int i = 0; i < x2; i++){
    num += rand() % (y + 1);
    printf("[%d回目] ... %d\n",i + 1,num);
    if(mode == 1){
       count++;
    }
 }
 return num;
}

int main(){

 int mode,x,y;
 char d;

 puts("-----xdy-----\n x ... ダイスの個数\n y ... ダイスの面数\n-------------");
 while(mode != 0 && mode != 1){

    puts("モードを選んでください\n0 ... no mantion\n1 ... for DX3rd");
    scanf("%d",&mode);
    if(mode != 0 && mode != 1)
    puts("ERROR. PUT AGAIN.");
 }

 puts("xdyの形で入力してください");
 scanf("%*c%d %c %d",&x,&d,&y);

 printf("%d面ダイスを%d個振ります\n",y,x);
 printf("出目は%d\n",roll(x,y,mode));

 return 0;
}

 最近身内でTRPGをする事が多いので、それの為に&勉強がてらCoCとDX3rd用のダイスプログラムを作ってみようと思った訳です。

 色々ゴミが挟まってますが、やらんとする事は、xdyの形で定義されたダイスロールをしてもらって、それぞれその結果を出してもらうプログラムです。

 ちょうどいいので合計値まで出してもらおうと思ってnumを順番に足し合わせる事もしています。

 この時点で「num合計してる位置が違うからちゃんと出力されないやろ」と思われますがそこじゃないんです。

 これをコンパイルして起動したログの結果が以下の様に出たんです。

$ ./xdy
-----xdy-----
 x ... ダイスの個数
 y ... ダイスの面数
-------------
モードを選んでください
0 ... no mantion
1 ... for DX3rd
0
xdyの形で入力してください
10d10
10面ダイスを10個振ります
[1回目] ... 5
[2回目] ... 14
[3回目] ... 16
[4回目] ... 23
[5回目] ... 26
[6回目] ... 33
[7回目] ... 39
[8回目] ... 42
[9回目] ... 48
[10回目] ... 49
出目は49

 ほかにも何度かやったのですが、明らかに最後に出た値が出力されてるんですよね…。

 これを合計するのを別の変数に格納したら正常に動いたので多分加算処理に何かしら問題があるんだとは思うのですがなんでなのかはさっぱり分かりません。

 そして手を変えたら普通に動いたからもうこれ以上触る事もない気がします。

 ただどうしてこうなるのかなと気になったのでとりあえず書いてみた感じです。

まとめ

 よくわかんない! 以上!ノシ

追伸

 ちなみに出来上がったものがこちらになりますつ https://github.com/merlioneko/test/blob/main/xdy.c

【C言語】for文について【解決済み】

前書き

 初めてMarkdownでブログを書きます。でも、Githubを使ってる人間だったら普通に使えないといけないと思うのでこれを機にしっかり勉強したいと思いました。

 ちなみに今回も学校課題のものです。

本題

 学校課題でモンテカルロ法のプログラムを作ってみろと言われたので、四分円の面積内に点が打たれる確率から円周率を求めてみればいいのではないかと思ってとりあえずそれをやろうとしました。

 どうせレポートをその後に書くので、レポートに書きやすい様に試行回数を10倍ずつ変化させて出力すればいいかな、と思ってやってみたんですよ。

 初めはif文であらかじめ設定した値になるまで試行をさせたらいいのかなと思ったんですが、せっかくだし収束幅が幾らぐらいになったら止める様にすれば、どれぐらいにすれば適切な精度で出せるかが判ると思ったのでやってみたんです。

 コードはここです↓

github.com

 結果がこれです

start
1
set
calc ave
start plc_xy
0
calc place_x
calc place_y
calc place ave
start r_clc
1.000000
start plc_xy
0
calc place_x
calc place_y
calc place ave
start r_clc
2.000000
start plc_xy
0
calc place_x
calc place_y
calc place ave
start r_clc
3.000000
start plc_xy
0
calc place_x
calc place_y
calc place ave
start r_clc
3.000000

 率直に言って泣きました。

問題

 今回問題となるのはコードの中でもここの部分だと思うんですよね。

int r_calc(double place_x, double place_y){
 puts("start r_clc");
 if(sqrt(pow(place_x,2) + pow(place_y,2)) <= 100){
    return 1;
 }else{
    return 0;
 }
}

 double plc_xy(int N){

     double place_x,place_y,X;

     puts("start plc_xy");
     for(int i = 0; i < N; i++){   //   ここ
    printf("%d\n",i);
    puts("calc place_x");
        place_x = rand() % 101;
    puts("calc place_y");
    place_y = rand() % 101;
    puts("calc place ave");
    X += r_calc(place_x, place_y);
    printf("%f\n",X);
 }

(こうやって見ると自分のインデントがたがたですね…)

 ともかくも、この部分で正しくi++処理されてないのが原因っぽいです。

 iの定義を外に出したりいろいろしていますが、どうにもうまくいきません。

 何となく気になってNの入力が失敗してるんじゃないかとか考えてみてログを確認したらこんなんになってました(若干コードは変えました)。*1

start
1
set
calc ave
start plc_xy
N = 1
calc plc 0
calc place_x
calc place_y
calc place ave
start r_clc
calc ave 1.000000
start plc_xy
N = 1
calc plc 0
calc place_x
calc place_y
calc place ave
start r_clc
calc ave 1.000000
start plc_xy
N = 1
calc plc 0
calc place_x
calc place_y
calc place ave
start r_clc
calc ave 2.000000
start plc_xy
N = 1
calc plc 0
calc place_x
calc place_y
calc place ave
start r_clc
calc ave 3.000000
start plc_xy
N = 1
calc plc 0
calc place_x
calc place_y
calc place ave
start r_clc
calc ave 4.000000
start plc_xy
N = 1076887552
calc plc 0
calc place_x
calc place_y
calc place ave
start r_clc

 ええ…


現状

 色々何が起きてるのかさっぱりわからないのでとりあえずここに愚痴っておきます。

 どうしようもなければどこかに質問でも投げておかないとなあと思いました。

 以上です。ノシ


 puts("start plc_xy");
 printf("N = %d\n",N);                                        
 for(i = 0; i < N; i++){   
    printf("calc plc %d\n",i);                              
    puts("calc place_x");                                
    place_x = rand() % 101;                          
    puts("calc place_y");                         
    place_y = rand() % 101;                   
    puts("calc place ave");               
    X += r_calc(place_x, place_y);   
    printf("calc ave %f\n",X);   
}

追記(2021/1/23)

 すごく単純な問題でした。

 Githubの履歴を見て頂ければわかりますが、単純にプログラムミスでした。

 配列の定義がおかしくなってます。

 はい。

 泣きたくなりました。

 みなさんもしっかり配列の初期化には注意しましょうね。

 (´;ω;`)ノシ

*1:Nが見られるようになってます

【C言語】疑問ができたのでとりあえず上げる【解決済み】

 

 前略

 学校の課題で自然言語処理をCでやれって言われたのでやってみる事にしました。というか期間がもう間近に迫っていて結構しんどいんですよね。

 自然言語処理をする上で必要な情報に、出てくる文字の数というのがあると思います。例えばAが何回出ました、Bが何回出ました、といったものですね。

 なのでそれをとりあえず計算する必要があるので、そういった感じの処理を描こうとしたわけです。

  まずはstrをアスキーコード分、つまり128定義して初期化した後、以下の様な感じで1ずつ足していくといいかなと思った訳です。

 

28while( (ch = fgetc(fp) ) != EOF){
29 if(isalpha(ch) != 0 || isblank(ch) != 0 || ch == '\n'){
30
31    fputc(ch,sf);
32    if(i < 10){
33        str[ch]++;
34        i++;
35        printf("%c = %d\n",ch,str[ch]);
36    }
37 }else{
38
39 fputc(' ',sf);
40
41 }
42 }

 

  これならB = 2みたいな感じで出てくるのかなーと思ったんですけど

 

h = 1
e = 1
r = 15775232
l = 10
o = 32688
c = 32688
k = 1
= -204839807
H = 1
o = 32689

  結果的にこうなったんですよね。

 なんだこの値!?しかも律義に加算処理はされてるし……

 

 

 値が変なのは'r','l','o','c',' 'の値、具体的には114,108,111,99です。

 まだl移行が全ておかしいとかならばまだ色々考えられたのですが、cまでおかしいとなるとちょっと理解が及びません。

 ちなみに、str[246]にした場合には不具合がなくなってました。なんでや(困惑)

 

h = 1
e = 1
r = 1
l = 1
o = 1
c = 1
k = 1
= 1
H = 1
o = 2

 

  割とマジで理解が及んでないので誰か教えてくれねえかなあ見たいなのをかねてブログに纏めました。

 本当はこのくだりを何かしらそのような質問サイトに送るのが一番なんだとは思うんですけど、ぶっちゃけ面倒なのでここで済ませました。

 切羽詰まったら出そうかなとかは思ってるいや限界だ今出すねッ!

 

 少なくともchへの値の導入にミスってる様子はないので、多分配列エラーなんだろうなとは思います。初期化が上手くいっていないか、そう思って初期化の文をもう一度出力する文章もつけました。

 

13
14 fp = fopen("test.txt", "r");
15 if( ( fp == NULL) ){ 16 printf("test.txt FILE OPEN ERROR");
17 return -1;
18 }
19
20 sf = fopen("output.txt","w");
21 if(sf == NULL){
22 printf("output.txt FILE OPEN ERROR");
23 return -1;
24 }
25
26 27 for(i; i < 128; i++){
28 str[i] = 0;
29 }
30 for(i; i < 128; i++){
31 printf("str[%d] ... %d\n",i,str[i]);
32 }
33
34 i = 0;
35 while( (ch = fgetc(fp) ) != EOF){

:~/programs/works$ gcc litr.c -o litr
:~/programs/works$ ./litr
104 ... h = 1
101 ... e = 1
114 ... r = 15775232
108 ... l = 10
111 ... o = 32621
99 ... c = 32621
107 ... k = 1
32 ... = -1039616911
72 ... H = 1
111 ... o = 32622

 

 

どういうことなの……

 

 


 

 

 現場からは以上です

 ではノシ

 

 

 追記:ちょっとまって?なんでプログラムの一部が変な風になってるの?HTML画面見てもそれっぽい記述ないよ?なにしてくれてんの??

 追記2:プログラムははてな記法で書いた方がソースコードの色付けができるのを知ったので今後はそうする事にしますっていうかそうじゃねえなんで勝手にリンクが貼られてんのかをきいてんだおれはよおおおおお

 追記3:(重ねたらだめなの!?ふざけんな*1

 追記4:泣きの追記です。というか、すごく初歩的なミスだったことが判りました。

 ここの部分なんですけど、普通にi = 0ってするの忘れてますね、ええ。多分、したつもりだったんでしょうね。だからだと思いました。というか、そうでした。

:~/programs/works$ gcc litr.c -o litr
:~/programs/works$ ./litr
str[0] ... 0
str[1] ... 0
str[2] ... 0
str[3] ... 0
str[4] ... 0
str[5] ... 0
str[6] ... 0
str[7] ... 0
str[8] ... 0
str[9] ... 0
str[10] ... 0
str[11] ... 0
str[12] ... 0
str[13] ... 0
str[14] ... 0
str[15] ... 0
str[16] ... 0
str[17] ... 0
str[18] ... 0
str[19] ... 0
str[20] ... 0
str[21] ... 0
str[22] ... 0
str[23] ... 0
str[24] ... 0
str[25] ... 0
str[26] ... 0
str[27] ... 0
str[28] ... 0
str[29] ... 0
str[30] ... 0
str[31] ... 0
str[32] ... 0
str[33] ... 0
str[34] ... 0
str[35] ... 0
str[36] ... 0
str[37] ... 0
str[38] ... 0
str[39] ... 0
str[40] ... 0
str[41] ... 0
str[42] ... 0
str[43] ... 0
str[44] ... 0
str[45] ... 0
str[46] ... 0
str[47] ... 0
str[48] ... 0
str[49] ... 0
str[50] ... 0
str[51] ... 0
str[52] ... 0
str[53] ... 0
str[54] ... 0
str[55] ... 0
str[56] ... 0
str[57] ... 0
str[58] ... 0
str[59] ... 0
str[60] ... 0
str[61] ... 0
str[62] ... 0
str[63] ... 0
str[64] ... 0
str[65] ... 0
str[66] ... 0
str[67] ... 0
str[68] ... 0
str[69] ... 0
str[70] ... 0
str[71] ... 0
str[72] ... 0
str[73] ... 0
str[74] ... 0
str[75] ... 0
str[76] ... 0
str[77] ... 0
str[78] ... 0
str[79] ... 0
str[80] ... 0
str[81] ... 0
str[82] ... 0
str[83] ... 0
str[84] ... 0
str[85] ... 0
str[86] ... 0
str[87] ... 0
str[88] ... 0
str[89] ... 0
str[90] ... 0
str[91] ... 0
str[92] ... 0
str[93] ... 0
str[94] ... 0
str[95] ... 0
str[96] ... 0
str[97] ... 0
str[98] ... 0
str[99] ... 0
str[100] ... 0
str[101] ... 0
str[102] ... 0
str[103] ... 0
str[104] ... 0
str[105] ... 0
str[106] ... 0
str[107] ... 0
str[108] ... 0
str[109] ... 0
str[110] ... 0
str[111] ... 0
str[112] ... 0
str[113] ... 0
str[114] ... 0
str[115] ... 0
str[116] ... 0
str[117] ... 0
str[118] ... 0
str[119] ... 0
str[120] ... 0
str[121] ... 0
str[122] ... 0
str[123] ... 0
str[124] ... 0
str[125] ... 0
str[126] ... 0
str[127] ... 0
104 ... h = 1
101 ... e = 1
114 ... r = 1
108 ... l = 1
111 ... o = 1
99 ... c = 1
107 ... k = 1
32 ... = 1
72 ... H = 1
111 ... o = 2

 

 俺のキレ芸に何の意味があったんだろうか。

 涙が出ちゃう。女の子だもん

 というわけで解決です。

 みなさんも変数を定義するときはちゃんと()内でやろうな!

 あとプログラムをはてなブログに貼るときは編集ははてな記法かMa…Mなんとかを使うといいと思うお!

*1:半ギレ

覚え書きメイクライ

 

 Ubuntu18.04LTS環境でのSteam版DmC:Devil May Cryの覚え書きです。

 

【内容】

 1.インストールまでの流れ

 2.DefaultEngine.iniとDevilinput.iniの場所と編集の仕方


 

                   1.インストールまでの流れ

 基本的には普通にLinuxでSteamをインストールしてProtonを起動すればよし。(参考→[Proton] Ubuntu 18.04 で Windows 向け Steam ゲームをやる - under-identified’s diary

 一応その流れもざっくり。

 

  1. 公式ページからSteamをDL
  2. 多分Ubuntuソフトウェアからインストールすることになると思うのでそこからインストールする
  3. 起動させてログインしたら設定を開いて、左枠のSteam Play→「Enable Steam Play for supported titles.」と「他のすべてのタイトルでSteam Playを有効化」にチェックを入れる(Protonは最新のでいいと思う

 あとはWineやjoysticなど各自で必要だと思うものを入れればよし。ちなみに個人的にはグラボを積んでないのでkisakはいれてないです。余裕のあるやつだけやれ!

 

 一通り終わったら次(参考→https://www.youtube.com/watch?v=nEJ5JDgVL48)。

  1. NET Frame Work4.0(https://www.microsoft.com/ja-jp/download/details.aspx?id=17851)をDLする。
  2. DLしたのを/home/(ユーザー名)/.local/share/Steam/steamapps/common/DmC Devil May Cryを開いて中にあるdotNetFx40_Client_x86_x64の名前に変えておきかえる(Steamのライブラリから歯車→管理→ローカルファイルを閲覧が簡単)

 動画ではこのあとも色々やってますが、僕はこれだけで起動したのでおkにしました。

 もしダメそうなら動画をじっくり見てください。

 

 

 

                2.DefaultEngine.iniとDevilinput.iniの場所と編集の仕方

 多分多くの人がSteam版DmCをやって思うのが「デビルトリガーと銃特殊のボタン変更できない」っていうことじゃないでしょうか。そして多分、このサイトに行くと思います。→Steam Community :: Guide :: How to Disable Intros and modify Devil Trigger Controls

 ただもともとWindows版でだされてるのでこれもWindowsのアドレスに則ってるのでどこにあるのかわからんって人が結構いると思います。いなきゃいないでいいです。とりあえず僕はわからなかったのでちょうどいいので変更の仕方についても一緒に書きます。

 

 DefaultEngine.iniは、

 /home/(ユーザー名)/.local/share/Steam/steamapps/common/DmC Devil May Cry/DevilGame/Config

 の中にあります。

 見つけたら適当なエディタで開いて、中にある[FullScreenMovie]を探して、

+StartupMovies=Capcom
+StartupMovies=Ninjatheory
+StartupMovies=UE3_logo
+StartupMovies=AMDLogo
+StartupMovies=Save_360
+StartupMovies=black

 の文章のはじめに;をつけてください。

;+StartupMovies=Capcom
;+StartupMovies=Ninjatheory
;+StartupMovies=UE3_logo
;+StartupMovies=AMDLogo
;+StartupMovies=Save_360
;+StartupMovies=black

 こういうことですね。これで冒頭のムービーがまるまるカットできると思います。(どうでもいいけど暗転までムービー処理なんですね)

 

 Devilinput.iniは

/home/(ユーザー名)/.local/share/Steam/steamapps/compatdata/220440/pfx/drive_c/users/steamuser/My Documents/My Games/UnrealEngine3/DevilGame/Config

 の中にあります。

 ダンテの場合は[DevilGame.DVButtonMap]を、バージルの場合は[VergilDLC.DVButtonMap_Vergil]のキーを変えることで変更ができます(もしかしたら違うかもしれないです。いやぁすんませーん)。絶対に変えられないキーコンフィグもここをいじれば変えられます。

 英語なので多分どれを触れば行動のコンフィグが変えられるか判ると思います。

 デビルトリガーはDEVILTRIGGER、銃特殊はGUNSPECIALの行を見ます。

 初期状態では

    DEVILTRIGGER=NTB_V_GAME3

    GUNSPECIAL=NTB_V_GAME2

 になっていると思います。NTB_V_GAME2が銃+ジャンプ、NTB_V_GAME3がカメラ視点+ロックオン変更の意味みたいです(どこで定義されてるのかわからないです誰か教えてください)。

 与えられるキーコンフィグもなんとなく見たらどれがどれとかわかると思います。

 一応NTB_NONEにすると定義なしになるのでいらない行動はなしにするといいと思います(でもその行動があるのかと言われても謎です)。

 変更をするキーコンフィグを見つけたら、下部にあるDEFAULT〜の部分も一緒に変えてください。

 わかりやすく言うと、GUNSPECIALを変えるときは、GUNSPACIALとDEFAULT_GUNSPECIALの両方を変える必要があるということです。

 理由は不明ですが私の環境ではGUNSPECIALだけ変えてもうまく反映されませんでした。

 またEVADE1は絶対にないと何かしら変なことが起きることがあったので、ここから変更するのはやめたほうがいいと思います。

 僕はGUNSPECIAL=NTB_DPADDOWNだけ変更をしました(Defaultのほうも!)。方向キー下で銃特殊が出ます。

 

 少し長くなったのでまとめます。

 

  1.  /home/(ユーザー名)/.local/share/Steam/steamapps/compatdata/220440/pfx/drive_c/users/steamuser/My Documents/My Games/UnrealEngine3/DevilGame/ConfigからDevilinput.iniを開く
  2. 変えたいキーコンフィグをDEFAULTも一緒に変更する

 

 これだけですね。まとめたら異様に短くなって不安。

 


 

 もしかしたら嘘言ってる場合もあるので何かあった場合にはコメントで指摘してください。

 また私もわからない部分があるので誰か知ってたら教えてください。

以上。