C语言实现最小贪食蛇源码

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#include <conio.h>

int	v=200;						//小蛇的移动速度
int foodx;						//食物的坐标
int foody;
int snakeleng=2;				//蛇身的长度(注意数组坐标从0开始)
int count=0;					//计算分数

struct body
{
	int x;
	int y;
};
struct body snake_body[500];	//蛇身的长度


void gotoxy(int x,int y)
{
	HANDLE app;								//定义句柄
	COORD pos;								//定义坐标
	pos.X=x;								//修改X坐标,使X移动
	pos.Y=y;								//修改Y坐标,使Y移动
	app=GetStdHandle(STD_OUTPUT_HANDLE);	//获取句柄
	SetConsoleCursorPosition(app,pos);		//将获取的句柄移动,坐标是POS	
}

void drawmap()						//地图函数
{
	int i;

	for(i=1;i<=30;i++)
		printf("★");

	printf("\n");

	for(i=1;i<=23;i++)
	{
		printf("★\t\t\t\t\t\t\t  ★");
		printf("\n");
	}

	for(i=1;i<=30;i++)
		printf("★");
	
	gotoxy(65,3);
	printf("数组版贪吃蛇");
	gotoxy(66,4);
	printf("贪吃蛇内测");
	

	gotoxy(64,7);
	printf("======");
	gotoxy(64,8);
	printf("‖玩家得分‖");
	gotoxy(64,9);
	printf("‖\t  ‖");
	gotoxy(64,10);
	printf("======");

	gotoxy(64,13);
	printf("======");
	gotoxy(64,14);
	printf("‖游戏说明 ‖");
	gotoxy(64,15);
	printf("‖w向上移动‖");
	gotoxy(64,16);
	printf("‖s向下移动‖");
	gotoxy(64,17);
	printf("‖a向左移动‖");
	gotoxy(64,18);
	printf("‖d向右移动‖");
	gotoxy(64,19);
	printf("======");
}

void initsnake()			//初始化小蛇
{
	int i,temp=7;

	for(i=0;i<3;i++,temp-=2)
	{
		snake_body[i].x=temp;
		snake_body[i].y=10;

		gotoxy(temp,10);
		printf("■");
	}
}

void direct(char ch)		//小蛇移动方向函数
{
		if(ch=='s'||ch=='S')//支持大小写按键
			snake_body[0].y=snake_body[0].y+1;	

		if(ch=='w'||ch=='W')
			snake_body[0].y=snake_body[0].y-1;

		if(ch=='a'||ch=='A')
			snake_body[0].x=snake_body[0].x-2;

		if(ch=='d'||ch=='D')
			snake_body[0].x=snake_body[0].x+2;
}

void make_food()					//制造食物(有问题,怎么避免把食物生成在蛇身里?)
{
	int i,flag=1;					//此处是flag用于记录蛇身坐标与食物坐标是否相等

	srand((unsigned)time(NULL));

	while(flag)
	{
		foodx=rand()%53+2;
		if(foodx%2==0)				//将食物的X轴坐标变为奇数
			foodx++;

		foody=rand()%22+2;
	
		for(i=snakeleng;i>=0;i--)	//遍历蛇身
		{	
			if(snake_body[i].x==foodx && snake_body[i].y==foody)//如果产生的食物坐标与蛇身的任意位置相等
			{
				flag=1;				//坐标相等则再重新产生新的坐标
				break;				//跳出循环
			}
			else
				flag=0;
		}
		
	}
	gotoxy(foodx,foody);			//画出食物
	printf("●");
}


int add_snake_body()			//增加蛇身的函数
{
	if(snake_body[0].x==foodx && snake_body[0].y==foody)	//如果食物坐标和蛇头坐标相等,说明蛇已经吃到食物了
	{
		gotoxy(foodx,foody);	//擦去蛇的食物
		printf("■");

		snakeleng++;			//增加蛇的长度
		count++;				//每吃一个食物增加一分
		v--;

		gotoxy(66,9);			//打印得分
		printf("%5d",count);

		snake_body[snakeleng].x=snake_body[snakeleng-1].x;		//增加新的身体,读取下个位置的坐标
		snake_body[snakeleng].y=snake_body[snakeleng-1].y;
			
		return 1;				//记录蛇已经吃了食物
	}
	else
		return 0;
}

void read_next_coord()			//下一位置坐标函数
{
	int i;

	for(i=snakeleng;i>0;i--)	//循环读取下一个位置的坐标
		{
			if(i==snakeleng)	//如果i等于蛇尾(snakeleng最先初始化为2,那么2是蛇尾)
			{
				gotoxy(snake_body[i].x,snake_body[i].y);		//擦除蛇尾
				printf("  ");
			}

			snake_body[i].x=snake_body[i-1].x;					
			snake_body[i].y=snake_body[i-1].y;	
	}
}

