C语言练习--打字器项目代码(vs2019)

#include<stdio.h>    
#include<time.h>
#include<stdlib.h>
#include<conio.h>                             //knhit()的头文件
#include<graphics.h>
#define _CRT_SECURE_NO_WARNINGS

//设计数据;设计窗口属性

const int WIDTH = 640; //640
const int HEIGHT = 500;//500

//正确率和错误率
 int right=0;
 int error=0;

 

 //写一个结构体,保存下落的文字信息(坐标+保存文字的指针)
 struct TARGET
 {
     int x, y;
     char* str;
};

 //写一个结构体,保存用户键盘输入的信息
 struct USRKEY
 {
     int x, y;
     char str[20];
 }userkey = { 320,500 - 30,"" };  //这是给结构体里面的元素初始化值,是一种格式

 //在指定位置输出整数
 void outtextxy_int(int x,int y,char* format,int num) //char* format固定的表示格式%xxxx
 {
     char str[20] = "";
     sprintf(str, format, num);
     outtextxy(x, y, str);
 }
 //在指定位置输出浮点数
 void outtextxy_double(double x, double y, char* format, double num)
 {
     char str[20] = "";
     sprintf(str, format, num);
     outtextxy(x, y, str);
 }

 void divwindow()   //写个函数,来切割窗口成几块
 {
     setlinecolor(RED);
     line(WIDTH-100, 0, WIDTH-100, HEIGHT-40);
     line(0,HEIGHT-40, WIDTH + 50, HEIGHT-40);
     line(WIDTH - 100, 130, WIDTH + 50, 130);
 }
 //通过结构体随机产生下落的字符,通过随机产生数组下标方式产生,把字符串存到结构体的二维数组里
 void initTarget(struct TARGET words[],int n) // word[],即结构体数组
 {
     static char str[43][42] = { "main","int","extern","static","volatile","initgraph","line","int","char","long","double",
     "float","struct","union","outtextxy","sprintf","graphics","NOR","XOR","NAND","AND","OR","NOT","return","include","while","for","switch",
     "case","break","goto","if","enum","private","public","class","default","else" ,"%p","%s","%c","%d","typedef"};

     //随机生成字符下标(取余算法)
     words[n].str = str[rand() % 43];

     //不断检测重复,如果重复,则重新生成
     while (words[n].str == words[(n + 1) % 3].str || words[n].str == words[(n + 2) % 3].str)
     {
         words[n].str = str[rand() % 37]; // rand()函数对一个数字取余,是算法:产生XX以内的数
     }
     words[n].x = rand() % (WIDTH - 200);
     words[n].y = -20;
 }

 void drawScore()
 {
     settextcolor(YELLOW);//设置字体颜色
     settextstyle(25, 0, "STXINGKA");//设置字体
     outtextxy(WIDTH - 90, 25, "鄂学谦");
     outtextxy(WIDTH - 90, 25+25, "打字练习器");

     outtextxy(WIDTH - 90, 225, "正确");
     outtextxy_int(WIDTH - 90, 225 + 25, "%d",right);  //调用之前封装的打印整形的函数outtextxy_int,安装%d的格式
     
     outtextxy(WIDTH - 90, 285, "错误");
     outtextxy_int(WIDTH - 90, 285 + 25, "%d", error);

     outtextxy(WIDTH - 90, 285+285-225, "正确率");
     if (right + error == 0)
     {
         outtextxy_double(WIDTH - 90, 285 + 285 - 225, "%.2lf%%",0.00);
     }
     else
     {    //c语言 除法会取整
         double sum = right + error;
         outtextxy_double(WIDTH - 90, 285 + 285 - 225, "%.2lf%%", right / sum * 100);
     }
     }


int main()

