- 何回勝負か(何回勝利したら終了か)の入力を促す。(= n)
- じゃんけんをして、結果を表示する。
- 勝者が一人になるまでじゃんけんを繰り返す。
- プレイヤーとNPC1~3のいずれかがn勝したら、プレイヤーの成績(a勝b敗c分け)を表示し、プログラムを終了する。
以上の動作をするプログラムを作成するにあたり、下記のようなソースコードを書きましたが、一部の組み合わせ(後述)において、間違った勝敗の判定が表示される不具合が発生しております。
3日間不具合の発見に尽力しましたが発見できなかったため、こちらの掲示板にて質問をさせていただきました。諦めが早いようではございますが、ソースコードのどの部分に問題があるのかご教示を賜りたく存じます。
開発環境
OS:Windows7
コンパイラ:MinGW (GCC)
間違った勝敗判定がされる組み合わせ(プレイヤー NPC1 NPC2 NPC3 の順)
※括弧内は正しい判定
グー パー パー パー : 引き分け (プレイヤーのみが負け)
グー チョキ チョキ チョキ : 引き分け (プレイヤーのみが勝ち)
パー グー グー チョキ : プレイヤーとNPC2が負け (引き分け)
パー チョキ チョキ グー : プレイヤーとNPC2が勝ち (引き分け)
グー パー パー チョキ : 同上
チョキ グー グー パー : 同上
ソースコード
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int pc;
int npc[3];
int judge;
int npc_only = 0;
int win_no, lose_no, draw_no;
int npc_win[3] = {0};
char *hd[] = {"グー", "チョキ", "パー"};
char pc_name[] = {"Player"};
char npc_name[][5] = {"NPC1", "NPC2", "NPC3"};
void initialize(void);
void janken(void);
int two_judge(int h1, int h2);
int three_judge(int h1, int h2, int h3);
int four_judge(int h1, int h2, int h3, int h4);
void count_no(int result);
void disp_result(int result);
void disp_winner(const char *winner);
void two_janken( const char *winner1, const char *winner2, const char *loser1, const char *loser2,
int *winner_v1, int *winner_v2 );
void three_janken( const char *winner1, const char *winner2, const char *winner3,
const char *loser, int *winner_v1, int *winner_v2, int *winner_v3 );
void main_janken(void);
int main(void)
{
int n;
printf("何回勝負しますか:");
scanf("%d", &n);
initialize();
do {
main_janken();
} while (win_no < n && npc_win[0] < n && npc_win[1] < n && npc_win[2] < n);
printf("%d勝%d敗%d分けでした。\n", win_no, lose_no, draw_no);
return 0;
}
void initialize(void)
{
win_no = 0;
lose_no = 0;
draw_no = 0;
srand(time(NULL));
printf("じゃんけんゲーム開始!!\n");
}
void janken(void)
{
int i;
npc[0] = rand() % 3;
npc[1] = rand() % 3;
npc[2] = rand() % 3;
if (!npc_only)
do {
printf("\n\aじゃんけんポン...");
for (i = 0; i < 3; i++)
printf(" (%d)%s", i, hd[i]);
printf(":");
scanf("%d", &pc);
} while (pc < 0 || pc > 2);
}
int two_judge(int h1, int h2)
{
return (h1 - h2 + 3) % 3;
}
/* three_judge関数の返却値
0 引き分け
1 h1が負け
2 h2が負け
3 h3が負け
4 h1が勝ち
5 h2が勝ち
6 h3が勝ち
*/
int three_judge(int h1, int h2, int h3)
{
switch ((h1 + h2 + h3) % 3) {
case 0 : break; /* 引き分け */
case 1 : /* 誰か一人が負け */
switch (two_judge(h1, h2)) {
case 0 : return 3;
case 1 : return 1;
case 2 : return 2;
}
case 2 : /* 誰か一人が勝ち */
switch (two_judge(h1, h2)) {
case 0 : return 6;
case 1 : return 5;
case 2 : return 4;
}
}
return 0;
}
/* four_judgeの返却値
0 引き分け
1 h1が負け
2 h2が負け
3 h3が負け
4 h4が負け
5 h1が勝ち
6 h2が勝ち
7 h3が勝ち
8 h4が勝ち
9 h1,h2が負け
10 h1,h3が負け
11 h1,h4が負け
12 h1,h2が勝ち
13 h1,h3が勝ち
14 h1,h4が勝ち
*/
int four_judge(int h1, int h2, int h3, int h4)
{
if (h1 == h2 && h2 == h3 && h3 == h4)
return 0;
else if (h1 == h2 && h2 == h3) {
if (two_judge(h3, h4) == 1)
return 8;
else
return 4;
}
else {
switch (three_judge(h1, h2, h3)) {
case 0 : break;
case 1 :
switch (two_judge(h1, h4)) {
case 0 : return 11;
case 1 : return 1;
case 2 : break;
}
case 2 :
switch (two_judge(h1, h4)) {
case 0 : return 2;
case 1 : break;
case 2 : return 13;
}
case 3 :
switch (two_judge(h1, h4)) {
case 0 : return 3;
case 1 : break;
case 2 : return 12;
}
case 4 :
switch (two_judge(h1, h4)) {
case 0 : return 14;
case 1 : break;
case 2 : return 5;
}
case 5 :
switch (two_judge(h1, h4)) {
case 0 : return 6;
case 1 : return 10;
case 2 : break;
}
case 6 :
switch (two_judge(h1, h4)) {
case 0 : return 7;
case 1 : return 9;
case 2 : break;
}
}
}
return 0;
}
void count_no(int result)
{
switch (result) {
case 0 : draw_no++; break;
case 1 : lose_no++; break;
case 2 : win_no++; break;
}
}
void disp_result(int result)
{
switch (result) {
case 0 : puts("引き分けです。"); break;
case 1 : puts("あなたの負けです。"); break;
case 2 : puts("あなたの勝ちです。"); break;
}
}
void disp_winner(const char *winner)
{
printf("%sが勝ちました。\n", winner);
}
void two_janken( const char *winner1, const char *winner2, const char *loser1, const char *loser2,
int *winner_v1, int *winner_v2 )
{
printf("%sと%sは負けました。%sと%sで勝負をします。\n", loser1, loser2, winner1, winner2);
while (1) {
janken();
judge = two_judge(*winner_v1, *winner_v2);
printf("%sは%sで、%sは%sです。\n", winner1, hd[*winner_v1], winner2, hd[*winner_v2]);
if (judge)
break;
puts("あいこなのでもう一度勝負をします。");
}
}
void three_janken( const char *winner1, const char *winner2, const char *winner3,
const char *loser, int *winner_v1, int *winner_v2, int *winner_v3 )
{
printf("%sは負けました。%sと%sと%sで勝負をします。\n", loser, winner1, winner2, winner3);
while (1) {
janken();
judge = three_judge(*winner_v1, *winner_v2, *winner_v3);
printf("%sは%sで、%sは%sで、%sは%sです。\n",
winner1, hd[*winner_v1], winner2, hd[*winner_v2], winner3, hd[*winner_v3]);
if (judge)
break;
puts("あいこなのでもう一度勝負をします。");
}
}
void main_janken(void)
{
judge = 0;
npc_only = 0;
janken();
judge = four_judge(pc, npc[0], npc[1], npc[2]);
printf("Playerは%sで、NPC1は%sで、NPC2は%sで、NPC3は%sです。\n", hd[pc], hd[npc[0]], hd[npc[1]], hd[npc[2]]);
switch (judge) {
case 0 : printf("引き分けです。\n"); count_no(0); break;
case 1 :
count_no(1);
npc_only = 1;
three_janken(npc_name[0], npc_name[1], npc_name[2], pc_name, &npc[0], &npc[1], &npc[2]);
switch (judge) {
case 1 :
two_janken(npc_name[1], npc_name[2], pc_name, npc_name[0], &npc[1], &npc[2]);
switch (judge) {
case 1 : disp_winner(npc_name[2]); npc_win[2]++; break;
case 2 : disp_winner(npc_name[1]); npc_win[1]++; break;
}
break;
case 2 :
two_janken(npc_name[0], npc_name[2], pc_name, npc_name[1], &npc[0], &npc[2]);
switch (judge) {
case 1 : disp_winner(npc_name[2]); npc_win[2]++; break;
case 2 : disp_winner(npc_name[0]); npc_win[0]++; break;
}
break;
case 3 :
two_janken(npc_name[0], npc_name[1], pc_name, npc_name[2], &npc[0], &npc[1]);
switch (judge) {
case 1 : disp_winner(npc_name[1]); npc_win[1]++; break;
case 2 : disp_winner(npc_name[0]); npc_win[0]++; break;
}
break;
case 4 : disp_winner(npc_name[0]); npc_win[0]++; break;
case 5 : disp_winner(npc_name[1]); npc_win[1]++; break;
case 6 : disp_winner(npc_name[2]); npc_win[2]++; break;
}
break;
case 2 :
three_janken(pc_name, npc_name[1], npc_name[2], npc_name[0], &pc, &npc[1], &npc[2]);
switch (judge) {
case 1 :
count_no(1);
npc_only = 1;
two_janken(npc_name[1], npc_name[2], pc_name, npc_name[0], &npc[1], &npc[2]);
switch (judge) {
case 1 : disp_winner(npc_name[2]); npc_win[2]++; break;
case 2 : disp_winner(npc_name[1]); npc_win[1]++; break;
}
break;
case 2 :
two_janken(pc_name, npc_name[2], npc_name[0], npc_name[1], &pc, &npc[2]);
switch (judge) {
case 1 : disp_winner(npc_name[2]); count_no(1); npc_win[2]++; break;
case 2 : disp_winner(pc_name); count_no(2); break;
}
break;
case 3 :
two_janken(pc_name, npc_name[1], npc_name[0], npc_name[2], &pc, &npc[1]);
switch (judge) {
case 1 : disp_winner(npc_name[1]); count_no(1); npc_win[1]++; break;
case 2 : disp_winner(pc_name); count_no(2); break;
}
break;
case 4 : disp_winner(pc_name); count_no(2); break;
case 5 : disp_winner(npc_name[1]); count_no(1); npc_win[1]++; break;
case 6 : disp_winner(npc_name[2]); count_no(1); npc_win[2]++; break;
}
break;
case 3 :
three_janken(pc_name, npc_name[0], npc_name[2], npc_name[1], &pc, &npc[0], &npc[2]);
switch (judge) {
case 1 :
count_no(1);
npc_only = 1;
two_janken(npc_name[0], npc_name[2], pc_name, npc_name[1], &npc[0], &npc[2]);
switch (judge) {
case 1 : disp_winner(npc_name[2]); npc_win[2]++; break;
case 2 : disp_winner(npc_name[0]); npc_win[0]++; break;
}
break;
case 2 :
two_janken(pc_name, npc_name[2], npc_name[0], npc_name[1], &pc, &npc[2]);
switch (judge) {
case 1 : disp_winner(npc_name[2]); count_no(1); npc_win[2]++; break;
case 2 : disp_winner(pc_name); count_no(2); break;
}
break;
case 3 :
two_janken(pc_name, npc_name[0], npc_name[1], npc_name[2], &pc, &npc[0]);
switch (judge) {
case 1 : disp_winner(npc_name[0]); count_no(1); npc_win[0]++; break;
case 2 : disp_winner(pc_name); count_no(2); break;
}
break;
case 4 : disp_winner(pc_name); count_no(2); break;
case 5 : disp_winner(npc_name[0]); count_no(1); npc_win[0]++; break;
case 6 : disp_winner(npc_name[2]); count_no(1); npc_win[2]++; break;
}
break;
case 4 :
three_janken(pc_name, npc_name[0], npc_name[1], npc_name[2], &pc, &npc[0], &npc[1]);
switch (judge) {
case 1 :
count_no(1);
npc_only = 1;
two_janken(npc_name[0], npc_name[1], pc_name, npc_name[2], &npc[0], &npc[1]);
switch (judge) {
case 1 : disp_winner(npc_name[1]); npc_win[1]++; break;
case 2 : disp_winner(npc_name[0]); npc_win[0]++; break;
}
break;
case 2 :
two_janken(pc_name, npc_name[1], npc_name[0], npc_name[2], &pc, &npc[1]);
switch (judge) {
case 1 : disp_winner(npc_name[1]); count_no(1); npc_win[1]++; break;
case 2 : disp_winner(pc_name); count_no(2); break;
}
break;
case 3 :
two_janken(pc_name, npc_name[0], npc_name[1], npc_name[2], &pc, &npc[0]);
switch (judge) {
case 1 : disp_winner(npc_name[0]); count_no(1); npc_win[0]++; break;
case 2 : disp_winner(pc_name); count_no(2); break;
}
break;
case 4 : disp_winner(pc_name); count_no(2); break;
case 5 : disp_winner(npc_name[0]); count_no(1); npc_win[0]++; break;
case 6 : disp_winner(npc_name[1]); count_no(1); npc_win[1]++; break;
}
break;
case 5 : disp_winner(pc_name); count_no(2); break;
case 6 : disp_winner(npc_name[0]); count_no(1); npc_win[0]++; break;
case 7 : disp_winner(npc_name[1]); count_no(1); npc_win[1]++; break;
case 8 : disp_winner(npc_name[2]); count_no(1); npc_win[2]++; break;
case 9 :
count_no(1);
npc_only = 1;
two_janken(npc_name[1], npc_name[2], pc_name, npc_name[0], &npc[1], &npc[2]);
switch (judge) {
case 1 : disp_winner(npc_name[2]); npc_win[2]++; break;
case 2 : disp_winner(npc_name[1]); npc_win[1]++; break;
}
break;
case 10 :
count_no(1);
npc_only = 1;
two_janken(npc_name[0], npc_name[2], pc_name, npc_name[1], &npc[0], &npc[2]);
switch (judge) {
case 1 : disp_winner(npc_name[2]); npc_win[2]++; break;
case 2 : disp_winner(npc_name[0]); npc_win[0]++; break;
}
break;
case 11 :
count_no(1);
npc_only = 1;
two_janken(npc_name[0], npc_name[1], pc_name, npc_name[2], &npc[0], &npc[1]);
switch (judge) {
case 1 : disp_winner(npc_name[1]); npc_win[1]++; break;
case 2 : disp_winner(npc_name[0]); npc_win[0]++; break;
}
break;
case 12 :
two_janken(pc_name, npc_name[0], npc_name[1], npc_name[2], &pc, &npc[0]);
switch (judge) {
case 1 : disp_winner(npc_name[0]); count_no(1); npc_win[0]++; break;
case 2 : disp_winner(pc_name); count_no(2); break;
}
break;
case 13 :
two_janken(pc_name, npc_name[1], npc_name[0], npc_name[2], &pc, &npc[1]);
switch (judge) {
case 1 : disp_winner(npc_name[1]); count_no(1); npc_win[1]++; break;
case 2 : disp_winner(pc_name); count_no(2); break;
}
break;
case 14 :
two_janken(pc_name, npc_name[2], npc_name[0], npc_name[1], &pc, &npc[2]);
switch (judge) {
case 1 : disp_winner(npc_name[2]); count_no(1); npc_win[2]++; break;
case 2 : disp_winner(pc_name); count_no(2); break;
}
break;
}
}