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

如题所述

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

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

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

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

玩法:按键区分大小写,落到底部或被玩家按中,下落中的字母就会消失,并在该列顶部创建新的字母下落,按中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=0;i<W;i++)
            printf("-");
        printf("\n");
        runLetter(letrHead);
        letrTail=showList(letrHead,letrTail);
        for(i=0;i<W;i++)
            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=0;i<H;i++)
        for(j=0;j<W;j++)
            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=0;i<H;i++,printf("\n"))
        for(j=0;j<W;j++)
            printf("%c",sp[i][j]);
    return letrTail;
}

LETR *init(LETR *letrHead)//初始化一组字母,返回链表尾节点
{
    int i;
    LETR*letrTail=NULL;
    for(i=0;i<W;i++)
        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);
    }
}

温馨提示:答案为网友推荐,仅供参考
相似回答