c语言制作一个简单的打字游戏(落下一个字母按相应字母消去,记录分数)

c语言制作一个简单的打字游戏(落下一个字母按相应字母消去,记录分数),第1张

游戏常量参数自行修改(字母的列数,下落最大高度,下落速度等)。

程序功能:(随机生成字母,下落,并检查按键,计分)

多线程按键检查采用新的线程与主线程同步。

独立速度:每个字母下落速度都是随机且不相同。

玩法:按键区分大小写,落到底部或被玩家按中,下落中的字母就会消失,并在该梁粗列顶部创建新的字母下落,按中1次记1分。

注意:由于字母都是随机的,如果同时下落的字母很多,可能会有重复字母出现,如果按键对应了多个同样的字母,这些字母会删掉并新建,也就是说出现按中一次记多分,说明有多个重复字母,不是BUG!

#include <stdio.h>

#include <stdlib.h>

#include <malloc.h>

#include <conio.h>

#include <time.h>

#include <windows.h>

#define W 30//宽度

#define H 20//高度

#define MinSPEED 50//最慢下降速度(周期,数字越小越快)

#define MAXSPEED 5//最快下降速度

int score=0//总分

typedef struct letter

{

     int ascii// 字母ASCII码

     int hIndex//对应打印数组行下标

     int wIndex//对应打印数组列下标

     int cnt//周期计数,当cnt==speed,hIndex++并且cnt重新置0

     int speed//下降速度

     int key//0表示没有橡返镇被按中,1表示被按中

     struct letter *next

}LETR

void meError(void *p)//内存申请失败

LETR *newLETR(LETR *letrHead,LETR*letrTail,int wIndex)//产生一个新的字母,并添加到链表,返回尾节点

LETR* delLETR(LETR *letrHead,LETR*letrTail,int wIndex)//删除列下标的字母节点,返回新的尾节点

LETR *init(LETR *letrHead)//初始化一组字母,返回链表尾节点

LETR *showList(LETR *letrHead,LETR*letrTail)//显示列表并检查,发现到底或被按键按中的字母删除并新建新的字母,返回新的尾节点

void runLetter(LETR *letrHead)//所有字母一周期计数

DWORD WINAPI checkKey(LPVOID lpParameter)//新线程

int main()

{

   世旁 int i

    LETR *letrHead=NULL,*letrTail=NULL

    letrHead=(LETR *)malloc(sizeof(LETR))

    meError(letrHead)

    letrHead->next=NULL

    srand(time(NULL))

    letrTail=init(letrHead)

    CreateThread(NULL,0,checkKey,letrHead,0,NULL)

    letrTail=showList(letrHead,letrTail)

    while(1)

    {

        system("cls")

        printf("总分:%d\n",score)

        for(i=0i<Wi++)

            printf("-")

        printf("\n")

        runLetter(letrHead)

        letrTail=showList(letrHead,letrTail)

        for(i=0i<Wi++)

            printf("-")

        printf("\n")

    }

    return 0

}

DWORD WINAPI checkKey(LPVOID lpParameter)

{

char c

LETR *letrHead=NULL

while(1)

    {

        letrHead=(LETR *)lpParameter

        c=getch()

        while(letrHead->next)

        {

            if(c==letrHead->next->ascii)

                letrHead->next->key=1,score++//按键标识置1,考虑可能有多个相同随机字母,故用标识,在显示函数统一删除并新建

            letrHead=letrHead->next

        }

    }

return 0

}

void runLetter(LETR *letrHead)//所有字母一周期计数

{

    while(letrHead->next)

    {

        if(letrHead->cnt<letrHead->speed)

            letrHead->cnt++

        else

            (letrHead->next->hIndex)++,letrHead->cnt=0

        letrHead=letrHead->next

    }

}

LETR *showList(LETR *letrHead,LETR*letrTail)//显示列表并检查,发现到底或被按键按中的字母删除并新建新的字母,返回新的尾节点

