【明解c语言中级篇第三章练习答案】

明解c语言中级篇第三章练习答案

3-1

练习3-1编写一个程序,把List3-9程序中的函数count_no和disp_result整合成一个函数,然后讨论更改前和更改后的程序。

//List 3-9
#include <time.h>
#include <stdio.h>
#include <stdlib.h>

int human; /* 玩家手势 */
int comp; /* 计算机手势 */
int win_no; /* 胜利次数 */
int lose_no; /* 失败次数 */
int draw_no; /* 平局次数 */

char *hd[] = {"石头", "剪刀", "布"}; /* 手势 */

/* 初始处理 */
void initialize(void) {
    win_no = 0; /* 胜利次数 */
    lose_no = 0; /* 失败次数 */
    draw_no = 0; /* 平局次数 */
    srand(time(NULL)); /* 设定随机数种子 */
    printf("猜拳游戏开始!\n");
}

/* 运行猜拳游戏(读取/生成手势) */
void jyanken(void) {
    int i;
    comp = rand() % 3; /* 用随机数生成计算机的手势(0~2) */
    do {
        printf("\n\a石头剪刀布...");
        for (i = 0; i < 3; i++)
            printf("(%d)%s ", i, hd[i]);
        printf(": ");
        scanf("%d", &human); /* 读取玩家的手势 */
    } while (human < 0 || human > 2);
}

/* 计数胜利/失败/平局次数 */
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;
    }
}

/* 确认是否再次挑战 */
int confirm_retry(void) {
    int x;
    printf("再来一次吗...(0)否(1)是:");
    scanf("%d", &x);
    return x;
}

int main(void) {
    int judge; /* 胜负 */
    int retry; /* 再来一次? */

    initialize(); /* 初始处理 */

    do {
        jyanken(); /* 运行猜拳游戏 */

        /* 显示计算机和玩家的手势 */
        printf("我出%s,你出%s。\n", hd[comp], hd[human]);

        judge = (human - comp + 3) % 3; /* 判断胜负 */
        count_no(judge); /* 更新胜利/失败/平局次数 */
        disp_result(judge); /* 显示判断结果 */

        retry = confirm_retry(); /* 确认是否再次挑战 */
    } while (retry == 1);

    printf("%d胜 %d负 %d平。\n", win_no, lose_no, draw_no);
    return 0;
}

//答案
#define _CRT_SECURE_NO_WARNINGS 1
#include <time.h>
#include <stdio.h>
#include <stdlib.h>

int human; /* 玩家手势 */
int comp; /* 计算机手势 */
int win_no; /* 胜利次数 */
int lose_no; /* 失败次数 */
int draw_no; /* 平局次数 */

const char* hd[] = { "石头", "剪刀", "布" }; /* 手势 */

/* 初始处理 */
void initialize(void) {
    win_no = 0; /* 胜利次数 */
    lose_no = 0; /* 失败次数 */
    draw_no = 0; /* 平局次数 */
    srand(time(NULL)); /* 设定随机数种子 */
    printf("猜拳游戏开始!\n");
}

/* 运行猜拳游戏(读取/生成手势) */
void jyanken(void) {
    int i;
    comp = rand() % 3; /* 用随机数生成计算机的手势(0~2) */
    do {
        printf("\n\a石头剪刀布...");
        for (i = 0; i < 3; i++)
            printf("(%d)%s ", i, hd[i]);
        printf(": ");
        scanf("%d", &human); /* 读取玩家的手势 */
    } while (human < 0 || human > 2);
}

/* 更新和显示结果 */
void update_and_display_result(int result) {
    switch (result) {
    case 0:
        draw_no++;
        puts("平局。");
        break;
    case 1:
        lose_no++;
        puts("你输了。");
        break;
    case 2:
        win_no++;
        puts("你赢了。");
        break;
    }
}

/* 确认是否再次挑战 */
int confirm_retry(void) {
    int x;
    printf("再来一次吗...(0)否(1)是:");
    scanf("%d", &x);
    return x;
}

