4-1
编写一个限制玩家可输人次数的“珠玑妙算”程序。
#include <time.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_TRIES 10 // 最大尝试次数
// 生成4个不同数字的组合并存入数组x
void make4digits(int x[]) {
int i, j, val;
for (i = 0; i < 4; i++) {
do {
val = rand() % 10; // 0~9的随机数
for (j = 0; j < i; j++)
if (val == x[j])
break;
} while (j < i); // 循环直至获得不重复的数值
x[i] = val;
}
}
// 检查已输入的字符串s的有效性
int check(const char s[]) {
int i, j;
if (strlen(s) != 4) // 字符串长度不为4
return 1;
for (i = 0; i < 4; i++) {
if (!isdigit(s[i])) // 包含了除数字以外的字符
return 2;
for (j = 0; j < i; j++)
if (s[i] == s[j]) // 含有相同数字
return 3;
}
return 0; // 字符串有效
}
// hit和blow的判断
void judge(const char s[], const int no[], int *hit, int *blow) {
int i, j;
*hit = *blow = 0;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
if (s[i] == '0' + no[j]) { // 数字一致
if (i == j)
(*hit)++; // hit(位置也一致)
else
(*blow)++; // blow(位置不一致)
}
}
}
}
// 显示结果
void print_result(int snum, int spos) {
if (spos == 4)
printf("回答正确!\n");
else if (snum == 0)
printf("这些数字里没有答案数字。\n");
else {
printf("这些数字里包括%d个答案数字。\n", snum);
if (spos == 0)
printf("但是数字的位置都不一致。\n");
else
printf("其中有%d个数字的位置是一致的。\n", spos);
}
putchar('\n');
}
int main(void) {
int try_no = 0; // 输入次数
int chk; // 已输入的字符串的检查结果
int hit; // 位置和数字都正确的数字个数
int blow; // 数字正确但位置不正确的数字个数
int no[4]; // 要猜的数字串
char buff[10]; // 用于存放读取的数字串的字符串
clock_t start, end; // 开始时间/结束时间
srand(time(NULL)); // 设定随机数种子
puts("来玩珠玑妙算吧。");
puts("其中不包含相同数字。");
puts("请猜4个数字。");
puts("请像4307这样连续输入数字。");
puts("不能输入空格字符。\n");
make4digits(no); // 生成4个各不相同的数字串
start = clock(); // 开始计时
do {
printf("请输入:");
scanf("%s", buff); // 读取为字符串
chk = check(buff); // 检查读取到的字符串
switch (chk) {
case 1:
puts("\a请确保输入4个字符。");
break;
case 2:
puts("\a请不要输入除了数字以外的字符。");
break;
case 3:
puts("\a请不要输入相同的数字。");
break;
}
if (chk == 0) { // 如果输入有效,则进行判断
try_no++;
judge(buff, no, &hit, &blow); // 判断
print_result(hit + blow, hit); // 显示判断结果
}
if (try_no >= MAX_TRIES) {
puts("你已达到最大尝试次数。游戏结束!");
break;
}
} while (hit < 4); // 直到猜对为止
if (hit == 4) {
end = clock(); // 结束计时
printf("用了%d次。\n用时%.1f秒。\n", try_no, (double)(end - start) / CLOCKS_PER_SEC);
}
return 0;
}
4-2
给“珠玑妙算”添加提示功能
※例如可以设置像下面这样的提示:
-> 提示开头的第1个字符
->提示“hit”的数字中最前面的1个字符。
->提示“blow”的数字中最末尾的1个字符。
->定期给出提示(例如玩家每答3次题给出1次提示)。
->根据玩家的要求给出提示
->限制提示次数。
#include <time.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_TRIES 10 // 最大尝试次数
#define MAX_HINTS 3 // 最大提示次数
// 生成4个不同数字的组合并存入数组x
void make4digits(int x[]) {
int i, j, val;
for (i = 0; i < 4; i++) {
do {
val = rand() % 10; // 0~9的随机数
for (j = 0; j < i; j++)
if (val == x[j])
break;
} while (j < i); // 循环直至获得不重复的数值
x[i] = val;
}
}
// 检查已输入的字符串s的有效性
int check(const char s[]) {
int i, j;
if (strlen(s) != 4) // 字符串长度不为4
return 1;
for (i = 0; i < 4; i++) {
if (!isdigit(s[i])) // 包含了除数字以外的字符
return 2;
for (j = 0; j < i; j++)
if (s[i] == s[j]) // 含有相同数字
return 3;
}
return 0; // 字符串有效
}
// hit和blow的判断
void judge(const char s[], const int no[], int *hit, int *blow) {
int i, j;
*hit = *blow = 0;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
if (s[i] == '0' + no[j]) { // 数字一致
if (i == j)
(*hit)++; // hit(位置也一致)
else
(*blow)++; // blow(位置不一致)
}
}
}
}
// 显示结果
void print_result(int snum, int spos) {
if (spos == 4)
printf("回答正确!\n");
else if (snum == 0)
printf("这些数字里没有答案数字。\n");
else {
printf("这些数字里包括%d个答案数字。\n", snum);
if (spos == 0)
printf("但是数字的位置都不一致。\n");
else
printf("其中有%d个数字的位置是一致的。\n", spos);
}
putchar('\n');
}
// 显示提示
void give_hint(const int no[], int try_no, int *hint_count) {
if (*hint_count >= MAX_HINTS) {
printf("提示次数已用完。\n");
return;
}
(*hint_count)++;
printf("提示 %d:\n", *hint_count);
switch (*hint_count) {
case 1:
printf("开头的第一个字符是: %d\n", no[0]);
break;
case 2:
// 提示第一个hit的字符
for (int i = 0; i < 4; i++) {
if (try_no % 3 == 0) { // 定期给出提示
printf("hit中的第一个字符是: %d\n", no[i]);
break;
}
}
break;
case 3:
// 提示最后一个blow的字符
for (int i = 3; i >= 0; i--) {
if (try_no % 3 == 0) { // 定期给出提示
printf("blow中的最后一个字符是: %d\n", no[i]);
break;
}
}
break;
default:
printf("没有更多提示了。\n");
break;
}
}
int main(void) {
int try_no = 0; // 输入次数
int chk; // 已输入的字符串的检查结果
int hit; // 位置和数字都正确的数字个数
int blow; // 数字正确但位置不正确的数字个数
int no[4]; // 要猜的数字串
char buff[10]; // 用于存放读取的数字串的字符串
clock_t start, end; // 开始时间/结束时间
int hint_count = 0; // 提示次数
srand(time(NULL)); // 设定随机数种子
puts("来玩珠玑妙算吧。");
puts("其中不包含相同数字。");
puts("请猜4个数字。");
puts("请像4307这样连续输入数字。");
puts("不能输入空格字符。\n");
make4digits(no); // 生成4个各不相同的数字串
start = clock(); // 开始计时
do {
printf("请输入:");
scanf("%s", buff); // 读取为字符串
chk = check(buff); // 检查读取到的字符串
switch (chk) {
case 1:
puts("\a请确保输入4个字符。");
break;
case 2:
puts("\a请不要输入除了数字以外的字符。");
break;
case 3:
puts("\a请不要输入相同的数字。");
break;
}
if (chk == 0) { // 如果输入有效,则进行判断
try_no++;
judge(buff, no, &hit, &blow); // 判断
print_result(hit + blow, hit); // 显示判断结果
}
if (try_no % 3 == 0) {
give_hint(no, try_no, &hint_count); // 定期给出提示
}
if (try_no >= MAX_TRIES) {
puts("你已达到最大尝试次数。游戏结束!");
break;
}
} while (hit < 4); // 直到猜对为止
if (hit == 4) {
end = clock(); // 结束计时
printf("用了%d次。\n用时%.1f秒。\n", try_no, (double)(end - start) / CLOCKS_PER_SEC);
}
return 0;
}
4-3
#include <time.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_TRIES 10 // 最大尝试次数
// 生成不同数字的组合并存入数组x
void make_digits(int x[], int num_digits) {
int i, j, val;
for (i = 0; i < num_digits; i++) {
do {
val = rand() % 10; // 0~9的随机数
for (j = 0; j < i; j++)
if (val == x[j])
break;
} while (j < i); // 循环直至获得不重复的数值
x[i] = val;
}
}
// 检查已输入的字符串s的有效性
int check(const char s[], int num_digits) {
int i, j;
if (strlen(s) != num_digits) // 字符串长度不为指定位数
return 1;
for (i = 0; i < num_digits; i++) {
if (!isdigit(s[i])) // 包含了除数字以外的字符
return 2;
for (j = 0; j < i; j++)
if (s[i] == s[j]) // 含有相同数字
return 3;
}
return 0; // 字符串有效
}
// hit和blow的判断
void judge(const char s[], const int no[], int *hit, int *blow, int num_digits) {
int i, j;
*hit = *blow = 0;
for (i = 0; i < num_digits; i++) {
for (j = 0; j < num_digits; j++) {
if (s[i] == '0' + no[j]) { // 数字一致
if (i == j)
(*hit)++; // hit(位置也一致)
else
(*blow)++; // blow(位置不一致)
}
}
}
}
// 显示结果
void print_result(int snum, int spos, int num_digits) {
if (spos == num_digits)
printf("回答正确!\n");
else if (snum == 0)
printf("这些数字里没有答案数字。\n");
else {
printf("这些数字里包括%d个答案数字。\n", snum);
if (spos == 0)
printf("但是数字的位置都不一致。\n");
else
printf("其中有%d个数字的位置是一致的。\n", spos);
}
putchar('\n');
}
int main(void) {
int num_digits; // 用户设定的数字位数
int try_no = 0; // 输入次数
int chk; // 已输入的字符串的检查结果
int hit; // 位置和数字都正确的数字个数
int blow; // 数字正确但位置不正确的数字个数
int *no; // 要猜的数字串
char buff[100]; // 用于存放读取的数字串的字符串
clock_t start, end; // 开始时间/结束时间
srand(time(NULL)); // 设定随机数种子
printf("设成几位数:");
scanf("%d", &num_digits);
no = (int *)malloc(num_digits * sizeof(int)); // 动态分配内存
puts("来玩珠玑妙算吧。");
puts("其中不包含相同数字。");
printf("请猜%d个数字。\n", num_digits);
puts("请像4307这样连续输入数字。");
puts("不能输入空格字符。\n");
make_digits(no, num_digits); // 生成各不相同的数字串
start = clock(); // 开始计时
do {
printf("请输入:");
scanf("%s", buff); // 读取为字符串
chk = check(buff, num_digits); // 检查读取到的字符串
switch (chk) {
case 1:
printf("\a请确保输入%d个字符。\n", num_digits);
break;
case 2:
puts("\a请不要输入除了数字以外的字符。");
break;
case 3:
puts("\a请不要输入相同的数字。");
break;
}
if (chk == 0) { // 如果输入有效,则进行判断
try_no++;
judge(buff, no, &hit, &blow, num_digits); // 判断
print_result(hit + blow, hit, num_digits); // 显示判断结果
}
if (try_no >= MAX_TRIES) {
puts("你已达到最大尝试次数。游戏结束!");
break;
}
} while (hit < num_digits); // 直到猜对为止
if (hit == num_digits) {
end = clock(); // 结束计时
printf("用了%d次。\n用时%.1f秒。\n", try_no, (double)(end - start) / CLOCKS_PER_SEC);
}
free(no); // 释放动态分配的内存
return 0;
}
4-4
编写一个允许出现重复数字的“珠玑妙算”程序。
#include <time.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_TRIES 10 // 最大尝试次数
// 生成数字组合并存入数组x,允许重复数字
void make_digits(int x[], int num_digits) {
int i;
for (i = 0; i < num_digits; i++) {
x[i] = rand() % 10; // 0~9的随机数
}
}
// 检查已输入的字符串s的有效性
int check(const char s[], int num_digits) {
if (strlen(s) != num_digits) // 字符串长度不为指定位数
return 1;
for (int i = 0; i < num_digits; i++) {
if (!isdigit(s[i])) // 包含了除数字以外的字符
return 2;
}
return 0; // 字符串有效
}
// hit和blow的判断
void judge(const char s[], const int no[], int *hit, int *blow, int num_digits) {
int i, j;
*hit = *blow = 0;
for (i = 0; i < num_digits; i++) {
for (j = 0; j < num_digits; j++) {
if (s[i] == '0' + no[j]) { // 数字一致
if (i == j)
(*hit)++; // hit(位置也一致)
else
(*blow)++; // blow(位置不一致)
}
}
}
}
// 显示结果
void print_result(int snum, int spos, int num_digits) {
if (spos == num_digits)
printf("回答正确!\n");
else if (snum == 0)
printf("这些数字里没有答案数字。\n");
else {
printf("这些数字里包括%d个答案数字。\n", snum);
if (spos == 0)
printf("但是数字的位置都不一致。\n");
else
printf("其中有%d个数字的位置是一致的。\n", spos);
}
putchar('\n');
}
int main(void) {
int num_digits; // 用户设定的数字位数
int try_no = 0; // 输入次数
int chk; // 已输入的字符串的检查结果
int hit; // 位置和数字都正确的数字个数
int blow; // 数字正确但位置不正确的数字个数
int *no; // 要猜的数字串
char buff[100]; // 用于存放读取的数字串的字符串
clock_t start, end; // 开始时间/结束时间
srand(time(NULL)); // 设定随机数种子
printf("设成几位数:");
scanf("%d", &num_digits);
no = (int *)malloc(num_digits * sizeof(int)); // 动态分配内存
puts("来玩珠玑妙算吧。");
printf("请猜%d个数字。\n", num_digits);
puts("请像4307这样连续输入数字。");
puts("不能输入空格字符。\n");
make_digits(no, num_digits); // 生成各不相同的数字串
start = clock(); // 开始计时
do {
printf("请输入:");
scanf("%s", buff); // 读取为字符串
chk = check(buff, num_digits); // 检查读取到的字符串
switch (chk) {
case 1:
printf("\a请确保输入%d个字符。\n", num_digits);
break;
case 2:
puts("\a请不要输入除了数字以外的字符。");
break;
}
if (chk == 0) { // 如果输入有效,则进行判断
try_no++;
judge(buff, no, &hit, &blow, num_digits); // 判断
print_result(hit + blow, hit, num_digits); // 显示判断结果
}
if (try_no >= MAX_TRIES) {
puts("你已达到最大尝试次数。游戏结束!");
break;
}
} while (hit < num_digits); // 直到猜对为止
if (hit == num_digits) {
end = clock(); // 结束计时
printf("用了%d次。\n用时%.1f秒。\n", try_no, (double)(end - start) / CLOCKS_PER_SEC);
}
free(no); // 释放动态分配的内存
return 0;
}
4-5
编写一个不猜数字而猜颜色的“珠玑妙算”程序。颜色共8种(白色、黑色、红色、蓝色、黄色、绿色、橙色、褐色),从中选出不重复的4种颜色让玩家来猜。
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_TRIES 10 // 最大尝试次数
const char* colors[] = {"白色", "黑色", "红色", "蓝色", "黄色", "绿色", "橙色", "褐色"};
const int NUM_COLORS = 8;
const int NUM_TO_GUESS = 4;
// 生成不同颜色的组合并存入数组x
void make_colors(int x[]) {
int i, j, val;
for (i = 0; i < NUM_TO_GUESS; i++) {
do {
val = rand() % NUM_COLORS;
for (j = 0; j < i; j++)
if (val == x[j])
break;
} while (j < i); // 循环直至获得不重复的颜色
x[i] = val;
}
}
// 检查已输入的颜色组合的有效性
int check(const char* s[], int num_to_guess) {
int i, j;
if (num_to_guess != NUM_TO_GUESS) // 长度不为指定位数
return 1;
for (i = 0; i < NUM_TO_GUESS; i++) {
int valid = 0;
for (j = 0; j < NUM_COLORS; j++) {
if (strcmp(s[i], colors[j]) == 0) {
valid = 1;
break;
}
}
if (!valid) // 包含了无效的颜色
return 2;
for (j = 0; j < i; j++) {
if (strcmp(s[i], s[j]) == 0) // 含有相同颜色
return 3;
}
}
return 0; // 颜色组合有效
}
// hit和blow的判断
void judge(const char* s[], const int no[], int *hit, int *blow) {
int i, j;
*hit = *blow = 0;
for (i = 0; i < NUM_TO_GUESS; i++) {
for (j = 0; j < NUM_TO_GUESS; j++) {
if (strcmp(s[i], colors[no[j]]) == 0) { // 颜色一致
if (i == j)
(*hit)++; // hit(位置也一致)
else
(*blow)++; // blow(位置不一致)
}
}
}
}
// 显示结果
void print_result(int snum, int spos) {
if (spos == NUM_TO_GUESS)
printf("回答正确!\n");
else if (snum == 0)
printf("这些颜色里没有答案颜色。\n");
else {
printf("这些颜色里包括%d个答案颜色。\n", snum);
if (spos == 0)
printf("但是颜色的位置都不一致。\n");
else
printf("其中有%d个颜色的位置是一致的。\n", spos);
}
putchar('\n');
}
int main(void) {
int try_no = 0; // 输入次数
int chk; // 已输入的颜色组合的检查结果
int hit; // 位置和颜色都正确的颜色个数
int blow; // 颜色正确但位置不正确的颜色个数
int no[NUM_TO_GUESS]; // 要猜的颜色组合
char buff[NUM_TO_GUESS][10]; // 用于存放读取的颜色组合的字符串
const char* input_colors[NUM_TO_GUESS]; // 用于存放用户输入的颜色指针数组
clock_t start, end; // 开始时间/结束时间
srand(time(NULL)); // 设定随机数种子
puts("来玩珠玑妙算吧。");
puts("颜色共8种(白色、黑色、红色、蓝色、黄色、绿色、橙色、褐色)。");
puts("从中选出不重复的4种颜色让玩家来猜。");
puts("请像\"白色 红色 蓝色 绿色\"这样连续输入颜色,中间用空格分隔。");
make_colors(no); // 生成不重复的颜色组合
start = clock(); // 开始计时
do {
printf("请输入:");
for (int i = 0; i < NUM_TO_GUESS; i++) {
scanf("%s", buff[i]);
input_colors[i] = buff[i];
}
chk = check(input_colors, NUM_TO_GUESS); // 检查读取到的颜色组合
switch (chk) {
case 1:
printf("\a请确保输入%d种颜色。\n", NUM_TO_GUESS);
break;
case 2:
puts("\a请不要输入无效的颜色。");
break;
case 3:
puts("\a请不要输入相同的颜色。");
break;
}
if (chk == 0) { // 如果输入有效,则进行判断
try_no++;
judge(input_colors, no, &hit, &blow); // 判断
print_result(hit + blow, hit); // 显示判断结果
}
if (try_no >= MAX_TRIES) {
puts("你已达到最大尝试次数。游戏结束!");
break;
}
} while (hit < NUM_TO_GUESS); // 直到猜对为止
if (hit == NUM_TO_GUESS) {
end = clock(); // 结束计时
printf("用了%d次。\n用时%.1f秒。\n", try_no, (double)(end - start) / CLOCKS_PER_SEC);
}
return 0;
}
4-6
编写一个“珠玑妙算”程序,让玩家和计算机两者同时出题,交替给出提示并回答,先猜中者胜。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NUM_TO_GUESS 4 // 猜测的数字位数
#define MAX_TRIES 10 // 最大尝试次数
// 生成不同数字并保存在数组中
void make_numbers(int x[]) {
int i, j, val;
for (i = 0; i < NUM_TO_GUESS; i++) {
do {
val = rand() % 10;
for (j = 0; j < i; j++) {
if (val == x[j])
break;
}
} while (j < i); // 直至循环到不重复数字
x[i] = val;
}
}
// hit 和 blow 的判断
void judge(const int s[], const int no[], int* hit, int* blow) {
*hit = *blow = 0;
for (int i = 0; i < NUM_TO_GUESS; i++) {
for (int j = 0; j < NUM_TO_GUESS; j++) {
if (s[i] == no[j]) { // 数字一致
if (i == j) // 位置也一致
(*hit)++;
else
(*blow)++;
}
}
}
}
// 显示结果
void print_result(int snum, int spos) {
if (spos == NUM_TO_GUESS)
printf("回答正确\n");
else if (snum == 0)
printf("这些数字里面没有正确答案\n");
else {
printf("这些数字里面有%d个正确数字\n", snum);
printf("其中有%d个位置是一致的\n", spos);
}
printf("\n");
}
int main() {
int player_no[NUM_TO_GUESS]; // 玩家出题的数字组合
int computer_no[NUM_TO_GUESS]; // 计算机出题的数字组合
int computer_guess[NUM_TO_GUESS]; // 计算机当前猜测的数字组合
int player_input[NUM_TO_GUESS]; // 用于存储玩家输入的数字组合
int player_hit, player_blow; // 玩家猜测的结果
int computer_hit = 0, computer_blow = 0; // 计算机猜测的结果
int try_no = 0; // 尝试次数
srand(time(NULL)); // 设定种子
puts("来玩珠玑妙算吧。");
puts("从0到9中选出不重复的4个数字让玩家和计算机来猜。");
// 玩家出题
printf("请玩家出题(4个数字): (每个数字分隔开)\n");
for (int i = 0; i < NUM_TO_GUESS; i++) {
scanf("%d", &player_no[i]);
}
// 生成计算机出题
make_numbers(computer_no);
// 游戏开始
while (1) {
// 玩家猜测
printf("请输入你猜测的数字组合:");
for (int i = 0; i < NUM_TO_GUESS; i++) {
scanf("%d", &player_input[i]);
}
judge(player_input, computer_no, &player_hit, &player_blow); // 判断
print_result(player_hit + player_blow, player_hit); // 显示判断结果
if (player_hit == NUM_TO_GUESS) { // 玩家猜对
printf("恭喜你,你猜对了!\n");
break;
}
// 计算机猜测
make_numbers(computer_guess); // 计算机随机猜测
judge(computer_guess, player_no, &computer_hit, &computer_blow); // 判断
printf("计算机猜测:");
for (int i = 0; i < NUM_TO_GUESS; i++) {
printf("%d ", computer_guess[i]);
}
printf("\n");
print_result(computer_hit + computer_blow, computer_hit); // 显示判断结果
if (computer_hit == NUM_TO_GUESS) { // 计算机猜对
printf("计算机猜对了!\n");
break;
}
try_no++;
}
/* if (try_no >= MAX_TRIES) {
printf("达到最大尝试次数,游戏结束!\n");
}*/
return 0;
}
4-7
在第1章中,我们编写了一个猜0~999的数字的“猜数游戏”。编写一个程序,让所出的题目中不同数字位上不能出现相同的数字(例如55和919等)。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// 检查数字的各个位上是否有重复数字
int has_unique_digits(int num) {
int digits[10] = { 0 };
while (num > 0) {
int digit = num % 10;
if (digits[digit] != 0) {
return 0; // 有重复数字
}
digits[digit]++;
num /= 10;
}
return 1; // 无重复数字
}
// 生成一个0到999之间不含重复数字的数
int generate_unique_number() {
int num;
do {
num = rand() % 1000;
} while (!has_unique_digits(num));
return num;
}
int main() {
int target, guess, attempts = 0;
// 初始化随机数种子
srand(time(NULL));
// 生成一个0到999之间不含重复数字的数
target = generate_unique_number();
printf("猜一个0到999之间的数,每个数字位上不能有重复的数字。\n");
do {
printf("请输入你的猜测:");
scanf("%d", &guess);
if (guess < 0 || guess > 999) {
printf("请输入一个0到999之间的数。\n");
continue;
}
attempts++;
if (guess > target) {
printf("太大了!\n");
}
else if (guess < target) {
printf("太小了!\n");
}
else {
printf("恭喜你,猜对了!你用了%d次。\n", attempts);
}
} while (guess != target);
return 0;
}