{

    int i,j,wIndex

    char sp[H][W]

    LETR *head=letrHead

    for(i=0i<Hi++)

        for(j=0j<Wj++)

            sp[i][j]=' '

    while(letrHead->next)

    {

        if(letrHead->next->hIndex>H-1 || letrHead->next->key==1)//到底或者被按中就删除并新建,重新循环

        {

            wIndex=letrHead->next->wIndex

            letrTail=delLETR(head,letrTail,wIndex)

            letrTail=newLETR(head,letrTail,wIndex)

            letrHead=head

        }

        else

            sp[letrHead->next->hIndex][letrHead->next->wIndex]=letrHead->next->ascii

        letrHead=letrHead->next

    }

    for(i=0i<Hi++,printf("\n"))

        for(j=0j<Wj++)

            printf("%c",sp[i][j])

    return letrTail

}

LETR *init(LETR *letrHead)//初始化一组字母,返回链表尾节点

{

    int i

    LETR*letrTail=NULL

    for(i=0i<Wi++)

        letrTail=newLETR(letrHead,letrTail,i)

    return letrTail

}

LETR *newLETR(LETR *letrHead,LETR*letrTail,int wIndex)//在列下标wIndex首行,产生一个新的字母,并添加到链表,返回尾节点

{

    int n

    LETR *leterNEW=(LETR *)malloc(sizeof(LETR))

    meError(leterNEW)

    leterNEW->next=NULL

    n=rand()%2

    if(n)//随机大小写

        leterNEW->ascii=rand()%26+65//随机一个大写字母

    else

        leterNEW->ascii=rand()%26+97//随机一个小写字母

    leterNEW->hIndex=0

    leterNEW->wIndex=wIndex

    leterNEW->cnt=0

    leterNEW->speed=rand()%(MinSPEED-MAXSPEED)+1+MAXSPEED

    leterNEW->key=0

    if(letrHead->next==NULL)

        letrHead->next=leterNEW

    else

        letrTail->next=leterNEW

    letrTail=leterNEW

    return letrTail

}

LETR* delLETR(LETR *letrHead,LETR*letrTail,int wIndex)//删除列下标的字母节点,返回新的尾节点

{

    LETR *lhead=letrHead,*letrDel=NULL

    while(letrHead->next)

    {

        if(letrHead->next->wIndex==wIndex)

        {

            letrDel=letrHead->next

            letrHead->next=letrHead->next->next

            free(letrDel)

            break

        }

        letrHead=letrHead->next

    }

    letrHead=lhead

    while(letrHead->next)//重置尾节点

        letrHead=letrHead->next

    return letrHead

}

void meError(void *p)//内存申请失败

{

    if(p==NULL)

    {

        printf("\n异常:内存申请失败!回车结束程序!\n")

        while(getch()!='\r')

        exit(0)

    }

}

# include<stdio.h>

# include <conio.h>

# include <graphics.h>

# include <time.h>

# pragma comment(lib,”Winmm.lib”) //引用Windows Multimedia APT

int score =0 //全局变量********整型的分数

char s[5] //全局变量****字符型的分数

struct player_ //自定义的结构体,并顺便定义一个结构体变量

{

char name[20]

int score_

}player[11]

/***************函数声明*****************/

void record_() //记录彼此成绩函数

void welcome( ) //欢迎界面函数

void instructions( ) //游戏说明界面函数

void gane (int rank2) //游戏函数

void record ( ) //显示记录函数

int rank_(char rank1) //等级选择函数

void goodbye ( ); //退出界面函数

/**************主函数**************/

int main ()

