游戏常量参数自行修改(字母的列数,下落最大高度,下落速度等)。
程序功能:(随机生成字母,下落,并检查按键,计分)
多线程:按键检查采用新的线程与主线程同步。
独立速度:每个字母下落速度都是随机且不相同。
玩法:按键区分大小写,落到底部或被玩家按中,下落中的字母就会消失,并在该梁粗列顶部创建新的字母下落,按中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)
}
}
随机产生3行40列小写字母,然后请用户输入,如果和随机产生的字母一致则输出O错误输出X
知识点:数组,取余,判断,循环,几链慎铅个库函数,注释详细,适合像我这样的初学者。
#include //经典标准输入输出头文件,不然printf()用不了。
#include //为了使用rand()随机数函数,这个函数取决于srand()函数给它设置的环境。time()当前时间作为参数给srand()
#include //为了使用time()这个函数,能得到当前日历时间
#include //为了用getch()函数来接收一个不回显的按键,本来是getch()的,结果C++说这个函数不安全让我改成_getch()
int main(void)
{
unsigned char listchar[3][40] = { NULL }//无符号字符数组 初始化为null空,一个空所有空
unsigned char getW = NULL//初始化getW无符号变量getW 为null空
srand(time(0))//初始化随机数发生器,time(0)以当前时间作为随机数种子,给srand作为参数,方便使用rand()的时候产生合理的随机数
int i, j = 0
for (i = 0i <3i++) //3行
{
for (j = 0j <40j++) //40列
{
do
{
getW = rand() % 1000//随机产生一个1-3位数的整数给getW
if (getW >= 97 &&getW <= 122) //判断随机数是否在97到122,孝世也是小写字母a~z如果是 就结束do while。
{
break//用于终止do while
}
} while (1)
listchar[i][j] = getW//把随机得到的小写字母赋值给listchar二维数组。
printf("%2c",listchar[i][j])//输出本行的每个列位置的字符%2c的2是占位对齐位置,相当于空格
}
printf(" ")//换两行
}
//unsigned char keyW = ''没用
//keyW = _getch()这个函数好,得到一个字符不回显
i = 0//listchar二维数组的行初始化赋值为0
for(i <3i++)//因为i已经在上面赋值初始化了,所以棚好for里面的第一个表达式可以留空
{
j = 0//listchar二维数组的列初始化为0
do
{
if (_getch() == listchar[i][j])//判断按键的字母是否和二维数组里面的字母一致
{ printf(" O")}//一样的话就输出 O
else
{ printf(" X")}//不一致输出 X
j++//二维数组的列自增1
} while (j <40)//判断二维数组的列是否为最后一个
printf(" ")//二维数组的列结束后,输出一个换行符
}
return 0
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)