合計 昨日 今日

関数をうまく分けられません

[このトピックは解決済みです]

フォーラムルール
フォーラムルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Name: MRMR
[URL]
Date: 2017年8月10日(木) 22:04
No: 1
(OFFLINE)

 関数をうまく分けられません

初めまして、最近C言語の勉強を始めた初心者です。
Dxライブラリとサウンドノベル風のサンプルプログラムを利用して関数を分割する練習をしようと考えたのですが、うまくいきません。
下記のコードを実行すると、行の端に行くと”フ”が表示されてしまいます。

コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
 #include "DxLib.h" 
#include <math.h>
 
// 文字のサイズ
#define MOJI_SIZE 24
 
// 仮想テキストバッファの横サイズ縦サイズ
#define STRBUF_WIDTH    24
#define STRBUF_HEIGHT    20
 
 
 
void Kaigyou(int *CursorX, int *CursorY, char StringBuf[STRBUF_HEIGHT][STRBUF_WIDTH * 2 + 1]);        // テキストバッファの改行処理関数
 
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    ChangeWindowMode(TRUE);
 
    char StringBuf[STRBUF_HEIGHT][STRBUF_WIDTH * 2 + 1];    // 仮想テキストバッファ
    int CursorX, CursorY;                        // 仮想画面上での文字表示カーソルの位置
    int SP, CP;                            // 参照する文字列番号と文字列中の文字ポインタ
    int EndFlag = 0;                            // 終了フラグ
    int KeyWaitFlag = 0;                        // ボタン押し待ちフラグ
    int Count;                            // フレームカウンタ
 
    char String[][256] =
    {
        " ゲームプログラムを習得するための一番の近道はとにかく沢山プログラムを組む",
        "ことである。B" ,
        "@ プログラムの参考書にはゲームのプログラムの方法なんて何も書かれていない、B",
        "変数、B配列、B関数、Bループ、B条件分岐…Bこれらすべての説明はゲームで何に使うか",
        "なんてどこにも書いていない、Bせいぜい住所録を題材にした例がある程度である。B" ,
        "C プログラムは習うより慣れろなのでプログラムを組むに当たって少しでも知識が",
        "つけば後はそこからは掘り下げ、広げていけば良いわけで、Bプログラムの参考書を",
        "読んでいて少しでも何か出来るような気がしたらそこでとにかくプログラム",
        "を打ってみることが大事である。E",
    };
 
    char OneMojiBuf[3];    // 1文字分一時記憶配列
    int i, j;
 
    SetGraphMode(640, 480, 16);
    if (DxLib_Init() == -1)    // DXライブラリ初期化処理
    {
        return -1;                // エラーが起きたら直ちに終了
    }
 
    // 描画位置の初期位置セット
    CursorX = 0;
    CursorY = 0;
 
    // 参照文字位置をセット
    SP = 0;    // 1行目の
    CP = 0;    // 0文字
 
               // フォントのサイズセット
    SetFontSize(MOJI_SIZE);
 
    // フォントの太さを変更
    SetFontThickness(1);
 
    // フォントのタイプをアンチエイリアスフォントに変更
    ChangeFontType(DX_FONTTYPE_ANTIALIASING_EDGE_8X8);
 
    // 描画先を裏画面にセット
    SetDrawScreen(DX_SCREEN_BACK);
 
 
    // フレームカウンタ初期化
    Count = 0;
 
    // 仮想テキストバッファを初期化
    for (i = 0; i < STRBUF_HEIGHT; i++)
    {
        for (j = 0; j < STRBUF_WIDTH * 2; j++)
        {
            StringBuf[i][j] = 0;
        }
    }
 
    // ループ
    while (ProcessMessage() == 0 && CheckHitKey(KEY_INPUT_ESCAPE) == 0)
    {
        // サウンドノベル風文字列描画処理を行う
        // ただし終了フラグが1だった場合は処理をしない
        if (EndFlag == 0)
        {
            char  Moji;
 
            // ボタン押し待ちフラグがたっていた場合はボタンが押されるまでここで終了
            if (KeyWaitFlag == 1)
            {
                if (ProcessMessage() == 0 && CheckHitKeyAll() != 0)
                {
                    // ボタンが押されていたら解除
                    KeyWaitFlag = 0;
                }
            }
            else
            {
                // 文字の描画
                Moji = String[SP][CP];
                switch (Moji)
                {
                case '@':    // 改行文字
 
                             // 改行処理および参照文字位置を一つ進める
                    Kaigyou(&CursorX, &CursorY,StringBuf);
                    CP++;
 
                    break;
 
                case 'B':    // ボタン押し待ち文字
 
                             // ボタンが離されるまで待つ
                    while (ProcessMessage() == 0 && CheckHitKeyAll() != 0) {}
 
                    // ボタン押し待ちフラグをたてる
                    KeyWaitFlag = 1;
                    CP++;
 
                    break;
 
                case 'E':    // 終了文字
 
                             // 終了フラグを立てるおよび参照文字位置を一つ進める
                    EndFlag = 1;
                    CP++;
 
                    break;
 
                case 'C':    // クリア文字
 
                             // 仮想テキストバッファを初期化して描画文字位置を初期位置に戻すおよび参照文字位置を一つ進める
                    for (i = 0; i < STRBUF_HEIGHT; i++)
                    {
                        for (j = 0; j < STRBUF_WIDTH * 2; j++)
                        {
                            StringBuf[i][j] = 0;
                        }
                    }
 
                    CursorY = 0;
                    CursorX = 0;
                    CP++;
 
                    break;
 
                default:    // その他の文字
 
                            // 1文字分抜き出す
                    OneMojiBuf[0] = String[SP][CP];
                    OneMojiBuf[1] = String[SP][CP + 1];
                    OneMojiBuf[2] = '\0';
 
                    // 1文字テキストバッファに代入
                    StringBuf[CursorY][CursorX * 2] = OneMojiBuf[0];
                    StringBuf[CursorY][CursorX * 2 + 1] = OneMojiBuf[1];
 
                    // 参照文字位置を2バイト勧める
                    CP += 2;
 
                    // カーソルを一文字文進める
                    CursorX++;
 
                    // テキストバッファ横幅からはみ出たら改行する
                    if (CursorX >= STRBUF_WIDTH) Kaigyou(&CursorX, &CursorY, StringBuf);
 
                    break;
                }
 
                // 参照文字列の終端まで行っていたら参照文字列を進める
                if (String[SP][CP] == '\0')
                {
                    SP++;
                    CP = 0;
                }
            }
        }
 
        // 画面のクリア
        ClsDrawScreen();
 
        // 背景エフェクトの描画
        {
            int Color;
 
            Color = (int)(sin(Count / 100.0) * 80.0 + 125.0);
            DrawBox(0, 0, 640, 480, GetColor(Color, 0, 0), TRUE);
            Count++;
        }
 
        // テキストバッファの描画
        for (i = 0; i < STRBUF_HEIGHT; i++)
        {
            DrawString(8, i * MOJI_SIZE, StringBuf[i], GetColor(255, 255, 255));
        }
 
        // 裏画面の内容を表画面に反映させる
        ScreenFlip();
    }
 
    DxLib_End();                // DXライブラリ使用の終了処理
 
    return 0;                    // ソフトの終了
}
 
 
 