int main(void) {
    int judge; /* 胜负 */
    int retry; /* 再来一次? */

    initialize(); /* 初始处理 */

    do {
        jyanken(); /* 运行猜拳游戏 */

        /* 显示计算机和玩家的手势 */
        printf("我出%s,你出%s。\n", hd[comp], hd[human]);

        judge = (human - comp + 3) % 3; /* 判断胜负 */
        update_and_display_result(judge); /* 更新和显示结果 */

        retry = confirm_retry(); /* 确认是否再次挑战 */
    } while (retry == 1);

    printf("%d胜 %d负 %d平。\n", win_no, lose_no, draw_no);
    return 0;
}

更改前:
模块化清晰:原始程序中,count_no 和 disp_result 分别负责不同的功能,职责单一,模块化清晰。
可维护性高:单独的函数使得每个函数更容易维护和修改。


更改后:
简化结构:整合后的函数减少了函数调用的次数,使代码更加简洁。
功能合并:合并后的函数使得逻辑更加集中,不需要在不同函数间跳转。


总体来说: 更改后的程序更加简洁,但在某些情况下,过度简化可能会降低代码的可维护性和可读性。在实际开发中,应根据具体情况选择合适的方案。

3-2

把List3-10中的猜赢3次拳泛化为猜赢n次拳。在游戏一开始就问“要猜赢几次?”,让玩家来输人n的值。

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int human; /* 玩家手势 */
int comp; /* 计算机手势 */
int win_no; /* 胜利次数 */
int lose_no; /* 失败次数 */
int draw_no; /* 平局次数 */
int target_wins; /* 目标胜利次数 */

const char* hd[] = { "石头", "剪刀", "布" }; /* 手势 */

/* 初始处理 */
void initialize(void) {
    win_no = 0; /* 胜利次数 */
    lose_no = 0; /* 失败次数 */
    draw_no = 0; /* 平局次数 */
    srand(time(NULL)); /* 设定随机数种子 */
    printf("猜拳游戏开始!\n");

    /* 询问目标胜利次数 */
    printf("要猜赢几次?");
    scanf("%d", &target_wins);
}

/* 运行猜拳游戏(读取/生成手势) */
void jyanken(void) {
    int i;
    comp = rand() % 3; /* 用随机数生成计算机的手势(0~2) */
    do {
        printf("\n\a石头剪刀布...");
        for (i = 0; i < 3; i++) {
            printf("(%d)%s ", i, hd[i]);
        }
        printf(": ");
        scanf("%d", &human); /* 读取玩家的手势 */
    } while (human < 0 || human > 2);
}

/* 更新和显示结果 */
void update_and_display_result(int result) {
    switch (result) {
    case 0:
        draw_no++;
        puts("平局。");
        break;
    case 1:
        lose_no++;
        puts("你输了。");
        break;
    case 2:
        win_no++;
        puts("你赢了。");
        break;
    }
}

int main(void) {
    int judge; /* 胜负 */

    initialize(); /* 初始处理 */

    do {
        jyanken(); /* 运行猜拳游戏 */

        /* 显示计算机和玩家的手势 */
        printf("我出%s,你出%s。\n", hd[comp], hd[human]);

        judge = (human - comp + 3) % 3; /* 判断胜负 */
        update_and_display_result(judge); /* 更新和显示结果 */

    } while (win_no < target_wins && lose_no < target_wins);

    printf(win_no == target_wins ? "\n你赢了。\n" : "\n我赢了。\n");
    printf("%d胜 %d负 %d平。\n", win_no, lose_no, draw_no);
    return 0;
}

3-3

编写一个“猜拳游戏”,让计算机只能出石头和布

因为计算机只能出石头和布,而且控制手势的数组是char *hd[] = {"石头", "剪刀", "布"};,所以,只能让计算机生成 0和2,我们可以按照下面的代码来控制:

comp = rand() % 2 * 2; /* 生成0(石头)或2(布) */

这样 com 就只会生成 0和2 了。

完整代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int human; /* 玩家手势 */
int comp; /* 计算机手势 */
int win_no; /* 胜利次数 */
int lose_no; /* 失败次数 */
int draw_no; /* 平局次数 */

const 
char* hd[] = { "石头", "剪刀", "布" }; /* 手势 */

/* 初始处理 */
void initialize(void) {
    win_no = 0; /* 胜利次数 */
    lose_no = 0; /* 失败次数 */
    draw_no = 0; /* 平局次数 */
    srand(time(NULL)); /* 设定随机数种子 */
    printf("猜拳游戏开始!\n");
}

