🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

1101閲覧

コマンドラインで無限ループするプログラムで現象をなくしたい

退会済みユーザー

退会済みユーザー

総合スコア0

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2020/12/07 06:55

以下の画像ですがコマンド画面上で無限ループしてキー入力などを実装しているのですがなぜ画面がチカチカするのでしょうか?画像上ではどうしても画面がチカチカするという現象を捉えずらいのです。どうすればいいのでしょうか?そういうものなのでしょうか?その場合どうすればいいのでしょうか?

イメージ説明
イメージ説明

cpp

1#include <iostream> 2#include <algorithm> 3#include <vector> 4#include <compare> 5#include <filesystem> 6#include <map> 7 8#include "Main_Screen.hpp" 9#include "SoundPlayer.hpp" 10#include "Input_Key.hpp" 11 12/* 13* out_of_range の例外の出てる場所がわからない 14*/ 15// ------------------------------------------------------------------ コンストラクタ 16Main_Screen::Main_Screen() :mAllMemory(80)//メモリの大きさ 17{ 18 //デバッグ 関係 19 mText.file("Log.txt"); //ログを書き込むテキストファイルを指定 20 21 22 //---------------- 再生ゲージ 関係 23 mPlayingMemory = 0;//時間を蓄積 24 25 //---------------- 曲の状態 関係 26 mPlayList_Num = 0; //曲のリスト数 27 mNo_Playing = false; //何も再生していない場合 28 mEnter = false; //選んだ曲を決定 29 mEnter_push = false; //mEnter の連打防止 30 31 //---------------- ファイルパス 関係 32 mRootDir_Path = "\MusicTest_wav"; //初期ディレクトリ 33 mNowDir_Path = mRootDir_Path; //現在いるディレクトリをルートディレクトで初期化 34 mNowPath_num = 0; //前後のパスを調べるための値 35 mIndexString.push_back(mRootDir_Path); //mNowPath_numの値を使って前後をのパスを取得 36 mCursorDir_pos[mIndexString[mNowPath_num]] = 0; //カーソルの場所(数値)をパスの値を使って調べる 37 mIndexString.push_back(mRootDir_Path); //ファイルパスの履歴 38 // ファイル名と ファイルパスを設定 39 for (std::filesystem::directory_entry itr : std::filesystem::directory_iterator(mRootDir_Path)) 40 { 41 mPlayList_Name.push_back(itr.path().filename().string()); //ファイル名 42 mPlayList_Path.push_back(itr.path().string()); //ファイルパス 43 } 44 45 mNowSelect_Path = mPlayList_Path.at(0); //適当に最初のファイルパスを設定 46 mPlayList_Num = (int)mPlayList_Name.size(); //プレイリスト数を取得 47 48 /* 49 for (std::vector<std::string>::iterator itr = mPlayList_Name.begin(); itr != mPlayList_Name.end(); itr++) 50 { 51 52 } 53 */ 54} 55// ------------------------------------------------------------------ 56 57 58 59// ------------------------------------------------------------------ キー入力受付 60void Main_Screen::Input() 61{ 62 63 KeyCode Key = mInput.InputDown(); //キーコード入力 64 65 if (Key == KeyCode::Space)//再生と一時停止 66 { 67 mText.Write("Log.txt", "KeyCode::Space\n"); 68 69 printf("SPACE \n"); 70 71 // --------------------------------------------------- ディレクトリ選択 Left key ← 72 }else if (Key == KeyCode::Left) 73 { 74 mText.Write("Log.txt", "KeyCode::Left\n"); 75 76 77 78 79 80 81 //曲リストと曲パス、局の数を 再設定 82 mPlayList_Name.clear();//曲リストを初期化 83 mPlayList_Path.clear();//曲パスリストを初期化 84 85 for (std::filesystem::directory_entry itr : std::filesystem::directory_iterator(mNowDir_Path)) 86 { 87 mPlayList_Name.push_back(itr.path().filename().string()); //ファイル名 88 mPlayList_Path.push_back(itr.path().string()); //ファイルパス 89 } 90 91 mPlayList_Num = (int)mPlayList_Name.size(); //プレイリスト数を取得 92 93 } 94 // --------------------------------------------------- 95 96 97 98 // --------------------------------------------------- ディレクトリ選択 Right key → 99 else if (Key == KeyCode::Right) 100 { 101 mText.Write("Log.txt", "KeyCode::Right\n"); 102 103 104 105 106 107 108 //曲リストと曲パス、局の数を 再設定 109 mPlayList_Name.clear();//曲リストを初期化 110 mPlayList_Path.clear();//曲パスリストを初期化 111 112 for (std::filesystem::directory_entry itr : std::filesystem::directory_iterator(mNowDir_Path)) 113 { 114 mPlayList_Name.push_back(itr.path().filename().string()); //ファイル名 115 mPlayList_Path.push_back(itr.path().string()); //ファイルパス 116 } 117 118 mPlayList_Num = (int)mPlayList_Name.size(); //プレイリスト数を取得 119 } 120 // --------------------------------------------------- 121 122 else if (Key == KeyCode::Up)//曲セレクト ↓ 123 { 124 mText.Write("Log.txt", "KeyCode::Up\n"); 125 printf("UP \n"); 126 if (mPos_y > 0) 127 { 128 mPos_y--; 129 } 130 } 131 else if (Key == KeyCode::Down)//曲セレクト ↑ 132 { 133 mText.Write("Log.txt", "KeyCode::Down\n"); 134 printf("DOWN \n"); 135 if (mPos_y < mPlayList_Num - 1) 136 { 137 mPos_y++; 138 } 139 } 140 141 142 // 決定キー 143 else if (Key == KeyCode::Enter)//Enter 144 { 145 printf("ENTER \n"); 146 if (mEnter == false) 147 { 148 mEnter = true; 149 } 150 } 151 152 153} 154// ------------------------------------------------------------------ 155 156 157// ------------------------------------------------------------------ 158void Main_Screen::Update() 159{ 160 Input(); //キー入力 161 162 163 if (mNo_Playing == false) 164 { 165 mPlayer.InputFile((const char*)"Music.wav"); //ファイル読み込み 166 167 //再生時間のゲージを作成 168 mMemsec = (float)mPlayer.mAllsec / mAllMemory; //1秒のメモリの大きさ 169 mPlayingMemory = mMemsec; 170 mPlayer.Play(); 171 mNo_Playing = true; 172 } 173 174 //選択中の曲にパスを変更 175 if (mEnter == true) 176 { 177 try { 178 mPlayer.mFilePath = mPlayList_Path.at(mPos_y); //曲のパスを設定 179 } 180 catch (std::exception e) 181 { 182 printf("mEtner Error: %s", e.what()); 183 } 184 mPlayer.Stop();//一旦再生終了 185 186 187 mPlayPath = mPlayList_Path.at(mPos_y); //現在再生中の曲にパスを設定 188 mPlayer.Play(); //再生 ! 189 190 191 192 mEnter = false; 193 194 } 195} 196// ------------------------------------------------------------------ 197 198 199// -------------------------- ループ ---------------------------------- 200void Main_Screen::Loop() 201{ 202 // -------------------------------------- 203 while (true) 204 { 205 GenerateOutput(); //描画 206 Update(); //計算 207 208 // Sleep(16); 209 system("cls"); //画面クリア 210 } 211 // -------------------------------------- 212} 213// -------------------------- ------------------------------------ 214 215 216// ------------------------------------------------------------------- 217void Main_Screen::GenerateOutput() 218{ 219 220 printf("Sound Player\n\n"); //ソフトタイトル 221 222 printf("FilePath: %s\n", mPlayer.mFilePath.c_str()); //ファイルパス 223 224 //チャンネル数 225 if (mPlayer.mChannels == AL_FORMAT_STEREO16) 226 { 227 printf("Channels: Stereo 16 bit\n"); 228 } 229 else 230 { 231 printf("Channels: Monaural 16 bit\n"); 232 } 233 234 printf("BisPerSample: %llu bit\n", mPlayer.mBisPerSample); //ビットパーフレーム 235 printf("SamleRate %llu Khz\n\n", mPlayer.mSampleRate); //サンプルレート 236 237 printf("Music Status: "); 238 //再生か一時停止中 239 if (mPlayer.mPause == false) 240 { 241 printf("NOW PLAYING ♪"); 242 printf("\n"); 243 } 244 else 245 { 246 if (mNo_Playing == true) 247 { 248 printf("STOP\n"); 249 } 250 else 251 { 252 printf(" PAUSE\n"); 253 } 254 } 255 256 alGetSourcef(mPlayer.mSource, AL_SEC_OFFSET, &mPlayer.mTime); 257 printf("Time: %.2f / %llu\n", mPlayer.mTime, mPlayer.mAllsec); 258 printf("\n\n\n\n\n\n\n");//改行 259 260 261 printf("mPos_y: %d",mPos_y); 262 263 // ------ 再生時間ゲージ 264 if (mPlayingMemory <= mPlayer.mTime) { 265 mPlayingMemory += mMemsec; 266 mNowMemory++; 267 } 268 269 270 printf("\n"); 271 272 273 printf("PLAY: [ "); 274 for (int i = 0; i < mNowMemory; i++) 275 { 276 mPrint.RenderText(Color_Code::Black, Color_Code::Green, "#"); 277 } 278 279 for (int i = mAllMemory; i > mNowMemory; i--) 280 { 281 printf(" "); 282 } 283 284 printf(" ]"); 285 286 287 printf("\n\n\n"); 288 // ------------------- 曲リスト 289 int i = 0; 290 // printf("mPos_y: %d",mPos_y); 291 mPrint.RenderText(Color_Code::Green,Color_Code::Black,"----------------------- PLAY LIST -----------------------\n\n"); 292 const std::string str = mPlayList_Path.at(mPos_y); 293 for (std::vector<std::string>::const_iterator itr = mPlayList_Name.begin(); itr != mPlayList_Name.end(); itr++) 294 { 295 296 if (mPos_y == i) 297 { 298 printf(" > ");//カーソル 299 mPrint.RenderText(Color_Code::Green, Color_Code::White, "%s", itr->c_str()); 300 301 //ディレクトリの場合 < DIR > 302 if (std::filesystem::directory_entry(mPlayList_Path.at(i)).is_directory() == true) 303 { 304 printf(" < DIR > \n"); 305 } 306 else 307 { 308 printf("\n"); 309 } 310 } 311 else 312 { 313 printf(" %s", itr->c_str());//曲 314 315 //ディレクトリの場合 < DIR > 316 if (std::filesystem::directory_entry(mPlayList_Path.at(i)).is_directory() == true) 317 { 318 printf(" < DIR > \n"); 319 } 320 else 321 { 322 printf("\n"); 323 } 324 325 326 } 327 i++; 328 } 329 330 331} 332// ------------------------------------------------------------------- 333 334// ------------------------------------------------------------------- 335Main_Screen::~Main_Screen() 336{ 337 338} 339// ------------------------------------------------------------------- 340 341

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2020/12/07 07:03