{
    srand((unsigned int)time(NULL));//初始化随机函数,即清空里面的历史值
    
    initgraph(WIDTH+50, HEIGHT);  //1.创建一个可视化窗口,并设置窗口的属性和坐标

    
    struct TARGET words[3]; //一次生成3个下落的字符
    for (int n = 0; n < 3; n++)
    {
        initTarget(words,n);
        words[n].y = -15 - n * 30;//形成不等高
    }

    BeginBatchDraw();//开始双缓存绘图,先把图画好了再显示出来,不会一闪一闪的

    int i = 0;//定义一个计数的数,需要初始化从0开始计
    
    while (1)
    {
        cleardevice();//清空图形界面的函数
        divwindow();
        for (int n = 0; n < 3; n++) //碰线处理
        {
            words[n].y += 2;//往下落,关于下落速度
            if (words[n].y > (HEIGHT - 40 - textheight(words[n].str)))//如果碰线,其中 textheight是当前文字高度
            {
                initTarget(words, n);//消失就是再初始化一下
            }
        }
        for (int n = 0; n < 3; n++)//文字往下落,打印文字
        {
            settextcolor(RED);
            outtextxy(words[n].x, words[n].y, words[n].str);
        
        }

        if (kbhit())//kbhit()函数,如果有按键输入则返回非0,否则返回0
        {
            char target;//如果有按键输入,定义一个target接受用户的值,将字符串变成字符处理
            if ((target = getch()) != '\r') //如果用户输入不为换行符
            {
                userkey.str[i++] = target;//把用户输入保存到用户输入的字符串数组userkey里面去,target在此表示当前字符
            //    userkey.x += 5;   如果加上这个,用户输入会一直往右跑
            }
            else  //if和else之后的语句,每次只会执行一个;这里else里的语句,就是当输入是为换行符\r的时候,就会执行以下,即输入换行的时候,开始第二次输入
            {
                int flagError = 0;//"加标记"的的思想,起开关的作用,如果输入错误,error加1

                for (i = 0; i < 3; i++)//输入换行,即确认后,判断输入是否正确,正确则消除
                {
                    if (strcmp(userkey.str, words[i].str) == 0)
                    {
                        initTarget(words, i);
                        right++;
                        flagError = 1;//输入正确的时候,错误标记置为1
                    }
                }

                if (flagError == 0) //标记对应的动作实现,如果对不上,error++
                {
                    error++;
                }
                    i = 0;   //第二次输入的时候,把i置0,否则会一直堆积
                userkey.x = 320;  //把用户输入的显示坐标还原为320,而不是一直往后堆积跑
                memset(userkey.str, 0, 20);   //防止用户输入堆积,重置输入的字符串
            }
        }
        outtextxy(userkey.x, userkey.y, userkey.str);//没有这个,用户输入显示不出
        drawScore();
        FlushBatchDraw();//easyx里面的,双缓存绘图,批量绘图;从BeginBatchDraw()开始,直到这里才会把之前所有的绘图内容显示出来,期间不会显示绘图语句,用于防止程序闪屏
        Sleep(50);//文字下落的速度,并且防止闪退
            
        }

    getchar();
    closegraph();
    return 0;
}

#include"head.h" void PlayMusic(const char* FileName) { char cmdString[50] = "open "; strcat_s(cmdString, FileName); strcat_s(cmdString, " alias bkmusic"); mciSendString(cmdString, NULL, 0, NULL); //打开音乐 mciSendString("play bkmusic repeat", NULL, NULL, NULL); //循环播放次音乐 } int main() { PlayMusic("111.mp3 ");//播放 initgraph(600,480); int Easy = 0, General = 0, Hard = 0, *EasyScore = &Easy;, *GeneralScore = &General;, *HardScore = &Hard; Enter_Interface(EasyScore,GeneralScore,HardScore); system("pause"); return 0; } //开始界面 void Enter_Interface(int*EasyScore, int*GeneralScore, int*HardScore) { char s[5]; cleardevice();//清屏 IMAGE bk; loadimage(&bk;,"sk1.jpg",600,480); putimage(0,0,&bk;); setbkmode(TRANSPARENT); int r = rand() % 256; int g = rand() % 256; int b = rand() % 256; settextstyle(48, 0, "楷体"); setcolor(RGB(r, g, b)); // outtextxy(125, 130, "按对应数字进入游戏"); setcolor(RED); settextstyle(64, 0, "新宋体"); BeginBatchDraw(); IMAGE bk; for(int y=0;y<40;y++) { putimage(0,0,&bk;); outtextxy(172, y, "字"); outtextxy(172+64, y, "母"); outtextxy(172+64+64, y, "游"); outtextxy(172+64+64+64, y, "戏"); FlushBatchDraw(); Sleep(50);//设置延时 } EndBatchDraw(); //outtextxy(172, 40, "字母游戏"); setcolor(WHITE); settextstyle(40, 0, "宋体"); outtextxy(125, 130, "按对应字母进入游戏"); settextstyle(30, 0, "宋体"); outtextxy(202, 194, "1、简单"); outtextxy(202, 283, "2、一般"); outtextxy(202, 372, "3、困难"); settextstyle(24, 0, "新宋体"); outtextxy(334, 259, "最高分:"); _itoa_s(*EasyScore, s, 10);//将整形数据转为字符串 outtextxy(440, 259, s); outtextxy(334, 348, "最高分:"); _itoa_s(*GeneralScore, s, 10); outtextxy(440, 348, s); outtextxy(334, 437, "最高分:"); _itoa_s(*HardScore, s, 10); outtextxy(440, 437, s); char choose;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值