学了四个月,自己刚写出第一个小游戏贪吃蛇
c语言吧
全部回复
仅看楼主
level 12
知表不言 楼主
代码太长了,一层楼居然放不下,那就分两层放吧[太开心]
对了,感谢K-Z 12-17-2009 at 12:53 PM.在LinuxQuestions分享的kbhit()函数方法,自己想了好久没想通,虽然都没看懂,但先用着再说[笑眼]
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#define random(x) (rand()%(x))
#define MAXSIZEX 20 //地图多少"行"
#define MAXSIZEY 50 //地图每"行"多"长"
#define VOID 0 //空白
#define FOOD -1 //食物
#define WALL -2 //边界
#define HEAD 1 //蛇头
int count = 1; //记录蛇身长度
void MapInit(short *map);
void MoveEat(short *map, short *px, short *py, char dir, short *pX, short *pY);
void GetRan(short *X, short *Y);
void PrintMap(short *map);
int kbhit(void);
int main()
{
short map[MAXSIZEX][MAXSIZEY] = {};
short X, Y, x, y; //食物和自身坐标
short speed = 1;
char dir = 'd'; //w s a d分别为上下左右
char ch = ' ';
srand((int)time(0));
MapInit(&map[0][0]);
x = MAXSIZEX / 2; //初始化蛇头坐标
y = MAXSIZEY / 2;
map[x][y] = HEAD;
GetRan(&X, &Y);
map[X][Y] = FOOD;
printf("游戏速度(每秒前进多少步):");
while(!scanf("%hd", &speed))
{
getchar();
}
getchar();
while(dir != 'q' && dir != 'Q')
{
do
{
MoveEat(&map[0][0], &x, &y, dir, &X, &Y);
PrintMap(&map[0][0]);
printf("\n\n");
printf("当前得分:%d\n", count);
printf("游戏说明:w s a d q分别为上下左右及退出键,按完后请加回车(按键在按下回车时对第一个有效字母作出响应)\n\n");
usleep(1000000 / speed);
} while(!kbhit());
do
{
ch = getchar();
}while(ch != 'w' && ch != 'W' && ch != 's' && ch != 'S' && ch != 'a' && ch != 'A' && ch != 'd' && ch != 'D' && ch != 'q' && ch != 'Q'); //ch的有效性判断
if((count > 1) && ((((dir == 'w' || dir == 'W') && (ch == 's' || ch == 'S'))) || (((dir == 's' || dir == 'S') && (ch == 'w' || ch == 'W'))) || (((dir == 'a' || dir == 'A') && (ch == 'd' || ch == 'D'))) || (((dir == 'd' || dir == 'D') && (ch == 'a' || ch == 'A'))))) //当蛇身长度>1时不能调头
{
ch = dir;
}
dir = ch;
while((ch = getchar()) != '\n')
{
;
}
}
if(dir == 'q' || dir == 'Q')
{
printf("\t感谢您的本次使用,祝您生活愉快^_^\n\n");
}
return 0;
}
void MapInit(short *map)
{
for(int X = 0; X < MAXSIZEX; X++) //初始化地图
{
for(int Y = 0; Y < MAXSIZEY; Y++)
{
if(!X || !Y || X == MAXSIZEX - 1 || Y == MAXSIZEY - 1)
{
*(map+X*MAXSIZEY+Y) = WALL;
}
else
{
*(map+X*MAXSIZEY+Y) = VOID;
}
}
}
}
void GetRan(short *X, short *Y)
{
do
{
*X = random(MAXSIZEX - 1);
} while(!*X);
do
{
*Y = random(MAXSIZEY - 1);
} while(!*Y);
}
void PrintMap(short *map)
{
for(int i = 0; i < MAXSIZEX; i++)
{
printf("\t");
for(int j = 0; j < MAXSIZEY; j++)
{
if(*(map+i*MAXSIZEY+j) == WALL)
{
printf("口");
}
else if(*(map+i*MAXSIZEY+j) == FOOD)
{
printf("田");
}
else if(*(map+i*MAXSIZEY+j) == VOID)
{
printf(" ");
}
else if(*(map+i*MAXSIZEY+j) == HEAD)
{
printf("回");
}
else
{
switch(*(map+i*MAXSIZEY+j)%10)
{
case 1:
printf("一");
break;
case 2:
printf("二");
break;
case 3:
printf("三");
break;
case 4:
printf("四");
break;
case 5:
printf("五");
break;
case 6:
printf("六");
break;
case 7:
printf("七");
break;
case 8:
printf("八");
break;
case 9:
printf("九");
break;
case 0:
printf("十");
break;
}
}
}
printf("\n");
}
return;
}
2017年08月15日 15点08分 1
level 12
知表不言 楼主
void MoveEat(short *map, short *px, short *py, char dir, short *pX, short *pY)
{
switch(dir)
{
case 'w':
case 'W':
*px -= 1;
break;
case 's':
case 'S':
*px += 1;
break;
case 'a':
case 'A':
*py -= 1;;
break;
case 'd':
case 'D':
*py += 1;
break;
default:
break;
}
if(*px == 0)
{
*px += MAXSIZEX - 2;
}
if(*py == 0)
{
*py += MAXSIZEY - 2;
}
if(*px == MAXSIZEX - 1)
{
*px -= MAXSIZEX - 2;
}
if(*py == MAXSIZEY - 1)
{
*py -= MAXSIZEY - 2;
}
if(((*(map+*px*MAXSIZEY+*py)) != FOOD) && ((*(map+*px*MAXSIZEY+*py)) != VOID) && ((*(map+*px*MAXSIZEY+*py)) != WALL))
{
printf("GAME OVER!!!\n\n");
exit(-1);
}
else
{
system("clear");
printf("\n\n");
}
{
for(int i = 0; i < MAXSIZEX; i++)
{
for(int j = 0; j < MAXSIZEY; j++)
{
if(((*(map+i*MAXSIZEY+j)) == WALL) || ((*(map+i*MAXSIZEY+j)) == VOID))
{
continue;
}
if(*px == *pX && *py == *pY)
{
if((*(map+i*MAXSIZEY+j)) == FOOD)
{
count++;
do
{
GetRan(pX, pY);
}while(*(map+(*pX)*MAXSIZEY+(*pY)) != VOID);
}
else
{
*(map+i*MAXSIZEY+j) += 1;
}
}
else
{
if((*(map+i*MAXSIZEY+j)) != FOOD)
{
*(map+i*MAXSIZEY+j) += 1;
if(*(map+i*MAXSIZEY+j) > count)
{
*(map+i*MAXSIZEY+j) = VOID;
}
}
}
/*
else if((*(map+i*MAXSIZEY+j)) == FOOD)
{
if(*px == *pX && *py == *pY)
{
count++;
*(map+i*MAXSIZEY+j) = HEAD;
do
{
GetRan(pX, pY);
}while(*(map+(*pX)*MAXSIZEY+(*pY)) != VOID);
}
}
else
{
if((*(map+i*MAXSIZEY+j)) == HEAD || count == 1)
{
*(map+i*MAXSIZEY+j) = VOID;
}
else
{
if(*px == *pX && *py == *pY)
{
*(map+i*MAXSIZEY+j) -= 1;
}
else
{
*(map+i*MAXSIZEY+j) += 1;
}
}
}
*/
}
}
}
*(map+(*pX)*MAXSIZEY+(*pY)) = FOOD;
*(map+(*px)*MAXSIZEY+(*py)) = HEAD;
return;
}
int kbhit(void)
{
struct timeval tv;
fd_set read_fd;
tv.tv_sec=0;
tv.tv_usec=0;
FD_ZERO(&read_fd);
FD_SET(0,&read_fd);
if(select(1, &read_fd, NULL, NULL, &tv) == -1)
return 0;
if(FD_ISSET(0,&read_fd))
return 1;
return 0;
}
2017年08月15日 15点08分 2
level 15
[真棒]
2017年08月15日 15点08分 3
level 12
知表不言 楼主
还有一些问题没有解决,比如说按键中输出地图可能会出现错位,怎样在终端中实现getch()函数,网上搜的都无效。
还有假如蛇已撞到自己尾巴(游戏结束),而输入缓冲区中还有一堆乱键没有读取,怎样在结束时清除缓冲区(中间可能混杂着回车),否则终端就会把它们当成命令而出现 ** not found(flush(stdin)无效,刚开始学输入时不知道,憋了好多次才发现的[汗])
2017年08月15日 15点08分 4
好像是GCC编译器不支持还是什么原因[黑线]
2017年08月15日 15点08分
linux清缓存用scanf,getch需要ncurses
2017年08月15日 15点08分
回复 aaaaaaa421 :哦是这样吗 while (scanf("%c", ch)) {;} 以前用这样的语句判断输入的是否为整型或浮点数的
2017年08月15日 15点08分
回复 aaaaaaa421 :ncurses的头文件在网上找到了,但是不会用,直接放在c文件所在文件夹里还是会报错,要不也不用单独找kbhit()函数了[不高兴]
2017年08月15日 15点08分
level 12
知表不言 楼主
以前一直用
while (ch = (getchar) != '\n')
{;}
可是遇到多个回车呢,判断为EOF那还得按Ctrl+D才能结束[狂汗]
2017年08月15日 15点08分 5
level 12
知表不言 楼主
还有最大的一个问题,怎样在终端中不按回车就把按键流入stdin,没找到getch(),不知道它有没有这样的效果[太开心]
2017年08月15日 15点08分 6
有,conio.h这是无缓冲区
2017年08月15日 22点08分
level 3
厉害,收下了
2017年08月15日 16点08分 7
level 7
从未接触过到写程序吗?
2017年08月17日 15点08分 8
五月刚买的书开始自学的,大学专业是临床医学[笑眼]
2017年08月17日 21点08分
@知表不言 厉害了,我的哥,我刚自学,3天
2017年08月18日 00点08分
level 11
这么久才编出贪吃蛇???
2017年08月18日 00点08分 9
还有工作,只是业余爱好,现在能写出这些就已经很满足了
2017年08月18日 01点08分
level 1
7K 7K小游戏小孩玩呗搜索开始不要钱不要可以下载
2017年10月05日 02点10分 10
1