beginner11
@beginner11

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

VSCodeでC言語日本語入力が上手くいかない!

C言語で簡単な戦闘ゲームを作成しており、今は名前入力の所で行き詰っています。
開発環境はVSCodeです。

しかし、様々な方法を試してもVSCodeのターミナルでは、以下のように全角での名前入力を受け付けてくれません(半角英数字だと問題なく上手くいきます)。
qiita質問投稿用画像.png

プログラムのテキストは100行以上にわたりますが、問題点があればご指摘お願いします。

#pragma warning(disable: 4996)

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<conio.h>
int playerHP=300;

int enemyHP=300;

int damage;
int damage_m;
int guard;
int attack;
int attack_m;
int enemyattack;
int enemyguard;

int playerMP=200;
int MPuse=25;

unsigned long ll=0;

char x[256];
char str[1000];

int calcAttack(){
	return rand()%10+40;
}

int calcAttack_M(){
	return rand()%10+80;
}

int calcAttack_SP(){
	return rand()%10+80;
}

int calcGuard(){
	return rand()%40;
}

	void title(){
		printf("******************************************\n");
		printf("*  かんたんクエスト~勇者よいそげ!~    *\n");
		printf("******************************************\n");
	}

	void name(){
		printf("名前を入力してください>>>");
		scanf("%s",str);
		puts("\n");
		printf("%sよ、行け!",str);
	}

	void standby(){
		printf("aキー(通常攻撃)またはmキー(魔法攻撃)、gキー(防御)、rキー(回避)を押してください。\n");
		puts("何かキーを打ってください。\n");
	}

	void message(){
		puts("\n");
		printf("***プレイヤーのターン!***\n");
	}

	void message2(){
		printf("かわせるか?");
	}

	void message_enemy(){
		puts("\n");
		printf("***敵のターン!***\n");
	}

	void guard_message(){
		attack=calcAttack();
		enemyguard=calcGuard();
		enemyHP=enemyHP-(attack/2-enemyguard/2);
		printf("「防御魔法・ディフェンサー!」\n");
		printf("敵は攻撃を防いだ!\n");
		printf("%dのダメージ!\n",attack/2-enemyguard/2);
	}

	void guard_message2(){
		attack_m=calcAttack();
		enemyguard=calcGuard();
		enemyHP=enemyHP-(attack_m/2-enemyguard/2);
		printf("「防御魔法・ディフェンサー!」\n");
		printf("敵は攻撃を防いだ!\n");
		printf("%dのダメージ!\n",attack_m/2-enemyguard/2);
	}

	void clear_message(){
		puts("\n");
		puts("************************");
		printf("魔物討伐成功だ!\n");
		printf("GAME CLEAR!!\n");
		puts("************************");
	}

	void gameover(){
		puts("\n");
		printf("GAME OVER\n");
	}

void Turn(){
	guard=calcGuard();
	enemyguard=calcGuard();
	int attack_m=calcAttack_M();
	int attack=calcAttack();
	int enemyattack=calcAttack();
	int special=calcAttack_SP();
	char x=0;
    char str;

	x=getche();
	if(damage<=enemyHP){
		switch(x){
			case 'a':
				message();
				printf("「喰らえ!」\n");
				printf("%sの攻撃!\n",&str);
				if(enemyHP>0){
				message_enemy();
				}
				if(rand()%100<90){
				enemyHP=enemyHP-(attack/2-enemyguard/4);
				printf("敵:%dのダメージ!\n",attack/2-enemyguard/4);
					if(playerHP>0){
						if(enemyHP>0){
							printf("「死ね!」\n");
							playerHP-=(enemyattack/2-guard/4);
							printf("敵の攻撃!\nプレイヤー:%dのダメージ!\n",enemyattack/2-guard/4);
						}
					}
				}else{
					guard_message();
				}
				break;
				
			case 'm':
				message();
			if(playerMP>0){
				printf("「ファイアシュート!」\n");
				printf("%sの攻撃!\n",&str);
				if(enemyHP>0){
				message_enemy();
				}
				if(rand()%100<90){
				enemyHP=enemyHP-(attack_m/2-enemyguard/4);
				playerMP=playerMP-MPuse;
				printf("敵:%dのダメージ!\n",attack_m/2-enemyguard/4);
					if(playerHP>0){
						if(enemyHP>0){
							printf("「何をッ!」\n");
							playerHP=playerHP-(special/2-guard/4);
							printf("敵の攻撃!\nプレイヤー:%dのダメージ!\n",special/2-guard/4);
						}
					}
				}else{
					playerMP=playerMP-MPuse;
					guard_message2();
				}
			}else{
				printf("MPが足りない!\n");
				printf("「魔法が使えない……、なんてこった!」\n");
			}
				break;
			case 'g':
				message();
				printf("「盾でガード!」\n");
				playerHP=playerHP-(enemyattack/2-guard/4);
				message_enemy();
				printf("「無駄だ!」\n");
				printf("だが、プレイヤーは敵の攻撃を防御した!\nプレイヤー:%dのダメージ!\n",enemyattack/2-guard/4);
				break;
			case 'r':
				message();
				printf("「避けるぞ!」\n");
				message2();
				message_enemy();
				if(rand()%100<15){
					printf("「無駄な悪あがきを!」\n");
					playerHP-=(enemyattack/2-guard/4);
					printf("敵の攻撃!\nプレイヤー:%dのダメージ!\n",enemyattack/2-guard/4);
					break;
				}else{
				printf("「しまった!」\n");
				printf("敵の攻撃を回避した!\n");
				}
				break;
			default:
				puts("\n");
				printf("aキー(通常攻撃)またはmキー(魔法攻撃)、gキー(防御)、rキー(回避)を押してください\n");	
				break;
			}
		}
	}