int main()が無いので実際にどう動き始めているか分かりません。Main_Screen::Loop()が実質、本体だとして、 > void Main_Screen::Loop() > { > // -------------------------------------- > while (true) > { > GenerateOutput(); //描画 > Update(); //計算 > > // Sleep(16); > system("cls"); //画面クリア > } > // -------------------------------------- > } であれば、超高速で手動で描画、clsコマンド実行、を繰り返しているかたちですから、チラついて当然です。
guest

回答2

0

ベストアンサー

KeyCode Key = mInput.InputDown();

が,キー入力待ちではなくて,入力状態に関わらず処理が進むような物であるならば,
無限ループ内で問答無用で

  • 消去 : system("cls");
  • 表示 : (printfかな?)

を繰り返しているのでしょうから,まぁ,ちらつくでしょう.

表示の更新が必要なときだけ更新するならば軽減できるのではないでしょうか.
(結局消去したタイミングというのは見えるでしょうが)


Windowsのコンソールアプリなら WriteConsoleOutput() を使って一気に書き換えるとか.

投稿2020/12/07 07:10

編集2020/12/07 07:19
fana

総合スコア11990

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/12/07 12:15

WriteConsoleOutput() をやりましたがやはり同じ現象が置きます。
fana

2020/12/08 02:48

system("cls"); は取っ払ってますか?
退会済みユーザー

退会済みユーザー

2020/12/08 03:37

取っ払うと今度は画面が消えず下に続いてしまいます。両方試しました。
fana

2020/12/08 03:54

? WriteConsoleOutput() って,Writeする範囲を引数で指定するのでは?
guest

0

clsコマンドで毎回全画面クリアして全描画しているからでしょう。
コマンドラインで描画制御するのは厳しいので、ひとつの画面で何でもやろうとせず、再生中はせいぜい時間表示の更新にとどめるなどがよいかと。
その場合、\nではなく\rとすると、その行の先頭にカーソル位置が戻るのでチラつかずに済むかと思います。

投稿2020/12/07 07:14

ttyp03

総合スコア17000

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問