{

char rank1 //rank1接受从键盘输入的字符,根据字符判断等级毁碰

int rank2=15 // 控制延时时间,从而控制速度

intsign=1 // 当做标记,用于标记键余稿是否d出MessageBox对话框

welcome ( ) //调用欢迎界面函数

instructions ( )//调用游戏什么函数

record( )//调用显示记录函数

InputBox(player[10].name,20,"请输入玩家昵称" //以对话框形式获取用户输入函数

rank1=getch()//读入一个字母

rank2=rank_(rank1)//调用等级函数

game (rank2)//调用游戏函数

HWND wnd =GetHWnd()

while (sign) //sign作为标记,执行循环

if (MessageBox(wnd,"游戏结束!!!\n再来一局,挑战更高分数","询问",MB_YESNO|MB_ICONQUESTION)==IDYES)

game (rank2)

else

{

sign=0

goodbye( )

}

closegraph( )

return 0

}

/***************记录本次成绩函数***************/

void record_()

{

FILE*fp //文件指针

int i,j

struct player_t //定义结构体变量t,冒泡法比较大小时用

player[10].score_=score //把该局的分数赋给该局用户的结构体变量中

fp=fopen("记录.dat","rb") //打开二进制文件

for (i=0i<10i++)

{

fread(player[i].name,20,l,fp) //读入记录中的成绩和名字

fread (&player[i].score_,4,l,fp)

}

fclose(fp) //关闭二进制文件

for (j=0j<10j++) /稿孝/冒泡法排序

for (i=0i<10-ji++)

if (player[i].score_)

{

t=player[i]

player[i]=player[i+1]

player[i+1]=t

}

fp=fopen("记录.dat","wb") //打开文件

for (i=0i<10i++) //把排好序列的数据存入记录文件

{

fwrite(player[i].name,20,l,fp)

fwrite (&player[i].score_,4,l,fp)

}

fclose(fp) //关闭文件

}

/****************欢迎界面函数****************/

void welcome ( )

{

char ch

mciSendString("open\"res\\Sleep Away.mp3\"alias mymusic",NULL,0,NULL)

initgraph(640,480) //初始化画图界面

IMAGE img //定义IMAGE对象

loadimage (&img,"res\\00.jpg") //读取图片到img对象中

putimage (0,0,&img) //在坐标(0,0)位置显示IMAGE对象

ch=getch() //吸收掉一个按键

cleardevice() //清屏

}

/***************游戏说明界面函数**************/

void instructions()

{

int c=255 //控制变色的变量

setcolor(YELLOW) //设置颜色

setfont (30,0,"黑体") //设置字体

outtextxy(0,0,"游戏说明") //输出文字

setcolor(WHITE)

setfont(28,0,"宋体")

outtextxy(0,30,"一、每次游戏下落200个字母") //输出文字

outtextxy(0,58,"二、请按数字键选择游戏等级")

outtextxy(0,86,"三、统计被击中的个数")

setfont(30,0,"华文行楷")

outtextxy (20,220,"等级一二三四 五六七八九")

outtextxy(20,260,“按键 1 2 3 4 5 6 7 8 9”);

while (!kbhit()) //kihit()作用是判断是否有字幕输入

{

setcolor(RGB(c,255,0))

setfont (80,0,"楷体")

outtextxy(140,130,"请选择等级")

setcolor(RGB(c,0,255))

setfont(100,0,"Wickenden Cafe NDP")

outtextxy(100,135,"Let's go!!!")

c-=25 //控制颜色的变量自减

if(c<0)c=255 //控制颜色的变量小于0时,再把255赋给c

cleardevice() //清屏

}

/***************退出界面函数***************/

void goodbye()

{

int c=255 //控制变色变量

cleardevice() //清屏

setcolor(YELLOW)

setfont (48,0,"黑体")

outtextxy (104,120,"的最终成绩是: ")

setfont (48,0,"华文楷体")

setcolor(RGB(255,255,0))

outtextxy(140,320,"按任意键退出游戏")

setcolor(YELLOW)

setfont(48,0,"黑体")

outtextxy (104,120,"的最终成绩是: ")

outtextxy(104,70,player[10].name)

record_() //调用记录本次成绩函数

while(!kbhit())

{

setcolor(RGB(255,0,c-100)) //设置颜色

setfont(100,0,”Wickenden Café NDP”)

outtextxy(400,90,s) //输出数字

setcolor(RGB(c,0,255))

setfont(48,0,”黑体”)

if (score==200)

outtextxy(100,200,”全部击中!!!”)

else

if(score>190)

outtextxy(100,200,”不错!继续加油!”);

else

outtextxy(100,200,”不要灰心!继续加油!”);

c-=25

if(c<0)

c=255

Sleeep(20) //延时20秒

}

getch( ) //提供给用户时需要等待输入后再退出

}

/**************等级选择函数**************/

int rank_(char rank1)

{

int rank2

switch(rank1) //判断字符,确定等级

{

case’0’:rank2=11break

case’1’:rank2=10break

case’2’:rank2=9break

case’3’:rank2=8break

case’4’:rank2=7break

case’5’:rank2=6break

case’6’:rank2=5break

case’7’:rank2=4break

case’8’:rank2=3break

case’9’:rank2=2break

default:rank2=15break

}

return rank2

}

/**************显示记录函数***********/

void record( )

{

FILE *p //文件指针

int a[10],j

char b[10][10]

fp=fopen(“记录。dat”,”rb”) //打开文件

for (j=0j<10j++)

{

fread(player[j].name,20,1,fp) //读取文件中的信息

fread(&player[j].score_,4,1,fp)

}

fclose(fp) //关闭文件

setfont(60,0,”Arial”)

setcolor(RGB(250,250,0))

outtextxy(250,0,”TOP10”)

for(j=0j<10j++)

{

sprintf(“b[j],%d”,player[j].score_) //把整型转换为字符型

setcolor(RGB(0,100,255))

setfont(40,0,”Arial”)

outtextxy(420,50+40*j,b[j])

outtextxy(120,50+40*j,player[j].name) //输出名字

/**********游戏函数******************/

void game (int rank2)

{

cleardevice( ) //清屏

score=0 //清除掉原有的分数

outtextxy(0,0,”玩家:”);

outtextxy(90,0,player[10].name)

setfont(20,0,”Arial”)

outtextxy(100,460,” 人生有享受片刻优雅恬适的权力,让打字母游戏放松你一下吧!”);

int i;

char target //目标字母

char key //用户的按键

intx,y //字母的位置

int flag =1 //标记是否按了退出键

int sum=0 //成绩计数

int num =200 //规定下落字母的个数

srand (time(NULL)) //随机时间种子,设置第一个随机函数的值

setfillstyle(BLACK) //设置下面矩形内图的颜色

setcolor(YELLOW) //

line(0,450,640,450) //用3条线规定一下工作区

line(0,440,640,440) //用3条线规定一下工作区

line(0,40,640,40) //用3条线规定一下工作区

while (flag&&num)

{

setfont(40,0,”宋体”); //设置字母的字体和大小

i=rand()%2 //rand()函数返回0~32767之间的一个整数

if(i)

target=97+rand()%26 //产生任意小写字母

else

target=65+rand()%26 //产生任意大写字母

x=rand()%610 //产生任意下落位置

for (y=41y<380y++)

{

setcolor (RGB(255,0,255))

outtextxy(x,y,target) //显示字母

if(kbhit())

{

key=getch() //获取用户按键

if ((key==target)||( key==target-32)||( key==target+32))

{

score++ //分数统计

sprintf(s,”%d”score)

setfont(30,0,”Arial”)

outtextxy(500,0,“分数”)

outtextxy(600,0,s) //输出分数

bar(x-10,y-10,x+35,y+50) // 击中用黑框形擦去字母

break //跳出循环,进行下一个字母

}

else if (key==27) //判断是否按了

{

flag=0 //若果按ESC,退出游戏主循环

break

}

}

Sleep(rank2) //控制清除字母的时间爱你也就是控制下落速度

bar(x,y,x+35,y+60) //擦最下面的字符

}

num-- //计数

}

}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/8282375.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-15
下一篇 2023-04-15

发表评论

登录后才能评论

评论列表(0条)

保存