C语言编写贪吃蛇
整个代码都是C语言,其中调用少部分库函数,不如实现屏幕坐标打印的函数,贪吃蛇游戏代码的核心在于蛇身体坐标的更新,实现细节请看代码注释,
代码
//#include "stdafx.h" 如果是vc环境的话加上该头文件
#include<stdlib.h>
#include <stdio.h>
#include <windows.h>
#include <conio.h>
#include <time.h>
#define TURNUP 1 //宏定义蛇运动的四个方向
#define TURNDOWN 2
#define TURNRIGHT 3
#define TURNLEFT 4
#define MAXROW 20
#define MAXCOL 30
void printSnake(int bodylen,COORD bodypos[]);
void run (int bodylen,COORD *body,int dirction,int times);
void initSnake (int bodylen,COORD* body,COORD head);
void disappeartSnake(int bodylen,COORD *bodypos);
void createFood();
void printwall();
void printscore(int len);
void supervisekeybot(COORD *body,int direction,int times);
void createFood1();
int len=5;
COORD gfoodPos; //定义三个全局变量,身体长度和两种食物 坐标
COORD gfoodPos1; // COORD为系统定义结构体,可实现屏幕坐标表示
int main(int argc, char* argv[])
{
int direction=TURNRIGHT;//没有按键输入时默认的初始方向
COORD body[20]={0};
COORD head={1,1};
printwall();
initSnake (len,body,head);//根据head初始化蛇的身体
printSnake(len,body); //打印初始的蛇
createFood();
createFood1();
supervisekeybot(body,direction,10);
return 0;
}
/*******************************************
函数名称:printSnake
函数功能:打印蛇的身体
函数参数:bodylen --身体的长度
bodypos --蛇身体的坐标
函数返回:
函数作者:forxn@qq.com
********************************************/
void printSnake(int bodylen,COORD *bodypos)
{
//调用库函数,获取蛇身体的坐标,并在该坐标点打印信息,蛇头为8,蛇身为*
HANDLE hOut;
COORD pos=bodypos[bodylen-1];
hOut=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut,pos);
printf("8\n");
for(int i=0;i<bodylen-1;i++)
{
HANDLE hOut;
//获取蛇身体的坐标
COORD pos=bodypos[i];
hOut=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut,pos);
//打印该点
printf("*\n");
}
}
/*******************************************
函数名称:changeDirction
函数功能:实现蛇的转弯,或者说蛇身体的更新
该函数为整个贪吃蛇的核心点,核心思想为以蛇头坐标为起点,
此程序将蛇头坐标定为body[len-1];
后面点的坐标都取其前一个点的的位置
********************************************/
void changeDirction(int bodylen,COORD *body,int dirction)
{
int p=bodylen;
for(int i=0;bodylen>1;bodylen--)
{
body[i]=body[i+1];
i++;
}
switch (dirction)
{
case TURNUP :
{
body[p-1].Y--;
break;
}
case TURNDOWN :
{
body[p-1].Y++;
break;
}
case TURNRIGHT:
{
body[p-1].X++;
break;
}
case TURNLEFT :
{
body[p-1].X--;
break;
}
default:
{
break;
}
}
//吃到食物的时候
if(body[p-1].X==gfoodPos.X
&&body[p-1].Y==gfoodPos.Y)
{
body[p].X=body[p-1].X;
body[p].Y=body[p-1].Y;
len++;
createFood();
printscore(bodylen);
}
else if(body[p-1].X==gfoodPos1.X //此处必须加else;不然有bug
&&body[p-1].Y==gfoodPos1.Y)
{
body[p].X=body[p-1].X;
body[p].Y=body[p-1].Y;
body[p+1].X=body[p].X;
body[p+1].Y=body[p].Y;
len=len+2;
createFood1();
printscore(bodylen);
}
//边界检测
if(body[p-1].X==0||body[p-1].Y==0||body[p-1].X==MAXCOL||body[p-1].Y==MAXROW)
{
COORD a;
a.X=5;
a.Y=10;
HANDLE hOut;
hOut=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut,a);
printf("GAME OVER!");
printSnake(len,body);
exit(0);
}
for (int j=0;j<p;j++)
{
if (body[p-1].X==body[p-j-2].X&&body[p-1].Y==body[p-j-2].Y)
{
COORD b;
b.X=5;
b.Y=10;
HANDLE hOut;
hOut=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut,b);
printf("GAME OVER!");
printSnake(len,body);
exit(0);
}
}
}
/*******************************************
函数功能:
函数参数:
********************************************/
void run (int bodylen,COORD *body,int dirction,int times)
{
for(int i=0;i<times;i++)
{
//重新设置蛇身体的点坐标
changeDirction(bodylen,body,dirction);
printSnake(bodylen,body);
Sleep(200);
disappeartSnake(bodylen,body);
}
}
/*******************************************
函数功能:
函数参数:
********************************************/
void initSnake (int bodylen,COORD* body,COORD head)
{
for (int i=0;i<bodylen;i++)
{
body[bodylen-i-1].X=head.X;
body[bodylen-1-i].Y=head.Y;
}
}
/*******************************************
函数功能:产生食物,调用rand函数随机位置产生两种食物
函数参数:
********************************************/
void createFood()
{
srand(time(0));
int x=rand()%(MAXCOL-1);
int y=rand()%(MAXROW-1);
gfoodPos.X=x;
gfoodPos.Y=y;
if(gfoodPos.X==0||gfoodPos.Y==0)
{
createFood();
}
HANDLE hOut;
hOut=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut,gfoodPos);
printf("A\n");
}
void createFood1()
{
//srand(time(0));
int x=rand()%(MAXCOL-1);
int y=rand()%(MAXROW-1);
gfoodPos1.X=x;
gfoodPos1.Y=y;
if(gfoodPos1.X==0||gfoodPos1.Y==0)
{
createFood1();
}
HANDLE hOut;
hOut=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut,gfoodPos1);
printf("B\n");
}
/*******************************************
函数功能:蛇身体的更新,调用system("cls")不能满足要求
将坐标点依次打印空格可实现“清屏”效果
函数参数:
********************************************/
void disappeartSnake(int bodylen,COORD *bodypos)
{
for(int i=0;i<bodylen;i++)
{
HANDLE hOut;
COORD pos=bodypos[i];
hOut=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut,pos);
printf(" \n");
}
}
/*******************************************
函数功能:打印墙的边界
函数参数:
********************************************/
void printwall()
{
for(int i=0;i<=MAXROW;i++)
{
for(int j=0;j<=MAXCOL;j++)
{
if(i==0||j==0||i==MAXROW||j==MAXCOL)
putchar('#');
else
printf(" ");
}
putchar('\n');
}
}
/*******************************************
函数功能:检测键盘的按键,实现蛇的实时控制
函数参数:
********************************************/
void supervisekeybot(COORD *body,int direction,int times)
{
while(1) // 蛇开始移动并监测键盘
{
run (len,body,direction,1);
printscore(len);
if(_kbhit())//监测键盘是否有输入,也可采用多线程实现,此处调用_kbhit()
{
char ch=getch();
switch (ch)
{
case 'w':
{
run (len,body,TURNUP,1);//此时times设置为1,才能实现实时控制响应;
direction=TURNUP; //键盘键入时蛇的方向更新并维持
break;
}
case 's':
{
run (len,body,TURNDOWN,1);
direction=TURNDOWN;
break;
}
case 'a':
{
run (len,body,TURNLEFT,1);
direction=TURNLEFT;
break;
}
case 'd':
{
run (len,body,TURNRIGHT,1);
direction=TURNRIGHT;
break;
}
}
}
}
}
/*******************************************
函数功能:将蛇的身体长度打印,作为分数
函数参数:
********************************************/
void printscore(int len)
{
COORD score;
score.X=32;
score.Y=12;
HANDLE hOut;
hOut=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut,score);
printf("SCORE:%d",len);
}