/* 运行猜拳游戏(读取/生成手势) */
void jyanken(void) {
    int i;
    comp = (rand() % 2) * 2; /* 生成0(石头)或2(布) */
    do {
        printf("\n\a石头剪刀布...");
        for (i = 0; i < 3; i++) {
            printf("(%d)%s ", i, hd[i]);
        }
        printf(": ");
        scanf("%d", &human); /* 读取玩家的手势 */
    } while (human < 0 || human > 2);
}

/* 更新和显示结果 */
void update_and_display_result(int result) {
    switch (result) {
    case 0:
        draw_no++;
        puts("平局。");
        break;
    case 1:
        lose_no++;
        puts("你输了。");
        break;
    case 2:
        win_no++;
        puts("你赢了。");
        break;
    }
}

/* 确认是否再次挑战 */
int confirm_retry(void) {
    int x;
    printf("再来一次吗...(0)否(1)是:");
    scanf("%d", &x);
    return x;
}

int main(void) {
    int judge; /* 胜负 */
    int retry; /* 再来一次? */

    initialize(); /* 初始处理 */

    do {
        jyanken(); /* 运行猜拳游戏 */

        /* 显示计算机和玩家的手势 */
        printf("我出%s,你出%s。\n", hd[comp], hd[human]);

        judge = (human - comp + 3) % 3; /* 判断胜负 */
        update_and_display_result(judge); /* 更新和显示结果 */

        retry = confirm_retry(); /* 确认是否再次挑战 */
    } while (retry == 1);

    printf("%d胜 %d负 %d平。\n", win_no, lose_no, draw_no);
    return 0;
}

3-4

编写一个“猜拳游戏”,让计算机第1次一定出石头。
※让计算机从第2次开始随机出石头、剪刀或者布。

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int human; /* 玩家手势 */
int comp; /* 计算机手势 */
int win_no; /* 胜利次数 */
int lose_no; /* 失败次数 */
int draw_no; /* 平局次数 */
int round_no; /* 游戏轮数 */

const char* hd[] = { "石头", "剪刀", "布" }; /* 手势 */

/* 初始处理 */
void initialize(void) {
    win_no = 0; /* 胜利次数 */
    lose_no = 0; /* 失败次数 */
    draw_no = 0; /* 平局次数 */
    round_no = 0; /* 游戏轮数 */
    srand(time(NULL)); /* 设定随机数种子 */
    printf("猜拳游戏开始!\n");
}

/* 运行猜拳游戏(读取/生成手势) */
void jyanken(void) {
    int i;
    if (round_no == 0) {
        comp = 0; /* 第1次一定出石头 */
    }
    else {
        comp = rand() % 3; /* 从第2次开始随机生成手势(0, 1, 2) */
    }
    do {
        printf("\n\a石头剪刀布...");
        for (i = 0; i < 3; i++) {
            printf("(%d)%s ", i, hd[i]);
        }
        printf(": ");
        scanf("%d", &human); /* 读取玩家的手势 */
    } while (human < 0 || human > 2);
}

/* 更新和显示结果 */
void update_and_display_result(int result) {
    switch (result) {
    case 0:
        draw_no++;
        puts("平局。");
        break;
    case 1:
        lose_no++;
        puts("你输了。");
        break;
    case 2:
        win_no++;
        puts("你赢了。");
        break;
    }
}

/* 确认是否再次挑战 */
int confirm_retry(void) {
    int x;
    printf("再来一次吗...(0)否(1)是:");
    scanf("%d", &x);
    return x;
}

int main(void) {
    int judge; /* 胜负 */
    int retry; /* 再来一次? */

    initialize(); /* 初始处理 */

    do {
        jyanken(); /* 运行猜拳游戏 */
        round_no++; /* 增加轮数 */

        /* 显示计算机和玩家的手势 */
        printf("我出%s,你出%s。\n", hd[comp], hd[human]);

        judge = (human - comp + 3) % 3; /* 判断胜负 */
        update_and_display_result(judge); /* 更新和显示结果 */

        retry = confirm_retry(); /* 确认是否再次挑战 */
    } while (retry == 1);

    printf("%d胜 %d负 %d平。\n", win_no, lose_no, draw_no);
    return 0;
}

3-5

编写一个“猜拳游戏”,让计算机每5次就会“后出”编写两个版本,一个是只要玩家愿意就能不断重复玩的“猜拳游戏”,另一个是猜赢n次就会结束的“猜拳游戏”。