void snake_death()				//判断蛇死亡的函数
{
	int i;

	if( (snake_body[0].x<2 || snake_body[0].x>55) || (snake_body[0].y<1 || snake_body[0].y>23))	//检测左右两边是否碰墙,检测上下两边是否碰墙
	{
		printf("撞墙了!游戏结束!");
		exit(0);
	}

	for(i=snakeleng;i>=4;i--)					//能否避免遍历所有数组?
	{
		if(snake_body[0].x==snake_body[i].x && snake_body[0].y==snake_body[i].y)
		{
			printf("咬到身体了!");
			exit(0);
		}
	}
}

int main(void)
{
	int flag=1;						//标记食物是否被吃
	char ch2='d',ch1='a';

	system("color b");				//改变颜色

	drawmap();						//初始化地图
	
	initsnake();					//初始化蛇身

	while(1)
	{
		if(flag)
		{
			make_food();
			flag=0;
		}

		read_next_coord();			//蛇身读取下一个位置的坐标
	
		if(kbhit())					//接受键盘输入的方向
			ch1=getch();
		
		if(ch1!='a' && ch1!='s' && ch1!='w' && ch1!='d')//此语句是为了避免用户按下非a,s,w,d键
			ch1=ch2;				//将上次移动的方向键赋值(如果错误按下,然默认为按原来方向移动)

		if((ch2=='d' && ch1!='a')||(ch2=='w' && ch1!='s')||(ch2=='s' && ch1!='w')||(ch2=='a' && ch1!='d'))
		{
			ch2=ch1;				//此语句要来判断小蛇不往相反方向移动	
		}

		direct(ch2);				//调用方向函数	
		
		gotoxy(snake_body[0].x,snake_body[0].y);				//画出新的蛇头
		printf("■");
		Sleep(v);					//控制蛇的速度

		flag=add_snake_body();		//判断蛇是否吃了食物

		snake_death();				//判断蛇是否死亡
	}	
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
用windows api 做的贪吃蛇 #include #include"resource.h" #include"Node.h" #include #include TCHAR szAppname[] = TEXT("Snack_eat"); #define SIDE (x_Client/80) #define x_Client 800 #define y_Client 800 #define X_MAX 800-20-SIDE //点x的范围 #define Y_MAX 800-60-SIDE //点y的范围 #define TIME_ID 1 #define SECOND 100 #define NUM_POINT 10 //点的总个数 #define ADD_SCORE 10 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { HWND hwnd; //窗口句柄 MSG msg; //消息 WNDCLASS wndclass; //窗口类 HACCEL hAccel;//加速键句柄 wndclass.style = CS_HREDRAW | CS_VREDRAW; //窗口的水平和垂直尺寸被改变时,窗口被重绘 wndclass.lpfnWndProc = WndProc; //窗口过程为WndProc函数 wndclass.cbClsExtra = 0; //预留额外空间 wndclass.cbWndExtra = 0; //预留额外空间 wndclass.hInstance = hInstance; //应用程序的实例句柄,WinMain的第一个参数 wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); //设置图标 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); //载入预定义的鼠标指针 wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //设置画刷 wndclass.lpszMenuName = szAppname; //设置菜单 wndclass.lpszClassName = szAppname; //设置窗口类的名字 if (!RegisterClass(&wndclass))//注册窗口类 { MessageBox(NULL, TEXT("这个程序需要windows NT!"), szAppname, MB_ICONERROR); return 0; } hwnd = CreateWindow(szAppname, TEXT("Snack_eat"),//CreateWindow函数调用时,WndProc将受到WM_CREATE WS_OVERLAPPEDWINDOW&~WS_THICKFRAME& ~WS_MAXIMIZEBOX,//普通的层叠窗口&禁止改变大小&禁止最大化 CW_USEDEFAULT, //初始x坐标(默认) CW_USEDEFAULT, //初始y坐标 x_Client, //初始x方向尺寸 770 y_Client, //初始y方向尺寸 750 NULL, //父窗口句柄 NULL, //窗口菜单句柄 hInstance, //程序实例句柄 WinMain函数中第二个参数 NULL); //创建参数 ShowWindow(hwnd, iCmdShow);//显示窗口,iCmdShow是WinMain的第四个参数,决定窗口在屏幕中的初始化显示形式,例:SW_SHOWNORMAL表示正常显示 UpdateWindow(hwnd);//使窗口客户区重绘,通过向WndProc发送一条WM_PAINT消息而完成的 hAccel = LoadAccelerators(hInstance, szAppname);//加载加速键 while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(hwnd, hAccel, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } }/* while (GetMessage(&msg, NULL, 0, 0))//GetMessage函数从消息队列中得到消息,填充msg。如果msg.message等于WM_QUIT,返回0,否则返回非0 { TranslateMessage(&msg);//将msg返回给windows已进行某些键盘消息的转换 DispatchMessage(&msg);//将msg再次返回给windows }*/ return msg.wParam;//msg.wParam是PostQuitMessage函数的参数值,通常是0 } ...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值