C语言字符游戏-贪吃蛇(AI)

贪吃蛇游戏是一款经典的益智游戏,有PC和手机等多平台版本。既简单又耐玩。该游戏通过控制蛇头方向吃蛋,从而使得蛇变得越来越长。



让我们来看一下怎么用C语言来写一个简单的贪吃蛇游戏吧.

先是主程序的伪代码

输出字符矩阵
    WHILE not 游戏结束 DO
        ch=等待输入
        CASE ch DO
        ‘A’:左前进一步,break 
        ‘D’:右前进一步,break    
        ‘W’:上前进一步,break    
        ‘S’:下前进一步,break    
        END CASE
        输出字符矩阵
    END WHILE
    输出 Game Over!!! 

然后是程序的函数部分

void snakeMove (int, int);		//蛇移动函数 
void put_money (void);			//下放食物 
void output (void);				//输出数组 
void gameover (void);			//打印提示游戏结束 
void snakeExtent (void);		//吃到食物后蛇的伸长 
int judge (void);				//判断游戏是否结束 
char changeUpper (char);		//将字母全部转为大写 

蛇身部分

char map[12][13] =
	{"************",
	"*XXXXH     *",
	"*          *",
	"*          *",
	"*          *",
	"*          *",
	"*          *",
	"*          *",
	"*          *",
	"*          *",
	"*          *",
	"************"};
//蛇身的各个位置,[0]是头	
int snakeX[SNAKE_MAX_LENGTH] = {5, 4, 3, 2, 1}; 
int snakeY[SNAKE_MAX_LENGTH] = {1, 1, 1, 1, 1};

主程序部分

int main() {
 	char ch='d';//默认向右走 
	put_money(); 	
	output();
	while(1) {
 		ch = changeUpper(ch);
		switch(ch) {
			case 'A': 
				snakeMove (-1, 0);
				break;
			case 'S':
				snakeMove (0, 1);
				break;
			case 'D':
				snakeMove (1, 0);
				break; 
			case 'W':
				snakeMove (0, -1);
				break;
			}
		Sleep(200);	
		if(kbhit())
			ch = getche();
		if(judge() == 0){
			gameover();
			break;
		}
	}
}
蛇的移动函数

void snakeMove (int x, int y) {
	int i; 
	if(snakeX[0] + x == moneyX && snakeY[0] + y == moneyY) 				//判断是否吃到食物 ,如是便使蛇伸长 
		snakeExtent() ;						
	else 
		map[snakeY[snakeLength - 1]][snakeX[snakeLength - 1]] = ' ';	//如果没有吃到食物,把蛇的最后一段删除 
	//蛇的向前走,蛇身的后面一段继承前面一段的位置 
	for(i = snakeLength - 1; i > 0; i --) {								 
		snakeX[i] = snakeX[i - 1];		
		snakeY[i] = snakeY[i - 1];
		map[snakeY[i]][snakeX[i]] = 'X';
	}
	snakeX[0] += x;
	snakeY[0] += y;
	map[snakeY[0]][snakeX[0]] = 'H';
	//输出数组 
	output ();
}
放食物函数
void put_money (void) {
	//随机设置食物位置 
	moneyX = rand () % 9;
	moneyY = rand ()  % 9;
	//判断位置是否为空 
	if (map[moneyY][moneyX] == ' ') {
		map[moneyY][moneyX]='$';
	}
	else	//不为空重新调用 
		put_money ();		
}
吃到食物后的伸长

void snakeExtent (void) {
	put_money ();//蛇吃到食物后重置食物位置
	//小于最长长度 
	if (snakeLength < SNAKE_MAX_LENGTH) { 
		snakeY[snakeLength] = snakeY[snakeLength-1];
		snakeX[snakeLength] = snakeX[snakeLength-1];
		snakeLength ++ ;
	} 
	else 
		map[snakeY[snakeLength-1]][snakeX[snakeLength-1]] = ' '; //大于最长长度 
}

判断蛇是否存活

int judge(){
	int i;
	//碰到框架游戏结束 
	if(snakeX[0] == 0||snakeX[0] == 11||snakeY[0] == 0||snakeY[0] == 11)
		return 0;
	//头碰到自己游戏结束 
	for(i=1;i<snakeLength;i++) {
		if(snakeX[0] == snakeX[i]&&snakeY[0]==snakeY[i])
				return 0;
	}
	return 1;
}
然后就可以玩啦

接下来是AI部分(让蛇自己寻找食物)


新增函数

void movedis();					//设置可走路线与食物的距离 
char aisnake();					//这是找最小的距离的输出 
void judgearray();				//设置蛇的可走路线	
int autojudge(int , int);		//判断蛇是否可走 

新增变量

char array[4][2] = {{'a',1},{'s',1},{'w',1},{'d',1}};	//储存各个动作以及该动作是否可移动 
int distance[4]; 								//储存各个可移动动作与食物的距离 
int xymove[4][2] = {{-1,0},{0,1},{0,-1},{1,0}};  //[][0]为X,[][1]为Y ,储存各个动作的移动方向 

下面是各个函数

int autojudge(int x, int y) {
	if(map[snakeY[0] + y][snakeX[0] + x] != 'X'&&map[snakeY[0] + y][snakeX[0] + x] != '*')	//判断是否会移动到蛇身 
		return 1;
	else
		return 0;
}

void judgearray() {
	int count;
	for(count = 0;count<4;count ++) {
		if(autojudge (xymove[count][X],xymove[count][Y]) )
			array[count][1] = 1;		 //说明该移动是否合理 
		else
			array[count][1] = 0;
	}
}

void movedis() {
	int num;
	judgearray();
	for(num=0;num<4;num++) {
		if(array[num][1]==1)
			distance[num] = abs(moneyX-snakeX[0]-xymove[num][X])+abs(moneyY-snakeY[0]-xymove[num][Y]);//可移动的算距离 
		else
			distance[num] = 9999;			//不可移动的设置一个超大的值 
	}
}

char aisnake() {
	movedis();
	int num,min=0;
	//选择并返回一个最合适的动作 
	for(num=1;num<4;num++) {			 
		if(distance[num] < distance[min])
			min=num; 
	}
	return array[min][0];
}











  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值