//版本一
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int human; /* 玩家手势 */
int comp; /* 计算机手势 */
int win_no; /* 胜利次数 */
int lose_no; /* 失败次数 */
int draw_no; /* 平局次数 */
int round_no; /* 游戏轮数 */

const 
char* hd[] = { "石头", "剪刀", "布" }; /* 手势 */

/* 初始处理 */
void initialize(void) {
    win_no = 0; /* 胜利次数 */
    lose_no = 0; /* 失败次数 */
    draw_no = 0; /* 平局次数 */
    round_no = 0; /* 游戏轮数 */
    srand(time(NULL)); /* 设定随机数种子 */
    printf("猜拳游戏开始!\n");
}

/* 运行猜拳游戏(读取/生成手势) */
void jyanken(void) {
    int i;
    if (round_no % 5 == 4) {
        printf("请你先出:\n");
        for (i = 0; i < 3; i++) {
            printf("(%d)%s ", i, hd[i]);
        }
        printf(": ");
        scanf("%d", &human); /* 读取玩家的手势 */
        comp = rand() % 3; /* 随机生成计算机手势 */
    }
    else {
        comp = rand() % 3; /* 随机生成计算机手势 */
        do {
            printf("\n\a石头剪刀布...");
            for (i = 0; i < 3; i++) {
                printf("(%d)%s ", i, hd[i]);
            }
            printf(": ");
            scanf("%d", &human); /* 读取玩家的手势 */
        } while (human < 0 || human > 2);
    }
}

/* 更新和显示结果 */
void update_and_display_result(int result) {
    switch (result) {
    case 0:
        draw_no++;
        puts("平局。");
        break;
    case 1:
        lose_no++;
        puts("你输了。");
        break;
    case 2:
        win_no++;
        puts("你赢了。");
        break;
    }
}

/* 确认是否再次挑战 */
int confirm_retry(void) {
    int x;
    printf("再来一次吗...(0)否(1)是:");
    scanf("%d", &x);
    return x;
}

int main(void) {
    int judge; /* 胜负 */
    int retry; /* 再来一次? */

    initialize(); /* 初始处理 */

    do {
        jyanken(); /* 运行猜拳游戏 */
        round_no++; /* 增加轮数 */

        /* 显示计算机和玩家的手势 */
        printf("我出%s,你出%s。\n", hd[comp], hd[human]);

        judge = (human - comp + 3) % 3; /* 判断胜负 */
        update_and_display_result(judge); /* 更新和显示结果 */

        retry = confirm_retry(); /* 确认是否再次挑战 */
    } while (retry == 1);

    printf("%d胜 %d负 %d平。\n", win_no, lose_no, draw_no);
    return 0;
}

//版本二
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int human; /* 玩家手势 */
int comp; /* 计算机手势 */
int win_no; /* 胜利次数 */
int lose_no; /* 失败次数 */
int draw_no; /* 平局次数 */
int round_no; /* 游戏轮数 */
int target_wins; /* 目标胜利次数 */

const char* hd[] = { "石头", "剪刀", "布" }; /* 手势 */

/* 初始处理 */
void initialize(void) {
    win_no = 0; /* 胜利次数 */
    lose_no = 0; /* 失败次数 */
    draw_no = 0; /* 平局次数 */
    round_no = 0; /* 游戏轮数 */
    srand(time(NULL)); /* 设定随机数种子 */
    printf("猜拳游戏开始!\n");

    /* 询问目标胜利次数 */
    printf("要猜赢几次?");
    scanf("%d", &target_wins);
}

/* 运行猜拳游戏(读取/生成手势) */
void jyanken(void) {
    int i;
    if (round_no % 5 == 4) {
        printf("请你先出:\n");
        for (i = 0; i < 3; i++) {
            printf("(%d)%s ", i, hd[i]);
        }
        printf(": ");
        scanf("%d", &human); /* 读取玩家的手势 */
        comp = rand() % 3; /* 随机生成计算机手势 */
    }
    else {
        comp = rand() % 3; /* 随机生成计算机手势 */
        do {
            printf("\n\a石头剪刀布...");
            for (i = 0; i < 3; i++) {
                printf("(%d)%s ", i, hd[i]);
            }
            printf(": ");
            scanf("%d", &human); /* 读取玩家的手势 */
        } while (human < 0 || human > 2);
    }
}

