我正在编写一个模拟游戏Mastermind的程序,但我正在努力将猜测模式与关键模式进行比较。 游戏条件有点变化:
for (i=0; i<patternlength; i++)
{
for (x=0; x<patternlength; x++)
{
if (guess[i]==key[x] && i==x)
printf("b");
if (guess[i]==key[x] && i!=x)
printf("w");
if (guess[i]!=key[x])
printf(".");
}
}
这是使用Jonathan Leffler提供的一些答案。不幸的是,它还没有正常工作;你能救我吗?
函数length()和guessnum()已经定义。
#include<stdio.h>
#include<string.h>
int length()
{
int length;
printf("Enter the pattern length: ");
scanf("%d", &length);
return length;
}
int guessnum()
{
int guessnum;
printf("Enter the number of guesses: ");
scanf("%d", &guessnum);
return guessnum;
}
int main(void)
{
int patternlength = length();
char key[patternlength+1];
char keyc[patternlength+1];
int numguess = guessnum();
char guess[patternlength+1];
printf("Input the key pattern with no spaces: ");
scanf("%s", key);
int i,j,count = 1;
int bcount = 0, wcount = 0;
char guessc[patternlength+1];
guessc[0] = '\0';
int ind;
char output[patternlength];
for (ind=0; ind<(patternlength+1); ind++)
output[ind]='\0';
char outputc[patternlength+1];
char guessold[patternlength+1];
for (ind=0; ind<(patternlength+1); ind++)
guessold[ind]='\0';
while (strcmp(key, guess) !=0 && count<=numguess)
{
if(count>1)
strcpy(guessold, guess);
strcpy(keyc, key);
printf("Input a guess pattern with no spaces: ");
scanf("%s", guess);
if (count>1)
printf("%d: %s %s\n", count-1, output, guessold);
strcpy(guessc, guess);
wcount = 0;
bcount = 0;
printf("%d: ", count);
for (i = 0; i < patternlength; i++)
{
if (keyc[i] == guessc[i])
{
putchar('b');
keyc[i] = guessc[i] = '.';
bcount++;
for (ind=0; ind<patternlength; ind++)
output[ind]='b';
}
}
if (bcount != patternlength)
{
for (i = 0; i < patternlength; i++)
{
if (guessc[i] != '.')
{
for (j = 0; j < patternlength; j++)
{
if (guessc[i] == keyc[j])
{
wcount++;
putchar('w');
for (ind=0; ind<patternlength; ind++)
if (output[ind]!='b')
output[ind]='w';
keyc[j] = guessc[i] = '.';
break;
}
}
}
}
for (i = bcount + wcount; i < patternlength; i++)
putchar('.');
for (ind=bcount+wcount; ind<patternlength; ind++)
output[ind]='.';
}
count++;
printf(" %s\n", guess);
strcpy(outputc, output);
}
if (strcmp(key, guess) != 0)
{
printf("You did not guess the pattern!\n");
}
else
{
printf("You guessed the pattern!\n");
}
return 0;
}
以上代码的输出:
Enter the pattern length: 3
Enter the number of guesses: 3
Input the key pattern with no spaces: abc
Input a guess pattern with no spaces: acb
1: bww acb
Input a guess pattern with no spaces: abb
1: bbb acb
2: bb. abb
Input a guess pattern with no spaces: abc
2: bb. abb
3: bbb abc
You guessed the pattern!
需要输出:
Enter the pattern length: 3
Enter the number of guesses: 3
Input the key pattern with no spaces: abc
Input a guess pattern with no spaces: acb
1: bww acb
Input a guess pattern with no spaces: abb
1: bww acb
2: bb. abb
Input a guess pattern with no spaces: abc
1: bww acb
2: bb. abb
3: bbb abc
You guessed the pattern!
我试图再使用一个字符串,它会在其中存储猜测的反馈,但是当有几个猜测时,我想我应该使用某种循环来打印每次新猜测时所有先前猜测的反馈。但是我很难弄清楚应该如何使用Jonathan Leffler建议的结构来编写这个循环。
我在代码中添加了最后一次修正,所以几乎达到了所需的输出。有没有人知道这里有什么可以做的?
答案 0 :(得分:2)
我假设有一个结构(为了便于复制其中包含的数组),并且输入验证确保键和猜测的长度相同,并且键和猜测只包含字母字符
typedef struct pattern
{
char pattern[8];
} pattern;
size_t print_scoring(pattern key, pattern guess)
{
size_t n = strlen(key.pattern);
assert(n == strlen(guess.pattern));
size_t bcount = 0;
for (size_t i = 0; i < n; i++)
{
if (key.pattern[i] == guess.pattern[i])
{
putchar('b');
key.pattern[i] = guess.pattern[i] = '.';
bcount++;
}
}
if (bcount != n)
{
size_t wcount = 0;
for (size_t i = 0; i < n; i++)
{
if (guess.pattern[i] != '.')
{
for (size_t j = 0; j < n; j++)
{
if (guess.pattern[i] == key.pattern[j])
{
wcount++;
putchar('w');
guess.pattern[i] = key.pattern[j] = '.';
break;
}
}
}
}
for (size_t i = bcount + wcount; i < n; i++)
putchar('.');
}
return bcount;
}
该函数适用于键和模式的副本(结构按值传递,而不是通过指针传递)。它返回正确位置的正确猜测数;它假定调用代码知道模式有多长,因此调用代码可以判断模式何时正确。它将猜测和关键字符标记为“已使用”,将其替换为“。”。这对于防止"aba"
的密钥和"aaa"
的猜测被错误地标记为bbw
而不是正确地标记为bb.
非常重要。这在长度为4或更长的键/猜测中会更为重要。
#include <assert.h>
#include <string.h>
#include <stdio.h>
int main(void)
{
enum { NUM_KEYS = 3, NUM_GUESSES = 5 };
pattern k[] = { { "abc" }, { "aba" }, { "aaa" } };
pattern g[] = { { "aaa" }, { "aab" }, { "abc" }, { "cba" }, { "bab" } };
for (int i = 0; i < NUM_KEYS; i++)
{
for (int j = 0; j < NUM_GUESSES; j++)
{
printf("Key: %s; Guess %s; Score: ", k[i].pattern, g[j].pattern);
size_t n = print_scoring(k[i], g[j]);
if (n == 3)
printf(" -- Correct!");
putchar('\n');
}
}
return(0);
}
Key: abc; Guess aaa; Score: b..
Key: abc; Guess aab; Score: bw.
Key: abc; Guess abc; Score: bbb -- Correct!
Key: abc; Guess cba; Score: bww
Key: abc; Guess bab; Score: ww.
Key: aba; Guess aaa; Score: bb.
Key: aba; Guess aab; Score: bww
Key: aba; Guess abc; Score: bb.
Key: aba; Guess cba; Score: bb.
Key: aba; Guess bab; Score: ww.
Key: aaa; Guess aaa; Score: bbb -- Correct!
Key: aaa; Guess aab; Score: bb.
Key: aaa; Guess abc; Score: b..
Key: aaa; Guess cba; Score: b..
Key: aaa; Guess bab; Score: b..
为什么我的代码不起作用?你能看一下吗? 问题是在输入猜测模式后我无法进入下一步。也许我在代码中没有看到一些错误。
即时回复:
我的答案中的一个关键点是比较代码正在处理输入数据的副本。它是一种破坏性的比较算法,在数据上写点。您尝试将我的代码合并到您的程序中并没有保留单独的函数来处理数据的单独副本,而这些副本是此答案的关键部分。使用结构可以很容易地传递数据的副本(这是一次C自动复制数组)。比较代码应该是它自己的函数,而不是main()
中的内联。
但是,我们可以让代码工作。存在一些转录错误(下面标记为BUG),以及其他一些问题(也在下面列出)。
这是您的程序的工作版本,注释了关键的更改。非关键变化包括运算符周围的间距以及使用4个空格的缩进级别。
#include <string.h>
#include <stdio.h>
static int length(void) { return 3; } // Dummy function
static int guessnum(void) { return 5; } // Dummy function
int main(void)
{
int patternlength = length();
char key[patternlength+1]; // Buffer overflow
char keyc[patternlength+1]; // Copy of key
int numguess = guessnum();
char guess[patternlength+1]; // Buffer overflow
printf("Input the key pattern with no spaces: ");
scanf("%s", key);
int i,j,count = 1;
int bcount = 0, wcount = 0;
char guessc[patternlength+1]; // Buffer overflow
guessc[0] = '\0'; // Initialize!
while (strcmp(key, guess) != 0 && count <= numguess)
{
strcpy(keyc, key); // Copy key too
printf("Input a guess pattern with no spaces: ");
scanf("%s", guess);
strcpy(guessc, guess);
wcount = 0; // Reinitialize
bcount = 0; // Reinitialize
printf("%d: ", count);
for (i = 0; i < patternlength; i++)
{
if (keyc[i] == guessc[i])
{
putchar('b');
keyc[i] = guessc[i] = '.';
bcount++;
}
}
if (bcount != patternlength) // Extraneous semi-colon excised! ;
{
for (i = 0; i < patternlength; i++)
{
if (guessc[i] != '.')
{
//for (j = 0; i < patternlength; j++) BUG
for (j = 0; j < patternlength; j++)
{
//if (guessc[i] == keyc[i]) BUG
if (guessc[i] == keyc[j])
{
wcount++;
putchar('w');
//guessc[i] = keyc[i]; BUG
keyc[j] = guessc[i] = '.';
break;
}
}
}
}
for (i = bcount + wcount; i < patternlength; i++)
putchar('.');
}
count++;
printf(" %s\n", guess);
}
if (strcmp(key, guess) != 0)
{
printf("You did not guess the pattern!\n");
}
else
{
printf("You guessed the pattern!\n");
}
return 0;
}
编译器告诉我有关迷路的分号:
ss2.c: In function ‘main’:
ss2.c:36:37: warning: suggest braces around empty body in an ‘if’ statement [-Wempty-body]
如果您的编译器没有告诉您,那么您没有使用足够的警告(或者您需要更好的编译器)。我经常使用:
gcc -O3 -g -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
-Wold-style-definition ss2.c -o ss2
工作代码在没有呜咽的情况下通过了。
Input the key pattern with no spaces: abc
Input a guess pattern with no spaces: aaa
1: b.. aaa
Input a guess pattern with no spaces: bbb
2: b.. bbb
Input a guess pattern with no spaces: ccc
3: b.. ccc
Input a guess pattern with no spaces: cab
4: www cab
Input a guess pattern with no spaces: abc
5: bbb abc
You guessed the pattern!
这主要是为了显示我曾经看过出错的打印水平。使用stderr
作为诊断输出意味着诊断不会干扰stdout
的缓冲,因为输出线已建立。那并且在调试代码上使用没有缩进也意味着很容易剥离调试代码。
#include <string.h>
#include <stdio.h>
static int length(void) { return 3; }
static int guessnum(void) { return 5; }
int main(void)
{
int patternlength = length();
char key[patternlength+1]; // Buffer overflow
char keyc[patternlength+1]; // Copy of key
int numguess = guessnum();
char guess[patternlength+1]; // Buffer overflow
printf("Input the key pattern with no spaces: ");
scanf("%s", key);
int i,j,count = 1;
int bcount = 0, wcount = 0;
char guessc[patternlength+1]; // Buffer overflow
guessc[0] = '\0'; // Initialize!
while (strcmp(key, guess) != 0 && count <= numguess)
{
strcpy(keyc, key); // Copy key too
printf("Input a guess pattern with no spaces: ");
scanf("%s", guess);
strcpy(guessc, guess);
fprintf(stderr, "B1: (%s) vs (%s)\n", key, guess);
fprintf(stderr, "B2: (%s) vs (%s)\n", keyc, guessc);
wcount = 0; // Reinitialize
bcount = 0; // Reinitialize
printf("%d: ", count);
for (i = 0; i < patternlength; i++)
{
fprintf(stderr, "L1a: %d\n", i);
if (keyc[i] == guessc[i])
{
fprintf(stderr, "L1b: B (%c = %c)\n", keyc[i], guessc[i]);
putchar('b');
keyc[i] = guessc[i] = '.';
bcount++;
}
}
fprintf(stderr, "M1: (%s) vs (%s)\n", keyc, guessc);
if (bcount != patternlength) // Extraneous semi-colon excised! ;
{
fprintf(stderr, "L2a: b = %d (%s) vs (%s)\n", bcount, keyc, guessc);
for (i = 0; i < patternlength; i++)
{
fprintf(stderr, "L2b: %d (%c)\n", i, guessc[i]);
if (guessc[i] != '.')
{
fprintf(stderr, "L2c: %d (%c)\n", i, guessc[i]);
//for (j = 0; i < patternlength; j++) BUG
for (j = 0; j < patternlength; j++)
{
fprintf(stderr, "L2d: %d (%c) vs %d (%c)\n", i, guessc[i], j, keyc[j]);
//if (guessc[i] == keyc[i]) BUG
if (guessc[i] == keyc[j])
{
fprintf(stderr, "L2e: W %d (%c) vs %d (%c)\n", i, guessc[i], j, keyc[j]);
wcount++;
putchar('w');
keyc[j] = guessc[i] = '.';
//guessc[i] = keyc[i]; BUG
break;
}
}
}
}
fprintf(stderr, "L3a: %d + %d vs %d\n", bcount, wcount, patternlength);
for (i = bcount + wcount; i < patternlength; i++)
fprintf(stderr, "L3b: D %d\n", i),
putchar('.');
}
count++;
printf(" %s\n", guess);
}
if (strcmp(key, guess) != 0)
{
printf("You did not guess the pattern!\n");
}
else
{
printf("You guessed the pattern!\n");
}
return 0;
}
在最后一次fprintf()
函数调用之后,请注意使用逗号运算符的技巧。
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void err_exit(const char *msg, ...);
static void prompt_str(const char *prompt, int bufsiz, char *buffer);
static int prompt_int(const char *prompt);
int main(void)
{
int patternlength = prompt_int("Length of key");
int numguess = prompt_int("Number of guesses");
char key[patternlength+1];
char guesses[numguess][patternlength+1];
char marks[numguess][patternlength+1];
int count = 0;
prompt_str("Input the key pattern with no spaces", patternlength, key);
while (count < numguess)
{
char guess[patternlength+1];
char keyc[patternlength+1];
char mark[patternlength+1];
char *marker = mark;
int wcount = 0;
int bcount = 0;
strcpy(keyc, key);
prompt_str("Input a guess pattern with no spaces", patternlength, guess);
strcpy(guesses[count], guess);
for (int i = 0; i < patternlength; i++)
{
if (keyc[i] == guess[i])
{
*marker++ = 'b';
keyc[i] = guess[i] = '.';
bcount++;
}
}
if (bcount == patternlength)
break;
for (int i = 0; i < patternlength; i++)
{
if (guess[i] == '.')
continue;
for (int j = 0; j < patternlength; j++)
{
if (guess[i] == keyc[j])
{
wcount++;
*marker++ = 'w';
keyc[j] = guess[i] = '.';
break;
}
}
}
for (int i = bcount + wcount; i < patternlength; i++)
*marker++ = '.';
*marker = '\0';
strcpy(marks[count], mark);
count++;
for (int i = 0; i < count; i++)
printf("Guess: %d [%s] marks [%s]\n", i, guesses[i], marks[i]);
}
if (count >= numguess)
printf("You did not guess the pattern (which was [%s])!\n", key);
else
printf("You guessed the pattern!\n");
return 0;
}
static void prompt_str(const char *prompt, int bufsiz, char *buffer)
{
char fmt[8];
int c;
sprintf(fmt, "%%%ds", bufsiz);
printf("%s: ", prompt);
if (scanf(fmt, buffer) != 1)
err_exit("Unexpected input failure\n");
while ((c = getchar()) != EOF && c != '\n')
;
}
static int prompt_int(const char *prompt)
{
int number;
printf("%s: ", prompt);
if (scanf("%d", &number) != 1)
err_exit("Unexpected input failure\n");
if (number <= 0 || number > 9)
err_exit("Number should be in the range 1..9 (not %d)\n", number);
return(number);
}
static void err_exit(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
exit(1);
}
引入了函数prompt_int()
和prompt_str()
来获取数据。 prompt_str()
函数可以有效抵御溢出。有一个错误报告功能。虚拟功能被替换。这是一些示例输出。从现在开始,你就是自己了!
Length of key: 4
Number of guesses: 8
Input the key pattern with no spaces: abcd
Input a guess pattern with no spaces: aaaa
Guess: 0 [aaaa] marks [b...]
Input a guess pattern with no spaces: dcba
Guess: 0 [aaaa] marks [b...]
Guess: 1 [dcba] marks [wwww]
Input a guess pattern with no spaces: cdba
Guess: 0 [aaaa] marks [b...]
Guess: 1 [dcba] marks [wwww]
Guess: 2 [cdba] marks [wwww]
Input a guess pattern with no spaces: abcd
You guessed the pattern!
答案 1 :(得分:1)
您基本上将key
的所有元素与guess
的所有元素进行匹配,这不是您想要的。
您需要迭代guess
并区分这三种情况
元素没有正确猜测而且没有出现在密钥
中int i,k;
bool found;
for (i=0; i<patternlength; i++)
{
if (key[i] == guess[i])
{
printf("b");
}
else
{
found = false;
for (k=0; k<patternlength && !found; k++)
{
if (key[k] == guess[i])
{
found = true;
printf("w");
}
}
if (!found)
{
printf(".");
}
}
}
请注意,在内部循环中,当我找到带有&& !found
的元素时,我会停止。否则,我会遇到类似于你的问题(对于与w
中存在的猜测相匹配的每个元素,它会打印key