// 编程设计打字游戏：
//     1)随机函数
// 	A.srand((unsigned)time(NULL));
//     以当前时间为准，设置随机种子
//     注意：此函数，在每次开始游戏后调用一次即可
//     B.ch = rand();
//       注意：rand()函数，每调用一次，产生一个随机数字

// 	2)获得键值函数
// 	  ch=mygetch();  //无需按下回车，可直接获得键盘上按下的键值

//       还可以自己封装一个无阻塞，无回显的getch，实现如下：
// #include <termios.h>
// #include <unistd.h>
//           char
//           mygetch()
//       {
//           struct termios oldt, newt;
//           char ch;
//           tcgetattr(STDIN_FILENO, &oldt);
//           newt = oldt;
//           newt.c_lflag &= ~(ICANON | ECHO);
//           tcsetattr(STDIN_FILENO, TCSANOW, &newt);
//           ch = getchar();
//           tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
//           return ch;
//       }
//     3)时间函数
// 	start_time=time(NULL);
//     edn_time = time(NULL);
//     //可以返回系统当前时间，以秒为单位

//     4)system("clear");//清空屏幕

//     5)所需头文件
// #include <time.h>
// #include <math.h>
// #include <stdio.h>
// #include <stdlib.h>

#include <time.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>

char mygetch();
void help();

int main()
{
    int NUMS_OF_CHARS = 11; // 字符总数
    char ch;                // 键盘输入字符
    char str[11] = "";      // 题目字符数组
    int i;
    int cnt;                     // 正确数
    time_t start_time, end_time; // 开始，结束时间

    help();         // 首次进入游戏时主动显示游戏提示
    ch = mygetch(); // 按任意键开始游戏
    while (1)
    {

        // help();                      // 首次进入游戏时主动显示游戏提示 (这里如果解注释，则会每次都显示帮助信息)
        // ch = mygetch();              // 按任意键开始游戏

        srand((unsigned)time(NULL)); // 设置随机种子
        for (i = 0; i < NUMS_OF_CHARS - 1; i++)
        {
            switch (rand() % 3) // 根据每一次的随机值安顿好当前位置的字符类型
            {
            case 0:
                str[i] = rand() % 10 + '0'; // 0-9的数字
                break;
            case 1:
                str[i] = rand() % 26 + 'a'; // a-z的数字
                break;
            case 2:
                str[i] = rand() % 26 + 'A'; // A-Z的数字
                break;
            }
        }

        // str[NUMS_OF_CHARS - 1] = '\0'; // 末位补上结束符
        printf("%s\n", str);
        cnt = 0; // 计数器初始化为 0
        for (i = 0; i < NUMS_OF_CHARS - 1; i++)
        {
            ch = mygetch(); // 获取每一次的按键输入
            if (i == 0)     // 如果第一次按下任意键，则开始计时
                start_time = time(NULL);
            if (ch == str[i])
            {
                cnt++;            // 当按下的键和题目数组对应位置的值一致时，成功计数器加一
                printf("%c", ch); // 打印正确键入的字符
                continue;         // 继续下一位置的字符输入
            }
            else
            {
                printf("*"); // 如果输入的键和题目不匹配，则显示为 *
                continue;
            }
        }

        end_time = time(NULL); // 全部输入结束后，记录结束时间
        printf("\n你的打字正确率为 %d %c\n", cnt * 100 / (NUMS_OF_CHARS - 1), '%');
        printf("总共用时为 %lld 秒\n", (long long int)end_time - start_time);
        while (1) // 再次获取一下键盘输入
        {
            ch = mygetch();
            if (ch == 32)
            {
                system("clear"); // 清空屏幕
                break;           // 按 SPACE (ASCII=32) 跳出小循环，进入大循环，即重新一轮游戏
            }
            else if (ch == 27)
                return 0; // 按下 ESC (ASCII=27) 键退出游戏 (return 0 --- 程序结束)
        }
    }
    return 0; // 程序结束
}

char mygetch() // 无阻塞，无回显的getch
{
    struct termios oldt, newt;
    char ch;
    tcgetattr(STDIN_FILENO, &oldt);
    newt = oldt;
    newt.c_lflag &= ~(ICANON | ECHO);
    tcsetattr(STDIN_FILENO, TCSANOW, &newt);
    ch = getchar();
    tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
    return ch;
}

void help() // 游戏提示信息
{
    printf("\n *******************************************");
    printf("\n *请按所给字母敲击键盘！                   *");
    printf("\n *请按任意键开始测试，按下首字母时开始计时!*");
    printf("\n *输入出错则以 * 表示                      *");
    printf("\n *按空格键继续游戏 (新一轮游戏)            *");
    printf("\n *按 ESC 退出游戏                          *");
    printf("\n *******************************************\n");
}