/* 更新和显示结果 */
void update_and_display_result(int result) {
    switch (result) {
    case 0:
        draw_no++;
        puts("平局。");
        break;
    case 1:
        lose_no++;
        puts("你输了。");
        break;
    case 2:
        win_no++;
        puts("你赢了。");
        break;
    }
}

int main(void) {
    int judge; /* 胜负 */

    initialize(); /* 初始处理 */

    do {
        jyanken(); /* 运行猜拳游戏 */
        round_no++; /* 增加轮数 */

        /* 显示计算机和玩家的手势 */
        printf("我出%s,你出%s。\n", hd[comp], hd[human]);

        judge = (human - comp + 3) % 3; /* 判断胜负 */
        update_and_display_result(judge); /* 更新和显示结果 */

    } while (win_no < target_wins && lose_no < target_wins);

    printf(win_no == target_wins ? "\n你赢了。\n" : "\n我赢了。\n");
    printf("%d胜 %d负 %d平。\n", win_no, lose_no, draw_no);
    return 0;
}

3-6

编写一个“猜拳游戏”,让游戏结束时显示玩家和计算机出过的所有手势和胜负的历史记录。
编写两个版本,一个是只要玩家愿意就能不断重复玩的“猜拳游戏”,另一个是猜赢n次就会结束的“猜拳游戏”。
※关于历史记录的保存可参见第5章。

//版本一
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define MAX_ROUNDS 1000 /* 最大记录轮数 */

int human; /* 玩家手势 */
int comp; /* 计算机手势 */
int win_no; /* 胜利次数 */
int lose_no; /* 失败次数 */
int draw_no; /* 平局次数 */
int round_no; /* 游戏轮数 */

char *hd[] = {"石头", "剪刀", "布"}; /* 手势 */

int human_history[MAX_ROUNDS]; /* 保存玩家手势 */
int comp_history[MAX_ROUNDS]; /* 保存计算机手势 */
int result_history[MAX_ROUNDS]; /* 保存胜负记录 */

/* 初始处理 */
void initialize(void) {
    win_no = 0; /* 胜利次数 */
    lose_no = 0; /* 失败次数 */
    draw_no = 0; /* 平局次数 */
    round_no = 0; /* 游戏轮数 */
    srand(time(NULL)); /* 设定随机数种子 */
    printf("猜拳游戏开始!\n");
}

/* 运行猜拳游戏(读取/生成手势) */
void jyanken(void) {
    int i;
    if (round_no % 5 == 4) {
        printf("请你先出:\n");
        for (i = 0; i < 3; i++) {
            printf("(%d)%s ", i, hd[i]);
        }
        printf(": ");
        scanf("%d", &human); /* 读取玩家的手势 */
        comp = rand() % 3; /* 随机生成计算机手势 */
    } else {
        comp = rand() % 3; /* 随机生成计算机手势 */
        do {
            printf("\n\a石头剪刀布...");
            for (i = 0; i < 3; i++) {
                printf("(%d)%s ", i, hd[i]);
            }
            printf(": ");
            scanf("%d", &human); /* 读取玩家的手势 */
        } while (human < 0 || human > 2);
    }
}

/* 更新和显示结果 */
void update_and_display_result(int result) {
    switch (result) {
        case 0:
            draw_no++;
            puts("平局。");
            break;
        case 1:
            lose_no++;
            puts("你输了。");
            break;
        case 2:
            win_no++;
            puts("你赢了。");
            break;
    }
}

/* 记录历史 */
void record_history(int human, int comp, int result) {
    if (round_no < MAX_ROUNDS) {
        human_history[round_no] = human;
        comp_history[round_no] = comp;
        result_history[round_no] = result;
    }
}

/* 显示历史记录 */
void display_history(void) {
    printf("\n历史记录:\n");
    for (int i = 0; i < round_no; i++) {
        printf("第%d轮:你出%s,我出%s -> %s\n", 
            i + 1, hd[human_history[i]], hd[comp_history[i]], 
            result_history[i] == 0 ? "平局" : (result_history[i] == 1 ? "你输了" : "你赢了"));
    }
}

