C语言控制台简单实现贪吃蛇(附完整源码)

        “笔者刚学完c语言基础语法,本着练习的心态用控制台实现了贪吃蛇游戏,于是有了本篇。”

效果预览:

目录

一、预备知识

1、kbhit()

2、getch()

3、system()

4、rand()

二、基本思路

三、代码实现

1、变量声明

2、主程序

3、按键检测

4、食物判定

5、尾部判定加清楚

6、蛇体默认移动、死亡判定

7、源码


公众号摸鱼老K同步更新,感谢关注~


一、预备知识

        基本的语法就不多赘述了,本篇主要介绍基础学习不常涉及到的函数

1、kbhit()

        用于非阻塞地响应键盘输入事件,在本项目中用于检测按键控制蛇体移动。

        功能及返回值: 检查当前是否有键盘输入,若有则返回一个非0值,否则返回0

2、getch()

        从stdio流中读字符,即从控制台读取一个字符,但不显示在屏幕上,getch()会暂停输出控制台,直到按下一个键为止,它不使用任何缓冲区来存储输入字符,输入的字符将立即返回,而无需等待回车键。

        返回值:读取的字符的ASCII码值(整数)。

3、system()

int system(const char * command)

        在windows系统中,system函数直接在控制台调用一个command命令。这些命令可以通过system(“HELP”)获取,我们在这只使用system("cls")来清除屏幕输出。

        返回值:命令执行成功返回0,执行失败返回-1。

4、rand()

        rand()函数用于产生一个随机数,其内部实现是用线性同余法实现的,是伪随机数,由于周期较长,因此在一定范围内可以看成是随机的。调用rand()函数会得到一个在0-RAND_MAX。RAND_MAX在头文件stdlib.h中定义。

        我们还可以通过rand()%(n-m+1)+m这个公式实现指定范围(m,n)内的随机数。

二、基本思路

        实现思路就是通过清空控制台再打印输出,如此循环,实现动画效果。

        定义出蛇头,蛇身,蛇尾,程序难点就在蛇体运动和蛇尾判定。首先明确大体过程,蛇头不断朝着正向前进,并且可以通过按键改变方向。蛇的整体运动其实就是蛇头前移,之后在蛇头后面打印出一个蛇身,最后是清楚蛇的末尾,这样就能实现蛇的动态。

        再一个难点是蛇身拐点,也就是多一个拐点蛇身就多处一个运动的矢量,本例程是将拐点xy坐标以及方向存储在三个数组中,通过这三个值判断尾端的移动。这样的好处是编程逻辑清楚简单,相应缺点就是数组大小有限,并且不能释放无用的内存。当你熟练了指针用法之后也可以通过链表存储来改进。这里笔者还不熟练,今后学到可能会回头来优化(刚开始就挖坑~)

        食物就通过随机数生成,死亡判定就直接判断头坐标下一个内容(是墙或者蛇身判定死亡)。

三、代码实现

1、变量声明

//蛇头和蛇身
char head = '#', body = '*';

//蛇头的坐标值,长度,拐点个数
int x = 20, y = 10, length = 10, change = 0;

//记录拐点信息,方向用1233代表wasd
int xchange[999], ychange[999], decation[999] = {0};

//食物坐标
int xfood = 20, yfood = 30;

//尾部坐标,尾部到达拐点标志
int xtail, ytail, tailflag = 0;

2、主程序

int main() {
    //尾部初始值
	xtail = x;
	ytail = y - length;
	while (1) {
        //按键检测函数
		if (kbhit())
			input();
        //蛇体默认移动,触发死亡条件break掉循环
		if (add())
			break;
        //尾部检测,清楚尾部的图案
		tail();
        //吃到食物尾部加长
		addlong();
        //更新屏幕显示
		system("cls");
		printf("\t\t\t成绩:%d\n", length);
		printf("%s", backgd);
	}
	system("cls");
	printf("游戏结束");
	return 0;
}

3、按键检测

用来记录拐点信息

void input() {
	char key = getch();
	change++;
	xchange[change] = x;
	ychange[change] = y;
	if (key == 'w') {
		decation[change] = 1;
	}
	if (key == 'a') {
		decation[change] = 2;
	}
	if (key == 's') {
		decation[change] = 3;
	}
	if (key == 'd') {
		decation[change] = 4;
	}
}

4、食物判定

如果蛇头移动到食物坐标length就会加一,并且再随机一个食物

void addlong() {
	backgd[xfood][yfood] = 'X';
	if (x == xfood && y == yfood && change == 0) {
		length++;
		ytail--;
		xfood = rand() % 25 + 1;
		yfood = rand() % 77 + 1;
	}
	if (x == xfood && y == yfood && change != 0) {
		length++;
		if (decation[tailflag] == 1)
			xtail++;
		if (decation[tailflag] == 2)
			ytail++;
		if (decation[tailflag] == 3)
			xtail--;
		if (decation[tailflag] == 4)
			ytail--;
		xfood = rand() % 25 + 1;
		yfood = rand() % 77 + 1;
	}
}

5、尾部判定加清楚