// 改行関数
void Kaigyou(int *CursorX, int *CursorY, char StringBuf[STRBUF_HEIGHT][STRBUF_WIDTH * 2 + 1])
{
    // 描画行位置を一つ下げる
    (*CursorY)++;
 
    // 描画列を最初に戻す
    *CursorX = 0;
 
    // もしテキストバッファ縦幅からはみ出るならテキストバッファを縦スクロールさせる
    if (*CursorY >= STRBUF_HEIGHT)
    {
        int i, j;
 
        for (i = 1; i < STRBUF_HEIGHT; i++)
        {
            for (j = 0; j < STRBUF_WIDTH * 2; j++)
            {
                StringBuf[i - 1][j] = StringBuf[i][j];
            }
        }
 
        // 描画行位置を一つあげる
        (*CursorY)--;
    }
}



デバッグもしましたが、どこをどう改善すればいいのかもわからない状態です。
環境はWindows10でVisual Studio 2017 community、Dxライブラリ使用です。
乱文で申し訳ないのですが、教えてください。よろしくお願いいたします。

Name: peot
[URL]
Date: 2017年8月11日(金) 08:43
No: 2
(OFFLINE)

 Re: 関数をうまく分けられません

StringBufの初期化が正しくされてないようです。
下のように書き換えたところ余計な文字は表示されなくなりました。
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
// 仮想テキストバッファを初期化
for (i = 0; i < STRBUF_HEIGHT; i++)
{
    for (j = 0; j < STRBUF_WIDTH * 2 + 1; j++)
    {
        StringBuf[i][j] = 0;
    }
}


もしくは宣言時に初期化してしまえばより簡潔に書けます。
コード[C++]: 全て選択
1
2
// 仮想テキストバッファ
char StringBuf[STRBUF_HEIGHT][STRBUF_WIDTH * 2 + 1] = { 0 };

Name: MRMR
[URL]
Date: 2017年8月11日(金) 11:51
No: 3
(OFFLINE)

 Re: 関数をうまく分けられません

[解決!]

初期化のところでしたか!
改行処理やif文の条件ばかり気にしてました…
もっと勉強しないとだめですね(^▽^;)
peotさん、ありがとうございました!


Return to C言語何でも質問掲示板

オンラインデータ

このフォーラムを閲覧中のユーザー: なし & ゲスト[18人]