int main(void) {
    int judge; /* 胜负 */
    int retry; /* 再来一次? */

    initialize(); /* 初始处理 */

    do {
        jyanken(); /* 运行猜拳游戏 */
        judge = (human - comp + 3) % 3; /* 判断胜负 */
        update_and_display_result(judge); /* 更新和显示结果 */
        record_history(human, comp, judge); /* 记录历史 */
        round_no++; /* 增加轮数 */

        printf("再来一次吗...(0)否(1)是:");
        scanf("%d", &retry);
    } while (retry == 1);

    display_history(); /* 显示历史记录 */

    printf("%d胜 %d负 %d平。\n", win_no, lose_no, draw_no);
    return 0;
}

//版本二
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define MAX_ROUNDS 1000 /* 最大记录轮数 */

int human; /* 玩家手势 */
int comp; /* 计算机手势 */
int win_no; /* 胜利次数 */
int lose_no; /* 失败次数 */
int draw_no; /* 平局次数 */
int round_no; /* 游戏轮数 */
int target_wins; /* 目标胜利次数 */

const char *hd[] = {"石头", "剪刀", "布"}; /* 手势 */

int human_history[MAX_ROUNDS]; /* 保存玩家手势 */
int comp_history[MAX_ROUNDS]; /* 保存计算机手势 */
int result_history[MAX_ROUNDS]; /* 保存胜负记录 */

/* 初始处理 */
void initialize(void) {
    win_no = 0; /* 胜利次数 */
    lose_no = 0; /* 失败次数 */
    draw_no = 0; /* 平局次数 */
    round_no = 0; /* 游戏轮数 */
    srand(time(NULL)); /* 设定随机数种子 */
    printf("猜拳游戏开始!\n");

    /* 询问目标胜利次数 */
    printf("要猜赢几次?");
    scanf("%d", &target_wins);
}

/* 运行猜拳游戏(读取/生成手势) */
void jyanken(void) {
    int i;
    if (round_no % 5 == 4) {
        printf("请你先出:\n");
        for (i = 0; i < 3; i++) {
            printf("(%d)%s ", i, hd[i]);
        }
        printf(": ");
        scanf("%d", &human); /* 读取玩家的手势 */
        comp = rand() % 3; /* 随机生成计算机手势 */
    } else {
        comp = rand() % 3; /* 随机生成计算机手势 */
        do {
            printf("\n\a石头剪刀布...");
            for (i = 0; i < 3; i++) {
                printf("(%d)%s ", i, hd[i]);
            }
            printf(": ");
            scanf("%d", &human); /* 读取玩家的手势 */
        } while (human < 0 || human > 2);
    }
}

/* 更新和显示结果 */
void update_and_display_result(int result) {
    switch (result) {
        case 0:
            draw_no++;
            puts("平局。");
            break;
        case 1:
            lose_no++;
            puts("你输了。");
            break;
        case 2:
            win_no++;
            puts("你赢了。");
            break;
    }
}

/* 记录历史 */
void record_history(int human, int comp, int result) {
    if (round_no < MAX_ROUNDS) {
        human_history[round_no] = human;
        comp_history[round_no] = comp;
        result_history[round_no] = result;
    }
}

/* 显示历史记录 */
void display_history(void) {
    printf("\n历史记录:\n");
    for (int i = 0; i < round_no; i++) {
        printf("第%d轮:你出%s,我出%s -> %s\n", 
            i + 1, hd[human_history[i]], hd[comp_history[i]], 
            result_history[i] == 0 ? "平局" : (result_history[i] == 1 ? "你输了" : "你赢了"));
    }
}

int main(void) {
    int judge; /* 胜负 */

    initialize(); /* 初始处理 */

    do {
        jyanken(); /* 运行猜拳游戏 */
        judge = (human - comp + 3) % 3; /* 判断胜负 */
        update_and_display_result(judge); /* 更新和显示结果 */
        record_history(human, comp, judge); /* 记录历史 */
        round_no++; /* 增加轮数 */
    } while (win_no < target_wins && lose_no < target_wins);

    display_history(); /* 显示历史记录 */

    printf(win_no == target_wins ? "\n你赢了。\n" : "\n我赢了。\n");
    printf("%d胜 %d负 %d平。\n", win_no, lose_no, draw_no);
    return 0;
}

3-7

