C语言小白用easyX实现的一个简单的打字游戏
不要在意名字,这是学习中调侃一下室友,劳役结合。
如果没有图片,由于字体和背景颜色设置的问题,难度一和难度二估计看不到什么。 难度三正常。图片可以根据代码自己弄一下,或者问我要也行。
easyX实现的一个简单的打字游戏
学习easyx时随便写的一个小项目,单词模式可接受退格,分享出来和大家一起研究学习。
图片就几张背景图和一张掩码图,可以自己找。
图片展示
程序整体设计思想
游戏开始后,鼠标选择对应难度,单机开始游戏,字母模式时,输入对应字母,字母直接消除,单词模式时,可以接受退格,按回车确定输入,输入的单词正确时单词消除。 要有加速减速及速度复位,显示分数和正确率等功能。
程序整体设计流程图
重点子程序分析
随机产生字母和字符串利用时间做种子,对26进行求余,再加上65 ,就是字母的ASCLL码
字符串就是自己创一个字符串数组,然后用rand对其总数求余,利用下标对应字母。
2.字符的下落
利用easyx的输出机制,改变字符的Y坐标,使其慢慢增加,视觉上达到字符降落的效果
编译遇到的两个报错:
没有与参数列表匹配的重在函数实例的错误,错误代码E0304错误原因
是因为字符串的实际存储有多种编码格式,如果默认的编码格式和实际执行的平台不相符就会发生错误。
解决方案
以VS为例,只需右键项目>属性>配置属性>高级,把高级属性中的字符集改为使用多字节字符集
-编译出现 类似 const char类型的实参void NoiseSuppressionX32(char,cha,int,int)无法将参数1从const char[22]转换为char
在项目属性->C/C+±>语言中的符合模式项选择否即可,就是这样的编译环境问题
源代码及注释如下:
头文件:
#include<graphics.h>#include<mmsystem.h>#include<conio.h>#include<time.h>#include<stdlib.h>#include<stdio.h>#include<math.h>#pragma comment(lib,"winmm.lib")#define MAXSTAR 1000//星星个数//窗口宽高const int WIDTH = 750;const int HEIGHT = 600;struct STAR{double x;int y;double step;int color;};STAR star[MAXSTAR];//正确率和错误率int right = 0;int error = 0;//下坠字符串的结构体struct TARGET{int x;int y; //坐标char* str; //保存字符串};//保存用户输入的字符串的结构体struct USERKEY{int x;int y; //坐标char str[20]; //保存字符串}userkey = { 320,HEIGHT - 30,"" };//下坠字母的结构体typedef struct node{int x;int y;int s;}letter;void outtextxy_int(int x, int y, char* format, int num);void outtextxy_double(int x, int y, char* format, double num);void divWindow();void drawScore();void MYmusic();//音乐void welcome();// 欢迎界面void bkpicture();//背景图 void bkpicture2();void bkpicture3();void goodbye();// 退出界面void ifget();// 实现闪烁的“按任意键继续” 可以 用作暂停void divWindow2();//game2 窗口void InitGame2Target(letter FangAn[], int n);//game2 初始化字符void illustrate();void mygame1();void mygame2();void mygame3();
main.cpp
#include"head.h"void InitStar(int i)// 移动星星{star[i].x = 0;star[i].y = rand() % 810;star[i].step = (rand() % 5000) / 1000.0 + 1;star[i].color = (int)(star[i].step * 255 / 6.0 + 0.5);// 速度越快,颜色越亮star[i].color = RGB(star[i].color, star[i].color, star[i].color);}void MoveStar(int i){putpixel((int)star[i].x, star[i].y, 0);// 擦掉原来的星星star[i].x += star[i].step;// 计算新位置if (star[i].x > 810)InitStar(i);putpixel((int)star[i].x, star[i].y, star[i].color);// 画新星星}// 退出界面void goodbye(){/*closegraph();initgraph(WIDTH + 50, HEIGHT);*/cleardevice();setbkcolor(BLACK);cleardevice();int c = 0;int d = 8;//用来变色for (int i = 0; i < MAXSTAR; i++)// 初始化所有星星{InitStar(i);star[i].x = rand() % 640;}while (!_kbhit())//没有按下0,按下非0 //实现闪烁{for (int i = 0; i < MAXSTAR; i++)// 绘制星空,按任意键退出MoveStar(i);settextcolor(YELLOW);settextstyle(48, 0, _T("黑体"));outtextxy(104, 180, _T(" 方总要多练打字"));settextcolor(RGB(100, c, c));outtextxy(280, 400, _T("再见"));c += d;if (c < 8 || c>245)d = -d; //实现闪烁Sleep(60);//延时20ms}_getch();}// 欢迎界面void welcome(){// 输出屏幕提示cleardevice();bkpicture();setbkcolor(WHITE);setbkmode(TRANSPARENT);settextcolor(YELLOW);settextstyle(64, 0, _T("黑体"));outtextxy(280, 50, _T("方总练字"));settextcolor(RED);settextstyle(50, 0, _T("黑体"));outtextxy(300, 200, _T("一级难度"));outtextxy(300, 300, _T("二级难度"));outtextxy(300, 400, _T("三级难度"));settextcolor(LIGHTGRAY);outtextxy(700, 550, "退出");MOUSEMSG m;while (1){setlinestyle(0, 3, 0, 0);m = GetMouseMsg();if (m.x > 300 && m.x < 500 && m.y>200 && m.y < 250){setlinecolor(WHITE);rectangle(298, 198, 502, 252);if (m.uMsg == WM_LBUTTONDOWN){mygame1();}}else if (m.x > 300 && m.x < 500 && m.y>300 && m.y < 350){setlinecolor(WHITE);rectangle(298, 298, 502, 352);if (m.uMsg == WM_LBUTTONDOWN){mygame2();}}else if (m.x > 300 && m.x < 500 && m.y>400 && m.y < 450){setlinecolor(WHITE);rectangle(298, 398, 502, 452);if (m.uMsg == WM_LBUTTONDOWN){mygame3();}}else if (m.x > 700 && m.x < 800 && m.y>550 && m.y < 600){setlinecolor(WHITE);rectangle(700,548 , 800, 600);if (m.uMsg == WM_LBUTTONDOWN){goodbye();}}else{setlinecolor(BLACK);rectangle(298, 198, 502, 252);rectangle(298, 298, 502, 352);rectangle(298, 398, 502, 452);rectangle(700, 548, 800, 600);}}}//操作说明void illustrate(){cleardevice();bkpicture();settextcolor(YELLOW);settextstyle(30, 0, _T("黑体"));outtextxy(300, 50, _T("输入对应字母消除"));outtextxy(300, 100, _T("输入正确加速"));outtextxy(300, 150, _T("输入错误减速"));outtextxy(300, 150, _T("输入错误减速"));outtextxy(300, 200, _T("按空格暂停,任意键继续"));outtextxy(300, 250, _T("游戏界面输入数字0重选难度"));ifget();}// 实现闪烁的“按任意键继续”void ifget(){int c = 255;settextstyle(30, 0, _T("黑体"));while (!_kbhit()){settextcolor(RGB(c, 0, 0));outtextxy(330, 500, _T("按任意键继续"));c -= 8;if (c < 50) c = 255;Sleep(3);}_getch();}//音乐void MYmusic(){mciSendString("open D.mp3 alias music", 0, 0, 0);mciSendString("play music repeat", 0, 0, 0);}//背景图 void bkpicture(){IMAGE imagebk;setbkmode(TRANSPARENT);loadimage(&imagebk, "方总练字.jpg", 800, 600);putimage(0, 0, &imagebk);}//背景图 void bkpicture2(){IMAGE imagebk;setbkmode(TRANSPARENT);loadimage(&imagebk, "bk2.jpg", 800, 600);putimage(0, 0, &imagebk);}void bkpicture3(){IMAGE imagebk;setbkmode(TRANSPARENT);loadimage(&imagebk, "bk3.jpg", 800, 600);putimage(0, 0, &imagebk);}//上面是game1******************/******************* *///game2初始化字母void InitGame2Target(letter FangAn[], int n){srand((unsigned)time(NULL));FangAn[n].s = 65 + rand() % 26;while (FangAn[n].s == FangAn[(n + 1) % 3].s || FangAn[n].s == FangAn[(n + 2) % 3].s){FangAn[n].s = 65 + rand() % 26;}//X随机位置FangAn[n].x = rand() % (WIDTH - 200);while (FangAn[n].x == FangAn[(n + 1) % 3].x || FangAn[n].x == FangAn[(n + 2) % 3].x){FangAn[n].x = rand() % (WIDTH - 200);}//y 的位置FangAn[n].y = -60;}//game2 的分数框void divWindow2(){line(WIDTH - 100, 0, WIDTH - 100, HEIGHT);settextcolor(LIGHTBLUE);settextstyle(25, 0, "字魂24号-镇魂手书");outtextxy(WIDTH - 90, 25, "方总练字");outtextxy(WIDTH - 90, 50, "二级难度");settextcolor(RED);outtextxy(WIDTH - 90, 80, "没有暂停");settextcolor(LIGHTBLUE);outtextxy(WIDTH - 90, 120, "数字1减速");outtextxy(WIDTH - 90, 145, "数字2加速");outtextxy(WIDTH - 90, 170, "数字3复原");outtextxy(WIDTH - 90, HEIGHT - 100, "按0重选难度");}/************************************************************* game3 *///在指定位置输出整数void outtextxy_int(int x, int y, char* format, int num){char str[20] = "";sprintf_s(str, format, num);outtextxy(x, y, str);}//在指定位置输出浮点数void outtextxy_double(int x, int y, char* format, double num){char str[20] = "";sprintf_s(str, format, num);outtextxy(x, y, str);}//画窗口void divWindow(){line(WIDTH - 100, 0, WIDTH - 100, HEIGHT - 40);line(0, HEIGHT - 40, WIDTH + 50, HEIGHT - 40);line(WIDTH - 100, 130, WIDTH + 50, 130);settextcolor(LIGHTBLUE);settextstyle(25, 0, "字魂24号-镇魂手书");outtextxy(WIDTH - 90, 25, "方总练字");outtextxy(WIDTH - 90, 50, "三级难度");outtextxy(WIDTH - 90, 75, "空格暂停");outtextxy(WIDTH - 90, HEIGHT - 175, "数字1减速");outtextxy(WIDTH - 90, HEIGHT - 150, "数字2加速");outtextxy(WIDTH - 90, HEIGHT - 125, "数字3复原");outtextxy(WIDTH - 90, HEIGHT - 100, "按0重选难度");}//分数void drawScore(){outtextxy(WIDTH - 90, 225, "正确数");outtextxy_int(WIDTH - 90, 250, "%d", right);settextcolor(RED);outtextxy(WIDTH - 90, 285, "错误数");outtextxy_int(WIDTH - 90, 315, "%d", error);settextcolor(LIGHTBLUE);outtextxy(WIDTH - 90, 285 + 60, "正确率");if (right + error == 0)outtextxy_double(WIDTH - 90, 285 + 85, "%.2lf%%", 0);else{double sum = right + error;outtextxy_double(WIDTH - 90, 285 + 85, "%.2lf%%", right / sum * 100);}}//随机产生字符串void initTarget(struct TARGET words[], int n){srand((unsigned)time(NULL));static char str[18][10] = { "main","include","void","while","for","if","true","int","sizeof","continue","static","struct","else","void","case","switch","float","short" }; //0-18//随机产生字符串words[n].str = str[rand() % 18];while (words[n].str == words[(n + 1) % 3].str || words[n].str == words[(n + 2) % 3].str){words[n].str = str[rand() % 18];}//X随机位置words[n].x = rand() % (WIDTH - 200);if (abs(words[n].x - words[(n + 1) % 3].x < 50) || abs(words[n].x - words[(n + 2) % 3].x < 50)){words[n].x = rand() % (WIDTH - 200);}//y 的位置words[n].y = -20;}//游戏界面 难度1void mygame1(){illustrate();cleardevice();bkpicture();IMAGE imagebk;loadimage(&imagebk, "方总练字.jpg", 800, 600);IMAGE LB1, LB2;loadimage(&LB1, "hlb.jpg");loadimage(&LB2, "blb.jpg");srand((unsigned int)time(NULL));int x, y;int score = 0;//分数char s[1000];_itoa_s(score, s, 10);int speed = 5;//速度char fang;//掉落字符int key; //键盘输入while (1){fang = 65 + rand() % 26; //随机产生字符x = 10 + rand() % 770; //从10-780for (y = 0; y < 600; y++) //从上到下掉落{BeginBatchDraw();//预加载 防止闪耀 putimage(0, 0, &imagebk);//背景 putimage(x, y, &LB2, SRCPAINT);//这两个不能放反putimage(x, y, &LB1, SRCAND);//三元光栅setbkmode(TRANSPARENT);settextstyle(20, 0, "黑体");//字跟图一起掉下来settextcolor(BLACK);outtextxy(x + 15, y + 40, fang);settextcolor(YELLOW);outtextxy(700, 580, "score:");outtextxy(770, 580, s);if (_kbhit()){key = _getch();if (key == fang || key == fang + 32){score++; //分数加_itoa_s(score, s, 10); //转换分数speed--; //速度加if (speed < 1)speed = 1;break;}else if (key == ' '){_getch();}else if (key == 27){EndBatchDraw();/// goodbye();exit(0);}else if (key == '0'){EndBatchDraw();/// welcome();}else{if (speed > 20)speed = 20;speed += 3;}}Sleep(speed);//休眠0.0X毫秒再落下字母EndBatchDraw();}}}//游戏界面 难度2void mygame2(){IMAGE imagebk;loadimage(&imagebk, "bk3.jpg", 800, 600);IMAGE LB1, LB2;loadimage(&LB1, "hlb.jpg");loadimage(&LB2, "blb.jpg");letter FangAn[3]; //三个字符//初始化字符for (int n = 0; n < 3; n++){InitGame2Target(FangAn, n);FangAn[n].y = -15 - n * 30; //不等高落下}int speed = 10;//sudu while (1){BeginBatchDraw();//预加载 防止闪耀 cleardevice();bkpicture3(); //重新画背景divWindow2(); //重新画窗口drawScore();for (int n = 0; n < 3; n++){putimage(FangAn[n].x, FangAn[n].y, &LB2, SRCPAINT);//这两个不能放反putimage(FangAn[n].x, FangAn[n].y, &LB1, SRCAND);//三元光栅setbkmode(TRANSPARENT);settextcolor(BLACK);outtextxy(FangAn[n].x + 15, FangAn[n].y + 40, FangAn[n].s);FangAn[n].y += 4;//底部擦除if (FangAn[n].y > (HEIGHT)){InitGame2Target(FangAn, n);}if (_kbhit()){char target = _getch(); //接受键盘输入int flagERROR = 0;for (int i = 0; i < 3; i++){if (target == FangAn[i].s || target == FangAn[i].s + 32){InitGame2Target(FangAn, i);right++;flagERROR = 1;}else if (target == '1'){speed += 2;flagERROR = 1;if (speed > 100)speed = 100;}else if (target == '2'){speed -= 2;flagERROR = 1;if (speed < 0)speed = 0;}else if (target == '3'){speed = 10;flagERROR = 1;}else if (target == 27){EndBatchDraw();/// goodbye();exit(0);}else if (target == '0'){EndBatchDraw();/// welcome();}}if (flagERROR == 0){error++;}}}EndBatchDraw();Sleep(speed);}}//难度3个字符 随机掉落void mygame3(){struct TARGET words[3];IMAGE imagebk;loadimage(&imagebk, "bk2.jpg", 800, 600);IMAGE LB1, LB2;loadimage(&LB1, "hlb.jpg");loadimage(&LB2, "blb.jpg");//产生字符串for (int n = 0; n < 3; n++){initTarget(words, n);words[n].y = -15 - n * 30; //不等高落下}int i = 0;//计数int speed=10;while (1){BeginBatchDraw();//预加载 防止闪耀 cleardevice();bkpicture2(); //重新画背景divWindow(); //重新画窗口drawScore();//打印文字for (int n = 0; n < 3; n++){putimage(words[n].x, words[n].y, &LB2, SRCPAINT);//这两个不能放反putimage(words[n].x, words[n].y, &LB1, SRCAND);//三元光栅setbkmode(TRANSPARENT);settextcolor(YELLOW);outtextxy(words[n].x, words[n].y + 40, words[n].str);words[n].y += 2;//底部擦除if (words[n].y > (HEIGHT - 40 - textheight(words[n].str))){initTarget(words, n);error++;}}if (_kbhit()){char target; //接受键盘输入target = _getch();//回退if (target == 8) //如果回退了{if (i > 0) //往前走一步i--;userkey.str[i] = '\0'; //当前字母为\0/}//退出else if (target == 27){EndBatchDraw();/// goodbye();exit(0);}//暂停 加速 减速 复原else if (target == ' '){_getch();}else if (target == '1'){speed += 2;if (speed > 100)speed = 100;}else if (target == '2'){speed -= 2;if (speed < 0)speed = 0;}else if (target == '3'){speed = 10;}else if (target == '0'){EndBatchDraw();/// welcome();}else if (target != '\r'){userkey.str[i++] = target;}else{int flagERROR = 0;for (i = 0; i < 3; i++){if (strcmp(userkey.str, words[i].str) == 0){initTarget(words, i);right++;flagERROR = 1;}}if (flagERROR == 0){error++;}userkey.x = 320;i = 0;memset(userkey.str, 0, 20);}}outtextxy(userkey.x, userkey.y, userkey.str);EndBatchDraw();Sleep(10);}}void main(){initgraph(WIDTH + 50, HEIGHT);HWND hwnd = GetHWnd(); // 获取绘图窗口句柄(HWND)SetWindowText(hwnd, "方总练字"); //使用 Windows API 修改窗口名称MYmusic();welcome();// 开始界面closegraph();}