用tailflag去读取拐点信息,再进行相应的坐标偏移

void tail() {
	if (tailflag == 0) {
		ytail++;
		if (ytail == ychange[tailflag + 1])
			tailflag++;
	} else {
		if (decation[tailflag] == 1) {
			xtail--;
			if (xtail == xchange[tailflag + 1]) {
				tailflag++;
				return;
			}
		}
		if (decation[tailflag] == 2) {
			ytail--;
			if (ytail == ychange[tailflag + 1]) {
				tailflag++;
				return;
			}
		}
		if (decation[tailflag] == 3) {
			xtail++;
			if (xtail == xchange[tailflag + 1]) {
				tailflag++;
				return;
			}
		}
		if (decation[tailflag] == 4) {
			ytail++;
			if (ytail == ychange[tailflag + 1]) {
				tailflag++;
				return;
			}
		}
	}
}

6、蛇体默认移动、死亡判定

蛇头根据拐点进行坐标偏移,如果碰到“*”即为死亡

int add() {
	clear();
	if (change == 0) {
		y++;
		backgd[x][y] = head;
		backgd[x][y - 1] = body;
	} else {
		if (decation[change] == 1) {
			if (backgd[x - 1][y] == '*')
				return 1;
			backgd[x - 1][y] = head;
			backgd[x][y] = body;
			x--;
		}
		if (decation[change] == 2) {
			if (backgd[x][y - 1] == '*')
				return 1;
			backgd[x][y - 1] = head;
			backgd[x][y] = body;
			y--;
		}
		if (decation[change] == 3) {
			if (backgd[x + 1][y] == '*')
				return 1;
			backgd[x + 1][y] = head;
			backgd[x][y] = body;
			x++;
		}
		if (decation[change] == 4) {
			if (backgd[x][y + 1] == '*')
				return 1;
			backgd[x][y + 1] = head;
			backgd[x][y] = body;
			y++;
		}
	}
	return 0;
}

7、源码

#include <stdio.h>

char backgd[27][81] = {
	{"********************************************************************************\n"},
	{"*                                                                              *\n"},
	{"*                                                                              *\n"},
	{"*                                                                              *\n"},
	{"*                                                                              *\n"},
	{"*                                                                              *\n"},
	{"*                                                                              *\n"},
	{"*                                                                              *\n"},
	{"*                                                                              *\n"},
	{"*                                                                              *\n"},
	{"*                                                                              *\n"},
	{"*                                                                              *\n"},
	{"*                                                                              *\n"},
	{"*                                                                              *\n"},
	{"*                                                                              *\n"},
	{"*                                                                              *\n"},
	{"*                                                                              *\n"},
	{"*                                                                              *\n"},
	{"*                                                                              *\n"},
	{"*                                                                              *\n"},
	{"*                                                                              *\n"},
	{"*                                                                              *\n"},
	{"*                                                                              *\n"},
	{"*                                                                              *\n"},
	{"*                                                                              *\n"},
	{"******************************************************************************** "}
};
char head = '#', body = '*';
int x = 20, y = 10, length = 1, change = 0;