练习3-7编写一个3人对战的“猜拳游戏”。由计算机来担任2个角色,这2个角色的手势都用随机数来生成。
编写两个版本,一个是只要玩家愿意就能不断重复玩的“猜拳游戏”,另一个是猜赢n次就会结束的“猜拳游戏”。

//版本一
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define MAX_ROUNDS 1000 /* 最大记录轮数 */

int human; /* 玩家手势 */
int comp1; /* 计算机1手势 */
int comp2; /* 计算机2手势 */
int win_no; /* 胜利次数 */
int lose_no; /* 失败次数 */
int draw_no; /* 平局次数 */
int round_no; /* 游戏轮数 */

const char* hd[] = { "石头", "剪刀", "布" }; /* 手势 */

int human_history[MAX_ROUNDS]; /* 保存玩家手势 */
int comp1_history[MAX_ROUNDS]; /* 保存计算机1手势 */
int comp2_history[MAX_ROUNDS]; /* 保存计算机2手势 */
int result_history[MAX_ROUNDS]; /* 保存胜负记录 */

/* 初始处理 */
void initialize(void) {
    win_no = 0; /* 胜利次数 */
    lose_no = 0; /* 失败次数 */
    draw_no = 0; /* 平局次数 */
    round_no = 0; /* 游戏轮数 */
    srand(time(NULL)); /* 设定随机数种子 */
    printf("猜拳游戏开始!\n");
}

/* 运行猜拳游戏(读取/生成手势) */
void jyanken(void) {
    int i;
    comp1 = rand() % 3; /* 随机生成计算机1手势 */
    comp2 = rand() % 3; /* 随机生成计算机2手势 */
    do {
        printf("\n\a石头剪刀布...");
        for (i = 0; i < 3; i++) {
            printf("(%d)%s ", i, hd[i]);
        }
        printf(": ");
        scanf("%d", &human); /* 读取玩家的手势 */
    } while (human < 0 || human > 2);
}

/* 更新和显示结果 */
void update_and_display_result(int result) {
    switch (result) {
    case 0:
        draw_no++;
        puts("平局。");
        break;
    case 1:
        lose_no++;
        puts("你输了。");
        break;
    case 2:
        win_no++;
        puts("你赢了。");
        break;
    }
}

/* 记录历史 */
void record_history(int human, int comp1, int comp2, int result) {
    if (round_no < MAX_ROUNDS) {
        human_history[round_no] = human;
        comp1_history[round_no] = comp1;
        comp2_history[round_no] = comp2;
        result_history[round_no] = result;
    }
}

/* 显示历史记录 */
void display_history(void) {
    printf("\n历史记录:\n");
    for (int i = 0; i < round_no; i++) {
        printf("第%d轮:你出%s,计算机1出%s,计算机2出%s -> %s\n",
            i + 1, hd[human_history[i]], hd[comp1_history[i]], hd[comp2_history[i]],
            result_history[i] == 0 ? "平局" : (result_history[i] == 1 ? "你输了" : "你赢了"));
    }
}

/* 判断三者之间的胜负 */
int judge_result(int human, int comp1, int comp2) {
    if (human == comp1 && comp1 == comp2) {
        return 0; // 平局
    }

    int win = 0, lose = 0;
    
    if(comp2 == comp1&& (human - comp2 + 3) % 3 == 2)   return 2;
    if (comp2 == comp1 && (human - comp2 + 3) % 3 == 1)   return 1;


    if (human == comp1 && (human - comp2 + 3) % 3 == 2)    return 2;
    if (human == comp1 && (human - comp2 + 3) % 3 == 1)   return 1;
    
    if (human == comp2 && (human - comp1 + 3) % 3 == 2)   return 2;
    if (human == comp2 && (human - comp1 + 3) % 3 == 1)   return 1;

    return 0;

}

int main(void) {
    int judge; /* 胜负 */
    int retry; /* 再来一次? */

    initialize(); /* 初始处理 */

    do {
        jyanken(); /* 运行猜拳游戏 */
        judge = judge_result(human, comp1, comp2); /* 判断胜负 */
        update_and_display_result(judge); /* 更新和显示结果 */
        record_history(human, comp1, comp2, judge); /* 记录历史 */
        round_no++; /* 增加轮数 */

        printf("再来一次吗...(0)否(1)是:");
        scanf("%d", &retry);
    } while (retry == 1);

    display_history(); /* 显示历史记录 */

    printf("%d胜 %d负 %d平。\n", win_no, lose_no, draw_no);
    return 0;
}