int main(){
	srand((unsigned int)time(0));
	title();
	name();
	while(1){
		puts("\n");
		printf("プレイヤーのHP:%d MP:%d\n敵のHP:%d\n",playerHP,playerMP,enemyHP);

	standby();

	Turn();

		if(enemyHP<=0){
			printf("敵を倒した!\n");
			clear_message();
			break;
		}

		if(playerHP<=0){
			printf("プレイヤーは敗れた...\n");
			gameover();
			break;
		}
	}
	return 0;
}

以上が私の作成したプログラム文で、特に見て欲しいのはname()関数のところです。
恐らくここに不具合があると考えているのですが、どうやっても上手くいきません。
恐縮ですが、このプログラム文の欠陥を教えていただけないでしょうか。

0

2Answer

ロケールを変更し、wprintf()やwscanf()を使ってもこのような表示になります……。qiita質問用スクショ.png

0Like

Comments

  1. @beginner11

    Questioner

    訂正したバージョンはこちらになります。

    #include<stdio.h>
    #include<stdlib.h>
    #include<time.h>
    #include<conio.h>
    #include<locale.h>
    #include<wchar.h>
    int playerHP=300;
    
    int enemyHP=300;
    
    int damage;
    int damage_m;
    int guard;
    int attack;
    int attack_m;
    int enemyattack;
    int enemyguard;
    
    int playerMP=200;
    int MPuse=25;
    
    unsigned long ll=0;
    
    char x[256];
    wchar_t str[1000];
    
    int calcAttack(){
    	return rand()%10+40;
    }
    
    int calcAttack_M(){
    	return rand()%10+80;
    }
    
    int calcAttack_SP(){
    	return rand()%10+80;
    }
    
    int calcGuard(){
    	return rand()%40;
    }
    
    	void title(){
    		wprintf(L"******************************************\n");
    		wprintf(L"*  かんたんクエスト~勇者よいそげ!~    *\n");
    		wprintf(L"******************************************\n");
    	}
    
    	void name(){
    		wprintf(L"名前を入力してください>>>");
    		wscanf(L"%s",str);
    		puts("\n");
    		wprintf(L"%sよ、行け!",str);
    	}
    
    	void standby(){
    		wprintf(L"aキー(通常攻撃)またはmキー(魔法攻撃)、gキー(防御)、rキー(回避)を押してください。\n");
    		wprintf(L"何かキーを打ってください。\n");
    	}
    
    	void message(){
    		wprintf(L"\n");
    		wprintf(L"***プレイヤーのターン!***\n");
    	}
    
    	void message2(){
    		wprintf(L"かわせるか?");
    	}
    
    	void message_enemy(){
    		puts("\n");
    		wprintf(L"***敵のターン!***\n");
    	}
    
    	void guard_message(){
    		attack=calcAttack();
    		enemyguard=calcGuard();
    		enemyHP=enemyHP-(attack/2-enemyguard/2);
    		wprintf(L"「防御魔法・ディフェンサー!」\n");
    		wprintf(L"敵は攻撃を防いだ!\n");
    		wprintf(L"%dのダメージ!\n",attack/2-enemyguard/2);
    	}
    
    	void guard_message2(){
    		attack_m=calcAttack();
    		enemyguard=calcGuard();
    		enemyHP=enemyHP-(attack_m/2-enemyguard/2);
    		wprintf(L"「防御魔法・ディフェンサー!」\n");
    		wprintf(L"敵は攻撃を防いだ!\n");
    		wprintf(L"%dのダメージ!\n",attack_m/2-enemyguard/2);
    	}
    
    	void clear_message(){
    		puts("\n");
    		puts("************************");
    		wprintf(L"魔物討伐成功だ!\n");
    		wprintf(L"GAME CLEAR!!\n");
    		puts("************************");
    	}
    
    	void gameover(){
    		puts("\n");
    		wprintf(L"GAME OVER\n");
    	}
    
    void Turn(){
    	guard=calcGuard();
    	enemyguard=calcGuard();
    	int attack_m=calcAttack_M();
    	int attack=calcAttack();
    	int enemyattack=calcAttack();
    	int special=calcAttack_SP();
    	char x=0;
        char str;
    
    	x=getche();
    	if(damage<=enemyHP){
    		switch(x){
    			case 'a':
    				message();
    				wprintf(L"「喰らえ!」\n");
    				wprintf(L"%sの攻撃!\n",&str);
    				if(enemyHP>0){
    				message_enemy();
    				}
    				if(rand()%100<90){
    				enemyHP=enemyHP-(attack/2-enemyguard/4);
    				wprintf(L"敵:%dのダメージ!\n",attack/2-enemyguard/4);
    					if(playerHP>0){
    						if(enemyHP>0){
    							wprintf(L"「死ね!」\n");
    							playerHP-=(enemyattack/2-guard/4);
    							wprintf(L"敵の攻撃!\nプレイヤー:%dのダメージ!\n",enemyattack/2-guard/4);
    						}
    					}
    				}else{
    					guard_message();
    				}
    				break;
    				
    			case 'm':
    				message();
    			if(playerMP>0){
    				wprintf(L"「ファイアシュート!」\n");
    				wprintf(L"%sの攻撃!\n",&str);
    				if(enemyHP>0){
    				message_enemy();
    				}
    				if(rand()%100<90){
    				enemyHP=enemyHP-(attack_m/2-enemyguard/4);
    				playerMP=playerMP-MPuse;
    				wprintf(L"敵:%dのダメージ!\n",attack_m/2-enemyguard/4);
    					if(playerHP>0){
    						if(enemyHP>0){
    							wprintf(L"「何をッ!」\n");
    							playerHP=playerHP-(special/2-guard/4);
    							wprintf(L"敵の攻撃!\nプレイヤー:%dのダメージ!\n",special/2-guard/4);
    						}
    					}
    				}else{
    					playerMP=playerMP-MPuse;
    					guard_message2();
    				}
    			}else{
    				wprintf(L"MPが足りない!\n");
    				wprintf(L"「魔法が使えない……、なんてこった!」\n");
    			}
    				break;
    			case 'g':
    				message();
    				wprintf(L"「盾でガード!」\n");
    				playerHP=playerHP-(enemyattack/2-guard/4);
    				message_enemy();
    				wprintf(L"「無駄だ!」\n");
    				wprintf(L"だが、プレイヤーは敵の攻撃を防御した!\nプレイヤー:%dのダメージ!\n",enemyattack/2-guard/4);
    				break;
    			case 'r':
    				message();
    				wprintf(L"「避けるぞ!」\n");
    				message2();
    				message_enemy();
    				if(rand()%100<15){
    					wprintf(L"「無駄な悪あがきを!」\n");
    					playerHP-=(enemyattack/2-guard/4);
    					wprintf(L"敵の攻撃!\nプレイヤー:%dのダメージ!\n",enemyattack/2-guard/4);
    					break;
    				}else{
    				wprintf(L"「しまった!」\n");
    				wprintf(L"敵の攻撃を回避した!\n");
    				}
    				break;
    			default:
    				puts("\n");
    				wprintf(L"aキー(通常攻撃)またはmキー(魔法攻撃)、gキー(防御)、rキー(回避)を押してください\n");	
    				break;
    			}
    		}
    	}
    
    
    int main(){
    	setlocale(LC_ALL,"");
    	srand((unsigned int)time(0));
    	title();
    	name();
    	while(1){
    		puts("\n");
    		wprintf(L"プレイヤーのHP:%d MP:%d\n敵のHP:%d\n",playerHP,playerMP,enemyHP);
    
    	standby();
    
    	Turn();
    
    		if(enemyHP<=0){
    			wprintf(L"敵を倒した!\n");
    			clear_message();
    			break;
    		}
    
    		if(playerHP<=0){
    			wprintf(L"プレイヤーは敗れた...\n");
    			gameover();
    			break;
    		}
    	}
    	return 0;
    }
    
  2. いろいろ調べたところ vscode内のターミナルは "chcp 65001"を実行しているにも関わらず入力した文字列をプログラムに渡すときの文字コードは shift-jis(CP932)になるようで
    SetConsoleCPを使って無理やりshift-jisとして受け取るしかなさそうです

    	UINT consoleCP = GetConsoleCP();
    	SetConsoleCP(932);
    
    	char test1[128] = "";
    	scanf("%s", test1);   // shift-jisとしては受け取れる
    
    	SetConsoleCP(consoleCP);
    
    // ============================
    	UINT consoleOutputCP = GetConsoleOutputCP();
    	SetConsoleOutputCP(932);
    
    	printf("%s\n", test1);  // shift-jisを表示する
    
    	SetConsoleOutputCP(consoleOutputCP);
    

    受け取ったshift-jis文字列を utf8に変換すればプログラムに組み込めますが
    そんな面倒くさいことするより日本語入力を諦めるか
    vscodeではなく、setlocaleするだけで日本語入力/表示できる visual studioを使った方がよさそう

  3. @beginner11

    Questioner

    分かりました。ありがとうございます。

Your answer might help someone💌