int xchange[999], ychange[999], decation[999] = {0};
int xfood = 20, yfood = 30;
int xtail, ytail, tailflag = 0;
void clear() {
	backgd[xtail][ytail] = ' ';
}
void input() {
	char key = getch();
	change++;
	xchange[change] = x;
	ychange[change] = y;
	if (key == 'w') {
		decation[change] = 1;
	}
	if (key == 'a') {
		decation[change] = 2;
	}
	if (key == 's') {
		decation[change] = 3;
	}
	if (key == 'd') {
		decation[change] = 4;
	}
}
void addlong() {
	backgd[xfood][yfood] = 'X';
	if (x == xfood && y == yfood && change == 0) {
		length++;
		ytail--;
		xfood = rand() % 25 + 1;
		yfood = rand() % 77 + 1;
	}
	if (x == xfood && y == yfood && change != 0) {
		length++;
		if (decation[tailflag] == 1)
			xtail++;
		if (decation[tailflag] == 2)
			ytail++;
		if (decation[tailflag] == 3)
			xtail--;
		if (decation[tailflag] == 4)
			ytail--;
		xfood = rand() % 25 + 1;
		yfood = rand() % 77 + 1;
	}
}
void tail() {
	if (tailflag == 0) {
		ytail++;
		if (ytail == ychange[tailflag + 1])
			tailflag++;
	} else {
		if (decation[tailflag] == 1) {
			xtail--;
			if (xtail == xchange[tailflag + 1]) {
				tailflag++;
				return;
			}
		}
		if (decation[tailflag] == 2) {
			ytail--;
			if (ytail == ychange[tailflag + 1]) {
				tailflag++;
				return;
			}
		}
		if (decation[tailflag] == 3) {
			xtail++;
			if (xtail == xchange[tailflag + 1]) {
				tailflag++;
				return;
			}
		}
		if (decation[tailflag] == 4) {
			ytail++;
			if (ytail == ychange[tailflag + 1]) {
				tailflag++;
				return;
			}
		}
	}
}
int add() {
	clear();
	if (change == 0) {
		y++;
		backgd[x][y] = head;
		backgd[x][y - 1] = body;
	} else {
		if (decation[change] == 1) {
			if (backgd[x - 1][y] == '*')
				return 1;
			backgd[x - 1][y] = head;
			backgd[x][y] = body;
			x--;
		}
		if (decation[change] == 2) {
			if (backgd[x][y - 1] == '*')
				return 1;
			backgd[x][y - 1] = head;
			backgd[x][y] = body;
			y--;
		}
		if (decation[change] == 3) {
			if (backgd[x + 1][y] == '*')
				return 1;
			backgd[x + 1][y] = head;
			backgd[x][y] = body;
			x++;
		}
		if (decation[change] == 4) {
			if (backgd[x][y + 1] == '*')
				return 1;
			backgd[x][y + 1] = head;
			backgd[x][y] = body;
			y++;
		}
	}
	return 0;
}
int main() {
	xtail = x;
	ytail = y - length;
	while (1) {
		if (kbhit())
			input();
		if (add())
			break;
		tail();
		addlong();
		system("cls");
		printf("\t\t\t成绩:%d\n", length);
		printf("%s", backgd);
	}
	system("cls");
	printf("游戏结束");
	return 0;
}

  • 21
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CJds_snakeView类 Struct list { int x; int y; }; 点结构,x表示横坐标,y表示纵坐标。 成员变量: int start;start=1开始游戏,start=0停止游戏。 int difficulty;表示游戏难度,等于10表示容易,等于6表示普通,等于3表示困难,等于2表示特困。 int last_aspect;表示蛇之前前进的方向,用于判断防止蛇逆行的。 int can_new;表示是否添加新食物。等于1表示产生新的食物,等于0表示产生之后不不要再产生食物。 int count;表示蛇的节数; CRect rct;表示矩形方格; list a[100];保存蛇的长度; list b;用来保存蛇头的坐标位置; int aspect;表示蛇前进的方向 等于0表示蛇向右前进; 等于1表示蛇向下前进; 等于2表示蛇向左前进; 等于3表示蛇向上前进; int xx;表示食物的x坐标; int yy;表示食物的y坐标; 成员函数: void Init();初始化蛇的节数,并确定了节数的坐标位置。首先初始化蛇的前进方向aspect=0是向右前进的,last_aspect=0用来保存蛇当前前进的方向。并且初始化蛇的节数为4节,并指明了它们的坐标位置。can_new=1表示产生一个新的食物。 void aliveordie();判断蛇是死还是活着。有两种情况,一种是蛇自己撞到自己,表示死了,start=0从新开始游戏,另一种是超出了界面(20,20,420,420)撞到了墙start=0也从新开始游戏。 double random(double start,double end);在start和end坐标之间产生随即数; 消息处理事件: (1)void onTimer(UINT nIDEvent);在OnCreate()创建计时器SetTimer(),来触发OnTimer事件,所以要首先销毁时间计时器,然后调用aliveordie()函数判断蛇的生死情况,CString str_count; str_count.Format("分数:%d",count-4)显示蛇的节数,TextOut()指出坐标输出文本,创建设备上下文,和创建位图。然后把位图选择到设备上下文上,填充颜色为白色。 在位图上绘制两个矩形线框: Rectangle(CRect(10,10,440,440)); Rectangle(CRect(20,20,430,430)); 显示位图(BitBlt(0,0,1000,1000,&MenDC,0,0,SRCCOPY)); 判断如果游戏开始(start==1),b.x=a[0].x用b.x来保存蛇头的横坐标;b.y=a[0].y用b.y来保存蛇头的纵坐标。如果aspect==0表示蛇向右前进,aspect=1表示蛇向下前进,aspect==2表示蛇向左前进,aspect==3表示蛇向上前进,a[1].x=b.x;a[1].y=b.y;把蛇头的坐标付给了a[1],说明蛇头改变了前进的方向。绘制蛇头矩形方格,并且设置蛇头的颜色为红色,蛇身是三个黄色的矩形方格。if (a[0].x==xx && a[0].y==yy)判断蛇头的位置与食物的关系,现在的情况说明蛇吃了食物,蛇的节数加一,各个节数的坐标向前进一位。调用random()函数产生随即的食物,然后判断食物随即产生的位置与蛇的位置,如果产生的食物在蛇身体上,要从新调用random()函数随即再产生食物。产生的食物颜色为绿色。int m_timer=SetTimer(1,difficulty*30,NULL);计时间隔,计时间隔的快慢是根据难易程度的不而确定的。销毁位图、销毁设备上下文。 (2)OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);判断蛇当前前进的方向,当aspect返回0,表示蛇前进的方向是向右,当aspect返回1,表示蛇前进的方向是下,当aspect返回2,表示蛇前进的方向是向左,当aspect返回3,表示蛇前进的方向是向上。 (3)点击菜单按钮调用以下函数: OnDifficultyEasy();OnDifficultyHard();OnDifficultyNormal();OnDifficultyVeryhard();OnButtonStart();

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值