//版本二
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define MAX_ROUNDS 1000 /* 最大记录轮数 */

int human; /* 玩家手势 */
int comp1; /* 计算机1手势 */
int comp2; /* 计算机2手势 */
int win_no; /* 胜利次数 */
int lose_no; /* 失败次数 */
int draw_no; /* 平局次数 */
int round_no; /* 游戏轮数 */
int target_wins; /* 目标胜利次数 */

const char* hd[] = { "石头", "剪刀", "布" }; /* 手势 */

int human_history[MAX_ROUNDS]; /* 保存玩家手势 */
int comp1_history[MAX_ROUNDS]; /* 保存计算机1手势 */
int comp2_history[MAX_ROUNDS]; /* 保存计算机2手势 */
int result_history[MAX_ROUNDS]; /* 保存胜负记录 */

/* 初始处理 */
void initialize(void) {
    win_no = 0; /* 胜利次数 */
    lose_no = 0; /* 失败次数 */
    draw_no = 0; /* 平局次数 */
    round_no = 0; /* 游戏轮数 */
    srand(time(NULL)); /* 设定随机数种子 */
    printf("猜拳游戏开始!\n");

    /* 询问目标胜利次数 */
    printf("要猜赢几次?");
    scanf("%d", &target_wins);
}

/* 运行猜拳游戏(读取/生成手势) */
void jyanken(void) {
    int i;
    comp1 = rand() % 3; /* 随机生成计算机1手势 */
    comp2 = rand() % 3; /* 随机生成计算机2手势 */
    do {
        printf("\n\a石头剪刀布...");
        for (i = 0; i < 3; i++) {
            printf("(%d)%s ", i, hd[i]);
        }
        printf(": ");
        scanf("%d", &human); /* 读取玩家的手势 */
    } while (human < 0 || human > 2);
}

/* 更新和显示结果 */
void update_and_display_result(int result) {
    switch (result) {
    case 0:
        draw_no++;
        puts("平局。");
        break;
    case 1:
        lose_no++;
        puts("你输了。");
        break;
    case 2:
        win_no++;
        puts("你赢了。");
        break;
    }
}

/* 记录历史 */
void record_history(int human, int comp1, int comp2, int result) {
    if (round_no < MAX_ROUNDS) {
        human_history[round_no] = human;
        comp1_history[round_no] = comp1;
        comp2_history[round_no] = comp2;
        result_history[round_no] = result;
    }
}

/* 显示历史记录 */
void display_history(void) {
    printf("\n历史记录:\n");
    for (int i = 0; i < round_no; i++) {
        printf("第%d轮:你出%s,计算机1出%s,计算机2出%s -> %s\n",
            i + 1, hd[human_history[i]], hd[comp1_history[i]], hd[comp2_history[i]],
            result_history[i] == 0 ? "平局" : (result_history[i] == 1 ? "你输了" : "你赢了"));
    }
}

/* 判断三者之间的胜负 */
int judge_result(int human, int comp1, int comp2) {
    if (human == comp1 && comp1 == comp2) {
        return 0; // 平局
    }

    if (comp2 == comp1 && (human - comp2 + 3) % 3 == 2) return 2;
    if (comp2 == comp1 && (human - comp2 + 3) % 3 == 1) return 1;

    if (human == comp1 && (human - comp2 + 3) % 3 == 2) return 2;
    if (human == comp1 && (human - comp2 + 3) % 3 == 1) return 1;

    if (human == comp2 && (human - comp1 + 3) % 3 == 2) return 2;
    if (human == comp2 && (human - comp1 + 3) % 3 == 1) return 1;

    return 0;
}

int main(void) {
    int judge; /* 胜负 */

    initialize(); /* 初始处理 */

    do {
        jyanken(); /* 运行猜拳游戏 */
        judge = judge_result(human, comp1, comp2); /* 判断胜负 */
        update_and_display_result(judge); /* 更新和显示结果 */
        record_history(human, comp1, comp2, judge); /* 记录历史 */
        round_no++; /* 增加轮数 */
    } while (win_no < target_wins);

    display_history(); /* 显示历史记录 */

    printf("%d胜 %d负 %d平。\n", win_no, lose_no, draw_no);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值