好久没发博文了,这段时间正在入门kali,不过今天我会给大家讲解一下有关c语言贪吃蛇的小代码, 废话不多说,直接上代码

等等,不急,小编还有一个收藏了半年的文件给大家分享一下:
适合刚入门同学学习的编程小游戏(附源码)
https://download.csdn.net/download/qq_42662283/11965028

首先,咱不先急着做核心代码,先把可能会用到的画图函数写一写,方便日后使用

void drawRow(int y, int x1, int x2, char ch)
{  setxy(hOut,x1,y);  for(int i = 0; i <= (x2-x1); i++)  printf("%c",ch);
}
void drawCol(int x, int y1, int y2, char ch)
{  int y=y1;  while(y!=y2+1)  {  setxy(hOut,x, y);  printf("%c",ch);  y++;  }
}

setxy 这个函数之后会讲,用来定位光标输出位置

void drawFrame(COORD a, COORD  b, char row, char col)
{  drawRow(a.Y, a.X+1, b.X-1, row);  drawRow(b.Y, a.X+1, b.X-1, row);  drawCol(a.X, a.Y+1, b.Y-1, col);  drawCol(b.X, a.Y+1, b.Y-1, col);
}
void drawFrame(int x1, int y1, int x2, int y2, char row, char col)
{  COORD a={x1, y1};  COORD b={x2, y2};  drawFrame(a, b, row, col);
}

画个框框多好看,主界面都会用到画框

接下来是一些基础可能会用到的常用代码函数,非常实用,在其他dos窗口的c语言程序中经常会用

void HideCursor()
{  CONSOLE_CURSOR_INFO cursor_info = {1, 0};   SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
} 

隐藏光标,绝对实用

void setxy(HANDLE hOut, int x, int y)
{COORD pos;pos.X = x;            //横坐标pos.Y = y;            //纵坐标SetConsoleCursorPosition(hOut, pos);
}

这个setxy是之前讲的定位光标函数,这个HANDLE hOut 只是作为一个参数,在之前需要定义一下,

HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);//定义显示器句柄变量

或者哪位可以直接把定义显示器句柄变量写在函数里面,这样就不需要每次把hOut传给它了

下面正式进入贪吃蛇代码阶段

我们主要把程序分为home(),initial(),show()三个阶段,分别用来显示主界面,贪吃蛇初始化界面,和贪吃蛇函数

const int H =25;   //地图的高
const int L = 80;  //地图的长
int ifinitial = 1;
char GameMap[H+2][L+2];   //游戏地图
int time0;//初始时间
int timefinal;//结束时间
int  key;  //按键保存
int  sum = 1, over = 0, speed=0, stoppingtime=0, speedlevel=0;  //蛇的长度, 游戏结束(自吃或碰墙)
int  extrascore = 0;
int  dx[4] = {0, 0, -1, 1};  //左、右、上、下的方向
int  dy[4] = {-1, 1, 0, 0};
int flagOfyn=0;
struct Snake   //蛇的每个节点的数据类型
{  int x, y;  //左边位置  int now;   //保存当前节点的方向, 0,1,2,3分别为左右上下
}Snake[H*L];
const int ix=2,iy=2;
const char Shead = '@';  //蛇头
const char Sbody = '#';  //蛇身
const char Sfood = '*';  //食物
const char Snode = ' ';  //' '在地图上标示为空
const char Sfood2 = '!';  //2分食物
int Home();
void Initial();  //地图的初始化
void Create_Food(); //在地图上随机产生食物
void Show();   //刷新显示地图
void Button();  //取出按键,并判断方向
void Move();   //蛇的移动
void Check_Border();  //检查蛇头是否越界
void Check_Head(int x, int y);   //检查蛇头移动后的位置情况
void drawFrame(COORD a, COORD  b, char row, char col);//画框
void drawFrame(int x1, int y1, int x2, int y2, char row, char col);
void HideCursor();//隐藏光标
void drawRow(int y, int x1, int x2, char ch);
void drawCol(int y, int x1, int x2, char ch);
void setxy(HANDLE hOut,int x,int y);  //设置光标位置
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);//定义显示器句柄变量

这里小编为了之后解释方便就把所有变量就在这里列出来了, 各位看一下,真正Snake结构体不需要多么复杂,坐标和方向就足够了

好现在开始:

int Home(){system("cls");system("color 2E");HideCursor();
/* drawFrame(0, 0, 48, 24, '=', '|');//    draw map frame;  drawFrame(49, 0, 79, 4, '-', '|');//        draw output frame  drawFrame(49, 4, 79, 9, '-', '|');//        draw score frame  drawFrame(49, 9, 79, 20, '-', '|');//   draw operate frame  drawFrame(49, 20, 79, 24, '-', '|');//  draw other message frame*/ setxy(hOut,50, 1);  printf("Snakes eating game");  drawRow(3, 0, 119, '-');  drawRow(5, 0, 119, '-');  setxy(hOut,48, 4);  printf("up and down and enter");  setxy(hOut,35, 10);  printf("1. level:low");  setxy(hOut,35, 12);  printf("2. level:middle");setxy(hOut,35, 14);  printf("3. level:high"); drawRow(20, 0, 119, '-');  drawRow(22, 0, 119, '-');  setxy(hOut,67, 11);  printf("low level:");  setxy(hOut,71, 13);  printf("low speed");  setxy(hOut,44, 21);  printf("制作人:Platonic hacker");  int j=10;  setxy(hOut,32, j);  printf(">>");  //drawFrame(45, 9, 79, 17, '=', '|');  while(1)  {   if( _kbhit() )  {     char x=_getch();  switch (x)  {  case 72 :  {     if( j == 14)  {  setxy(hOut,32, j);  printf(" ");  j = 12;  setxy(hOut,32, j);  printf(">>");  setxy(hOut,71, 13);  printf("            ");  setxy(hOut,67, 11);  printf("              ");setxy(hOut,67, 11);  printf("middle level:");  setxy(hOut,71, 13);  printf("middle speed");  break;}  else if( j == 12)  {  setxy(hOut,32, j);  printf(" ");  j = 10;  setxy(hOut,32, j);  printf(">>");  setxy(hOut,71, 13);  printf("            ");  setxy(hOut,67, 11);  printf("              ");setxy(hOut,67, 11);  printf("low level:");  setxy(hOut,71, 13);  printf("low speed"); break; }  else break;}case 80 :  {     if( j == 10 )  {  setxy(hOut,32, j);  printf(" ");          j = 12;  setxy(hOut,32, j);  printf(">>");  setxy(hOut,71, 13);  printf("              ");  setxy(hOut,67, 11);  printf("              ");setxy(hOut,67, 11);  printf("middle level:");  setxy(hOut,71, 13);  printf("middle speed");  break;}  else if( j == 12 )  {  setxy(hOut,32, j);  printf(" ");          j = 14;  setxy(hOut,32, j);  printf(">>");  setxy(hOut,71, 13);  printf("              ");setxy(hOut,67, 11);  printf("              ");  setxy(hOut,67, 11);  printf("high level:");  setxy(hOut,71, 13);  printf("high speed");break;  }  else break;}  case 13 :  {     if (j == 10) return 1; else if(j==12) return 2; else return 3;  }  }  }  }
}

这是主界面代码,可以选择难度,并会将难度结果返回,由于博主尽可能将程序架构写的清晰,所以主界面比较繁琐,大佬请略过

void Initial()  //地图的初始化
{  stoppingtime=0;ifinitial=1;//时间每次初始system("cls");sum = 1, over = 0, extrascore = 0;int i, j;  int hx, hy;  system("title Gluttonous Snake");  //控制台的标题  memset(GameMap, ' ', sizeof(GameMap));  //初始化地图全部为空' ' for (i=0;i<H+2;i++){GameMap[i][0]='|';GameMap[i][L+1]='|';}for (j=0;j<L+2;j++){GameMap[0][j]='_';GameMap[H+1][j]='-';}srand(time(0));   //随机种子  hx = rand()%H+1;    //产生蛇头  hy = rand()%L+1;  GameMap[hx][hy] = Shead;  Snake[0].x = hx;  Snake[0].y = hy;  Snake[0].now = -1;  for (int i=0;i<25;i++){    //随机产生25个食物Create_Food();}                for(i = 0; i < H+2; i++)   //地图显示  {   for(j = 0; j < L+2; j++)  if(GameMap[i][j]!=' '){ setxy(hOut,j+ix,i+iy) ;printf("%c", GameMap[i][j]);} printf("\n");  }  drawRow(2,84,113,'_');drawRow(9,84,113,'-');drawRow(28,84,113,'-');drawCol(113,3,27,'|')  ;setxy(hOut,85,3);printf("speedlevel is %d",speedlevel);setxy(hOut,85,4);printf("your score is 0");setxy(hOut,85,5);printf("the time you have survived:");setxy(hOut,89,7);printf("0  minutes 0  seconds");setxy(hOut,85,10);printf("Made by Thomas"); setxy(hOut,85,12); printf("click any direction button");setxy(hOut,85,13); printf("to start the game");getch();   //先接受一个按键,使蛇开始往该方向走  Button();  //取出按键,并判断方向
}

初始化其实很大程度上是为了之后做铺垫,并解决直接运行show()而导致的bug和不好的游戏体验,这里如果程序看不懂可以在回复区里问,我相信这个还是很简单的

void Show()  //刷新显示地图
{  int i=0, j=0,speed=0;flagOfyn=0;if(speedlevel==1) speed=100;//设置速度 else if(speedlevel==2)speed=50;else if(speedlevel==3) speed=10;if(ifinitial == 1){ifinitial = 0;time0=time(0);//设置初始时间 }int ifchange=0;int leveltime=0;int leveltime0=time0;while(1)  {   leveltime=time(0)-leveltime0;if(speedlevel==3){if(Snake[0].now==2||Snake[0].now==3)speed=20;else if(Snake[0].now==0||Snake[0].now==1)speed=10;}else if(speedlevel==2){if(Snake[0].now==2||Snake[0].now==3)speed=100;else if(Snake[0].now==0||Snake[0].now==1)speed=50;}else if(speedlevel==1){if(Snake[0].now==2||Snake[0].now==3)speed=200;else if(Snake[0].now==0||Snake[0].now==1)speed=100;}Sleep(speed); //延迟半秒(1000为1s),即每speed秒刷新一次地图  Button();   //先判断按键在移动  Move();  int score=sum+extrascore-1;timefinal=time(0);if(over)  //自吃或碰墙即游戏结束  {   system("cls");drawFrame(33,7,83,20,'=','|');setxy(hOut,54,9);printf("Game Over");setxy(hOut,52,12);printf("Your score:%d",score);setxy(hOut,43,16);printf(" Do you want to play again(y/n)");setxy(hOut,37,18);printf("the time you survive: %d minutes %d seconds",(timefinal-time0-stoppingtime)/60,(timefinal-time0-stoppingtime)%60);while(flagOfyn!=89&&flagOfyn!=121&&flagOfyn!=78&&flagOfyn!=110)flagOfyn=getch(); break;  }setxy(hOut,99,4) ;printf("%d",score);setxy(hOut,100,7) ;printf("  ");setxy(hOut,100,7) ;printf("%d",(timefinal-time0-stoppingtime)%60);setxy(hOut,89,7) ;printf("%d",(timefinal-time0-stoppingtime)/60);setxy(hOut,99,3);printf("%d",speedlevel);for(i = 1; i < H+1; i++)   yun{   for(j = 1; j < L+1; j++)  if(GameMap[i][j]=='#'||GameMap[i][j]=='-'||GameMap[i][j]=='_'||GameMap[i][j]=='|'||GameMap[i][j]=='*'||GameMap[i][j]=='@'||GameMap[i][j]=='!'||GameMap[i+1][j]=='#'&&GameMap[i-1][j]!='#'&&GameMap[i][j+1]!='#'&&GameMap[i][j-1]!='#'||GameMap[i-1][j]=='#'&&GameMap[i+1][j]!='#'&&GameMap[i][j+1]!='#'&&GameMap[i][j-1]!='#'||GameMap[i][j+1]=='#'&&GameMap[i-1][j]!='#'&&GameMap[i+1][j]!='#'&&GameMap[i][j-1]!='#'||GameMap[i][j-1]=='#'&&GameMap[i+1][j]!='#'&&GameMap[i-1][j]!='#'&&GameMap[i][j+1]!='#'||GameMap[i][j]==' '&&GameMap[i+1][j]=='@'&&GameMap[i+2][j]!='#'||GameMap[i][j]==' '&&GameMap[i-1][j]=='@'&&GameMap[i-2][j]!='#'||GameMap[i][j]==' '&&GameMap[i][j-1]=='@'&&GameMap[i][j-2]!='#'||GameMap[i][j]==' '&&GameMap[i][j+1]=='@'&&GameMap[i][j+2]!='#'){//此处仅为判断是否是蛇尾之后的那个空格,如果是则刷新 setxy(hOut,j+ix,i+iy);if(GameMap[i][j]=='@'||GameMap[i][j]=='#')printf("%c",GameMap[i][j]);else printf("%c",GameMap[i][j]);}printf("\n");  } if(leveltime>=60&&speedlevel!=3){speedlevel++;leveltime=0;leveltime0+=60;}  }
}

请看show()贪吃蛇核心代码,当你看到中间那么长一段if语句判断,并且想骂博主没脑子就对了,这里实在是脑残之举,不过写完之后就不想改了,反正运行不出问题
一开始是通过全局变量speedlevel设置速度,由于字符的高比宽大很多,于是我给蛇在上下运动时速度放慢一倍
然后设置初始时间
由于为了保证游戏的流畅性,在刷新地图时我只刷新蛇和食物,因为每零点几秒输出那么多东西者的很卡,不信你删掉那个那么长if语句改用system(“cls”);保证很卡,尤其在游戏界面还是蛮大而且蛇的速度又快的情况下
那条if语句实际上就是在判断该空格是否在蛇尾的后面一格,是则刷新,这样保证蛇在输出时没有留下轨迹

中间我牺牲了一点刷新时间,在每次刷新的时候刷新当前分数,速度与时间,我个人认为这点字符每次刷新影响不了太多流畅性

之后你会发现我用了move()函数和Button(),分别是用来控制蛇,和等待下一步指令
一下给出代码

void Button()  //取出按键,并判断方向
{  if(kbhit() != 0) //检查当前是否有键盘输入,若有则返回一个非0值,否则返回0  {   while(kbhit() != 0)  //可能存在多个按键,要全部取完,以最后一个为主  key = getch(); //将按键从控制台中取出并保存到key中  switch(key)  {   //左  case 75:  if(Snake[0].now!=1)Snake[0].now = 0;  break;  //右  case 77:  if(Snake[0].now!=0)Snake[0].now = 1;       break;  //上  case 72:  if(Snake[0].now!=3)Snake[0].now = 2;  break;  //下  case 80:  if(Snake[0].now!=2)Snake[0].now = 3;  break;  case 27: over=1;break;case 32: int stoptime0=time(0);while(getch()!=32){Sleep(200);}stoppingtime+=time(0)-stoptime0;break;}  }
}

这里不懂的同学看注释,最后两个case分别是esc退出游戏和space暂停游戏并记录暂停用的时间,保证在最后算时间时不会加错

void Move()   //蛇的移动
{  int i, x, y;  int t = sum;  //保存当前蛇的长度  //记录当前蛇头的位置,并设置为空,蛇头先移动  x = Snake[0].x;  y = Snake[0].y;  GameMap[x][y] = ' ';  Snake[0].x = Snake[0].x + dx[ Snake[0].now ];  Snake[0].y = Snake[0].y + dy[ Snake[0].now ];  Check_Border();   //蛇头是否越界  Check_Head(x, y);  //蛇头移动后的位置情况,参数为: 蛇头的开始位置  if(sum == t)  //未吃到食物即蛇身移动哦  for(i = 1; i < sum; i++)  //要从蛇尾节点向前移动哦,前一个节点作为参照  {  if(i == 1)   //尾节点设置为空再移动  GameMap[ Snake[i].x ][ Snake[i].y ] = ' ';  if(i == sum-1)  //为蛇头后面的蛇身节点,特殊处理  {  Snake[i].x = x;  Snake[i].y = y;  Snake[i].now = Snake[0].now;  }  else   //其他蛇身即走到前一个蛇身位置  {  Snake[i].x = Snake[i+1].x;  Snake[i].y = Snake[i+1].y;  Snake[i].now = Snake[i+1].now;  }  GameMap[ Snake[i].x ][ Snake[i].y ] = '#'; //移动后要置为'#'蛇身   }
}

Move()其实才是这个贪吃蛇的核心,主要控制蛇的当前方向和位置,原理很简单看注释都能看懂

接下来是用来判断蛇是否越界和返回蛇头状态的两个函数

void Check_Border()  //检查蛇头是否越界
{  if(Snake[0].x < 1 || Snake[0].x >= H+2  || Snake[0].y < 1 || Snake[0].y >= L+2)  over = 1;
}

这个不需要我讲

void Check_Head(int x, int y)  //检查蛇头移动后的位置情况
{  if(GameMap[ Snake[0].x ][ Snake[0].y ] == ' ')  //为空  GameMap[ Snake[0].x ][ Snake[0].y ] = '@';  else if(GameMap[ Snake[0].x ][ Snake[0].y ] == '*')  //为食物  {  GameMap[ Snake[0].x ][ Snake[0].y ] = '@';    Snake[sum].x = x;   //新增加的蛇身为蛇头后面的那个  Snake[sum].y = y;  Snake[sum].now = Snake[0].now;  GameMap[ Snake[sum].x ][ Snake[sum].y ] = '#';   sum+=speedlevel;  Create_Food();  //食物吃完了马上再产生一个食物  } else if(GameMap[ Snake[0].x ][ Snake[0].y ] == '!')  //为食物2  {  Create_Food();GameMap[ Snake[0].x ][ Snake[0].y ] = '@';    Snake[sum].x = x;   //新增加的蛇身为蛇头后面的那个  Snake[sum].y = y;  Snake[sum].now = Snake[0].now;  GameMap[ Snake[sum].x ][ Snake[sum].y ] = '#';   sum+=speedlevel;  extrascore+=speedlevel; //食物吃完了马上再产生一个食物  }   else over = 1;
}

这里我设置的是两种食物,*是一分乘以当前速度等级,!是两分成以当前速度等级,有兴趣的同学可以自己添加新道具

最后补上生成食物函数

void Create_Food()  //在地图上随机产生食物
{  int fx, fy,foodlevel,x; while(1)  {  foodlevel = rand()%10;fx = rand()%H+1;  fy = rand()%L+1;  if(GameMap[fx][fy] == ' ')  //不能出现在蛇所占有的位置  {   if(foodlevel>=3){GameMap[fx][fy] = Sfood;  break;}else {GameMap[fx][fy] = Sfood2;  break;}  } }
}

注意生成食物一定记得判断不能跟已有食物和蛇重叠,否则又bug

到此为止, 代码部分讲解完毕
下面为了方便新手嫖代码,给出一次性完整版

#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <windows.h>
#include <conio.h>
#include <time.h>
#include <cstdio>
#include <bits/stdc++.h>
const int H =25;   //地图的高
const int L = 80;  //地图的长
int ifinitial = 1;
char GameMap[H+2][L+2];   //游戏地图
int time0;//初始时间
int timefinal;//结束时间
int  key;  //按键保存
int  sum = 1, over = 0, speed=0, stoppingtime=0, speedlevel=0;  //蛇的长度, 游戏结束(自吃或碰墙)
int  extrascore = 0;
int  dx[4] = {0, 0, -1, 1};  //左、右、上、下的方向
int  dy[4] = {-1, 1, 0, 0};
int flagOfyn=0;
struct Snake   //蛇的每个节点的数据类型
{  int x, y;  //左边位置  int now;   //保存当前节点的方向, 0,1,2,3分别为左右上下
}Snake[H*L];
const int ix=2,iy=2;
const char Shead = '@';  //蛇头
const char Sbody = '#';  //蛇身
const char Sfood = '*';  //食物
const char Snode = ' ';  //' '在地图上标示为空
const char Sfood2 = '!';  //2分食物
int Home();
void Initial();  //地图的初始化
void Create_Food(); //在地图上随机产生食物
void Show();   //刷新显示地图
void Button();  //取出按键,并判断方向
void Move();   //蛇的移动
void Check_Border();  //检查蛇头是否越界
void Check_Head(int x, int y);   //检查蛇头移动后的位置情况
void drawFrame(COORD a, COORD  b, char row, char col);//画框
void drawFrame(int x1, int y1, int x2, int y2, char row, char col);
void HideCursor();//隐藏光标
void drawRow(int y, int x1, int x2, char ch);
void drawCol(int y, int x1, int x2, char ch);
void setxy(HANDLE hOut,int x,int y);  //设置光标位置
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);//定义显示器句柄变量
int main()
{  HideCursor();
X: speedlevel=Home();Initial();  Show();if(flagOfyn==89||flagOfyn==121) goto X; else if(flagOfyn==78||flagOfyn==110){printf("/n/n/n");system("pause");}return 0;
}
int Home(){system("cls");system("color 2E");HideCursor();
/*  drawFrame(0, 0, 48, 24, '=', '|');//    draw map frame;  drawFrame(49, 0, 79, 4, '-', '|');//        draw output frame  drawFrame(49, 4, 79, 9, '-', '|');//        draw score frame  drawFrame(49, 9, 79, 20, '-', '|');//   draw operate frame  drawFrame(49, 20, 79, 24, '-', '|');//  draw other message frame*/ setxy(hOut,50, 1);  printf("Snakes eating game");  drawRow(3, 0, 119, '-');  drawRow(5, 0, 119, '-');  setxy(hOut,48, 4);  printf("up and down and enter");  setxy(hOut,35, 10);  printf("1. level:low");  setxy(hOut,35, 12);  printf("2. level:middle");setxy(hOut,35, 14);  printf("3. level:high"); drawRow(20, 0, 119, '-');  drawRow(22, 0, 119, '-');  setxy(hOut,67, 11);  printf("low level:");  setxy(hOut,71, 13);  printf("low speed");  setxy(hOut,44, 21);  printf("制作人:Platonic hacker");  int j=10;  setxy(hOut,32, j);  printf(">>");  //drawFrame(45, 9, 79, 17, '=', '|');  while(1)  {   if( _kbhit() )  {     char x=_getch();  switch (x)  {  case 72 :  {     if( j == 14)  {  setxy(hOut,32, j);  printf(" ");  j = 12;  setxy(hOut,32, j);  printf(">>");  setxy(hOut,71, 13);  printf("            ");  setxy(hOut,67, 11);  printf("              ");setxy(hOut,67, 11);  printf("middle level:");  setxy(hOut,71, 13);  printf("middle speed");  break;}  else if( j == 12)  {  setxy(hOut,32, j);  printf(" ");  j = 10;  setxy(hOut,32, j);  printf(">>");  setxy(hOut,71, 13);  printf("            ");  setxy(hOut,67, 11);  printf("              ");setxy(hOut,67, 11);  printf("low level:");  setxy(hOut,71, 13);  printf("low speed"); break; }  else break;}case 80 :  {     if( j == 10 )  {  setxy(hOut,32, j);  printf(" ");          j = 12;  setxy(hOut,32, j);  printf(">>");  setxy(hOut,71, 13);  printf("              ");  setxy(hOut,67, 11);  printf("              ");setxy(hOut,67, 11);  printf("middle level:");  setxy(hOut,71, 13);  printf("middle speed");  break;}  else if( j == 12 )  {  setxy(hOut,32, j);  printf(" ");          j = 14;  setxy(hOut,32, j);  printf(">>");  setxy(hOut,71, 13);  printf("              ");setxy(hOut,67, 11);  printf("              ");  setxy(hOut,67, 11);  printf("high level:");  setxy(hOut,71, 13);  printf("high speed");break;  }  else break;}  case 13 :  {     if (j == 10) return 1; else if(j==12) return 2; else return 3;  }  }  }  }
}void Initial()  //地图的初始化
{  stoppingtime=0;ifinitial=1;//时间每次初始system("cls");sum = 1, over = 0, extrascore = 0;int i, j;  int hx, hy;  system("title Gluttonous Snake");  //控制台的标题  memset(GameMap, ' ', sizeof(GameMap));  //初始化地图全部为空' ' for (i=0;i<H+2;i++){GameMap[i][0]='|';GameMap[i][L+1]='|';}for (j=0;j<L+2;j++){GameMap[0][j]='_';GameMap[H+1][j]='-';}srand(time(0));   //随机种子  hx = rand()%H+1;    //产生蛇头  hy = rand()%L+1;  GameMap[hx][hy] = Shead;  Snake[0].x = hx;  Snake[0].y = hy;  Snake[0].now = -1;  for (int i=0;i<25;i++){    //随机产生25个食物Create_Food();}                for(i = 0; i < H+2; i++)   //地图显示  {   for(j = 0; j < L+2; j++)  if(GameMap[i][j]!=' '){ setxy(hOut,j+ix,i+iy) ;printf("%c", GameMap[i][j]);} printf("\n");  }  drawRow(2,84,113,'_');drawRow(9,84,113,'-');drawRow(28,84,113,'-');drawCol(113,3,27,'|')  ;setxy(hOut,85,3);printf("speedlevel is %d",speedlevel);setxy(hOut,85,4);printf("your score is 0");setxy(hOut,85,5);printf("the time you have survived:");setxy(hOut,89,7);printf("0  minutes 0  seconds");setxy(hOut,85,10);printf("Made by Thomas"); setxy(hOut,85,12); printf("click any direction button");setxy(hOut,85,13); printf("to start the game");getch();   //先接受一个按键,使蛇开始往该方向走  Button();  //取出按键,并判断方向
}
void Create_Food()  //在地图上随机产生食物
{  int fx, fy,foodlevel,x; while(1)  {  foodlevel = rand()%10;fx = rand()%H+1;  fy = rand()%L+1;  if(GameMap[fx][fy] == ' ')  //不能出现在蛇所占有的位置  {   if(foodlevel>=3){GameMap[fx][fy] = Sfood;  break;}else {GameMap[fx][fy] = Sfood2;  break;}  } }
}
void Show()  //刷新显示地图
{  int i=0, j=0,speed=0;flagOfyn=0;if(speedlevel==1) speed=100;//设置速度 else if(speedlevel==2)speed=50;else if(speedlevel==3) speed=10;if(ifinitial == 1){ifinitial = 0;time0=time(0);//设置初始时间 }int ifchange=0;int leveltime=0;int leveltime0=time0;while(1)  {   leveltime=time(0)-leveltime0;if(speedlevel==3){if(Snake[0].now==2||Snake[0].now==3)speed=20;else if(Snake[0].now==0||Snake[0].now==1)speed=10;}else if(speedlevel==2){if(Snake[0].now==2||Snake[0].now==3)speed=100;else if(Snake[0].now==0||Snake[0].now==1)speed=50;}else if(speedlevel==1){if(Snake[0].now==2||Snake[0].now==3)speed=200;else if(Snake[0].now==0||Snake[0].now==1)speed=100;}Sleep(speed); //延迟半秒(1000为1s),即每speed秒刷新一次地图  Button();   //先判断按键在移动  Move();  int score=sum+extrascore-1;timefinal=time(0);if(over)  //自吃或碰墙即游戏结束  {   system("cls");drawFrame(33,7,83,20,'=','|');setxy(hOut,54,9);printf("Game Over");setxy(hOut,52,12);printf("Your score:%d",score);setxy(hOut,43,16);printf(" Do you want to play again(y/n)");setxy(hOut,37,18);printf("the time you survive: %d minutes %d seconds",(timefinal-time0-stoppingtime)/60,(timefinal-time0-stoppingtime)%60);while(flagOfyn!=89&&flagOfyn!=121&&flagOfyn!=78&&flagOfyn!=110)flagOfyn=getch(); break;  }setxy(hOut,99,4) ;printf("%d",score);setxy(hOut,100,7) ;printf("  ");setxy(hOut,100,7) ;printf("%d",(timefinal-time0-stoppingtime)%60);setxy(hOut,89,7) ;printf("%d",(timefinal-time0-stoppingtime)/60);setxy(hOut,99,3);printf("%d",speedlevel);for(i = 1; i < H+1; i++)   {   for(j = 1; j < L+1; j++)  if(GameMap[i][j]=='#'||GameMap[i][j]=='-'||GameMap[i][j]=='_'||GameMap[i][j]=='|'||GameMap[i][j]=='*'||GameMap[i][j]=='@'||GameMap[i][j]=='!'||GameMap[i+1][j]=='#'&&GameMap[i-1][j]!='#'&&GameMap[i][j+1]!='#'&&GameMap[i][j-1]!='#'||GameMap[i-1][j]=='#'&&GameMap[i+1][j]!='#'&&GameMap[i][j+1]!='#'&&GameMap[i][j-1]!='#'||GameMap[i][j+1]=='#'&&GameMap[i-1][j]!='#'&&GameMap[i+1][j]!='#'&&GameMap[i][j-1]!='#'||GameMap[i][j-1]=='#'&&GameMap[i+1][j]!='#'&&GameMap[i-1][j]!='#'&&GameMap[i][j+1]!='#'||GameMap[i][j]==' '&&GameMap[i+1][j]=='@'&&GameMap[i+2][j]!='#'||GameMap[i][j]==' '&&GameMap[i-1][j]=='@'&&GameMap[i-2][j]!='#'||GameMap[i][j]==' '&&GameMap[i][j-1]=='@'&&GameMap[i][j-2]!='#'||GameMap[i][j]==' '&&GameMap[i][j+1]=='@'&&GameMap[i][j+2]!='#'){//此处仅为判断是否是蛇尾之后的那个空格,如果是则刷新 setxy(hOut,j+ix,i+iy);if(GameMap[i][j]=='@'||GameMap[i][j]=='#')printf("%c",GameMap[i][j]);else printf("%c",GameMap[i][j]);}printf("\n");  } if(leveltime>=60&&speedlevel!=3){speedlevel++;leveltime=0;leveltime0+=60;}  }
}
void Button()  //取出按键,并判断方向
{  if(kbhit() != 0) //检查当前是否有键盘输入,若有则返回一个非0值,否则返回0  {   while(kbhit() != 0)  //可能存在多个按键,要全部取完,以最后一个为主  key = getch(); //将按键从控制台中取出并保存到key中  switch(key)  {   //左  case 75:  if(Snake[0].now!=1)Snake[0].now = 0;  break;  //右  case 77:  if(Snake[0].now!=0)Snake[0].now = 1;       break;  //上  case 72:  if(Snake[0].now!=3)Snake[0].now = 2;  break;  //下  case 80:  if(Snake[0].now!=2)Snake[0].now = 3;  break;  case 27: over=1;break;case 32: int stoptime0=time(0);while(getch()!=32){Sleep(200);}stoppingtime+=time(0)-stoptime0;break;}  }
}
void Move()   //蛇的移动
{  int i, x, y;  int t = sum;  //保存当前蛇的长度  //记录当前蛇头的位置,并设置为空,蛇头先移动  x = Snake[0].x;  y = Snake[0].y;  GameMap[x][y] = ' ';  Snake[0].x = Snake[0].x + dx[ Snake[0].now ];  Snake[0].y = Snake[0].y + dy[ Snake[0].now ];  Check_Border();   //蛇头是否越界  Check_Head(x, y);  //蛇头移动后的位置情况,参数为: 蛇头的开始位置  if(sum == t)  //未吃到食物即蛇身移动哦  for(i = 1; i < sum; i++)  //要从蛇尾节点向前移动哦,前一个节点作为参照  {  if(i == 1)   //尾节点设置为空再移动  GameMap[ Snake[i].x ][ Snake[i].y ] = ' ';  if(i == sum-1)  //为蛇头后面的蛇身节点,特殊处理  {  Snake[i].x = x;  Snake[i].y = y;  Snake[i].now = Snake[0].now;  }  else   //其他蛇身即走到前一个蛇身位置  {  Snake[i].x = Snake[i+1].x;  Snake[i].y = Snake[i+1].y;  Snake[i].now = Snake[i+1].now;  }  GameMap[ Snake[i].x ][ Snake[i].y ] = '#'; //移动后要置为'#'蛇身   }
}
void Check_Border()  //检查蛇头是否越界
{  if(Snake[0].x < 1 || Snake[0].x >= H+2  || Snake[0].y < 1 || Snake[0].y >= L+2)  over = 1;
}
void Check_Head(int x, int y)  //检查蛇头移动后的位置情况
{  if(GameMap[ Snake[0].x ][ Snake[0].y ] == ' ')  //为空  GameMap[ Snake[0].x ][ Snake[0].y ] = '@';  else if(GameMap[ Snake[0].x ][ Snake[0].y ] == '*')  //为食物  {  GameMap[ Snake[0].x ][ Snake[0].y ] = '@';    Snake[sum].x = x;   //新增加的蛇身为蛇头后面的那个  Snake[sum].y = y;  Snake[sum].now = Snake[0].now;  GameMap[ Snake[sum].x ][ Snake[sum].y ] = '#';   sum+=speedlevel;  Create_Food();  //食物吃完了马上再产生一个食物  } else if(GameMap[ Snake[0].x ][ Snake[0].y ] == '!')  //为食物2  {  Create_Food();GameMap[ Snake[0].x ][ Snake[0].y ] = '@';    Snake[sum].x = x;   //新增加的蛇身为蛇头后面的那个  Snake[sum].y = y;  Snake[sum].now = Snake[0].now;  GameMap[ Snake[sum].x ][ Snake[sum].y ] = '#';   sum+=speedlevel;  extrascore+=speedlevel; //食物吃完了马上再产生一个食物  }   else over = 1;
}
void drawFrame(COORD a, COORD  b, char row, char col)
{  drawRow(a.Y, a.X+1, b.X-1, row);  drawRow(b.Y, a.X+1, b.X-1, row);  drawCol(a.X, a.Y+1, b.Y-1, col);  drawCol(b.X, a.Y+1, b.Y-1, col);
}
void drawFrame(int x1, int y1, int x2, int y2, char row, char col)
{  COORD a={x1, y1};  COORD b={x2, y2};  drawFrame(a, b, row, col);
}
void HideCursor()
{  CONSOLE_CURSOR_INFO cursor_info = {1, 0};   SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
void setxy(HANDLE hOut, int x, int y)
{COORD pos;pos.X = x;            //横坐标pos.Y = y;            //纵坐标SetConsoleCursorPosition(hOut, pos);
}
void drawRow(int y, int x1, int x2, char ch)
{  setxy(hOut,x1,y);  for(int i = 0; i <= (x2-x1); i++)  printf("%c",ch);
}
void drawCol(int x, int y1, int y2, char ch)
{  int y=y1;  while(y!=y2+1)  {  setxy(hOut,x, y);  printf("%c",ch);  y++;  }
}  

最后的最后附上运行过程截图

C语言贪吃蛇,流畅版,可继续升级改造相关推荐

  1. c语言贪吃蛇控制台版

    用c语言写的期末作业 /* {conio.h阻塞式: getch(): 从无回显的控制台获取字符.无缓冲区,只有当按下一个键才会执行后面的程序.非阻塞式: kbhit() 检测缓冲区中是否有字符:执行 ...

  2. C语言贪吃蛇游戏(进阶版)

    一,实验游戏流程图(由结构与数组实现) 1.贪吃蛇游戏思路流程图(自作) 二,实验贪吃蛇全部代码(借鉴+修改) #include <stdio.h> #include <Window ...

  3. C语言贪吃蛇游戏代码,贪吃蛇C语言代码实现大全

    一.C语言贪吃蛇代码实现前言 设计贪吃蛇游戏的主要目的是让大家夯实C语言基础,训练编程思维,培养解决问题的思路,领略多姿多彩的C语言. 贪吃蛇是非常经典的一款游戏,本次我们模拟在控制台实现贪吃蛇游戏, ...

  4. c语言贪吃蛇大作业报告,C语言贪吃蛇实验报告

    C语言贪吃蛇实验报告 C 语言程序设计实训报告姓 名 专 业 班 级 指导教师 二 011 年 7 月 14 日I I目录1 实训目的和要求 11.1 实训目的和任务 11.2 实训要求 12 实训任 ...

  5. C语言贪吃蛇课程设计实验报告(包含贪吃蛇项目源码)

    文末有贪吃蛇代码全览,代码有十分细致的注释!!! 文末有贪吃蛇代码全览,代码有十分细致的注释!!! 文末有贪吃蛇代码全览,代码有十分细致的注释!!! 码文不易,给个免费的小星星和免费的赞吧,关注也行呀 ...

  6. c语言五子棋代码_基于控制台的C语言贪吃蛇

    相信对很多人来说,学完C语言以后,都会找一些小程序来练练手.例如贪吃蛇.五子棋.俄罗斯方块等等. 今天给大家分享一个基于控制台的C语言贪吃蛇小程序. 基础知识要求:C语言基础. 知识点补充 这里写一些 ...

  7. c语言安卓贪吃蛇代码下载,C语言贪吃蛇代码

    c语言编写贪吃蛇源代码,简单易懂,文件为VC源代码.如果你正在学习c语言,就来下载吧.很经典的 C语言贪吃蛇代码部分 #include #include #include#include #defin ...

  8. c语言贪吃蛇游戏编程视频教程,C语言贪吃蛇游戏精典源码 - 视频教程 - VC中文网-VC-MFC编程论坛 - Powered by Discuz!...

    19f700059b660539d5dc (38.08 KB, 下载次数: 0) 2017-11-14 16:28 上传 C语言贪吃蛇游戏精典源码 19f500058fe8fcaf675a (2.98 ...

  9. c语言对抗程序代码,C语言贪吃蛇源程序代码双人对抗

    C语言贪吃蛇源程序代码双人对抗 #include #include #include #include #include #include #include #define LEFT 100 #def ...

最新文章

  1. u盘循环冗余能修复吗_古董修复能修复吗?-恩平 - 商业服务
  2. 技术界与翻译界的交锋:机器翻译离我们还有多远? | 清华AI Time
  3. linear-gradient与radial-gradient
  4. Boost asio学习笔记之二—— 网络编程
  5. android正则判断两个符号之间,Android字母、数字、字符任意两种组合正则验证
  6. linux socket资源耗尽,TCP的socket资源被耗尽的问题
  7. python django 动态网页_Django-手撸简易web框架-实现动态网页-wsgiref初识-jinja2初识-python主流web框架对比-00...
  8. 利用nginx集群式部署服务器中,数据同步问题
  9. 数据库期末总结笔记( 零基础 )-第二章 关系数据库
  10. IDEA 代码格式化插件Save Actions示范
  11. php ZipArchive 压缩整个文件夹 - 自带ZipArchive类 - PHP递归创建目录压缩包
  12. 利用计算机名称共享打印机步骤,如何连接共享打印机汇总教程
  13. Android 前置摄像头强制关闭镜像预览
  14. 毫末追击智能驾驶1000天,对战蔚小理将现胜负手
  15. govendor使用及错误处理
  16. 神舟战神Z8-CA5NP,RTX3060怎么样?测评值得买吗?详细性能点评
  17. 使用eagle导出PCB制造商可用的gerber文件
  18. Tomcat绑定IPV4端口
  19. pd 生成mysql 脚本_powerdesigner 生成数据库脚本
  20. 第一阶 01 初识Java 安装Eclipse运行及推荐软件

热门文章

  1. opencv学习—简单车牌识别操作(python)
  2. 【制作数字人】零门槛通过三维重建技术生成个人三维模型
  3. divi模板下载_WordPress主题Divi 2.4进行了改进和新功能
  4. 山东省高等学校计算机等级考试真题,2013山东省计算机等级考试二级试题及答案...
  5. 大数据就业生就业信息分析可视化
  6. 常识——手机改直供电+usb调试
  7. 环形链表(python实现)
  8. windows无法安装到所选位置,请检查你的介质 0x80300024
  9. Laravel 常用包汇总
  10. 一个中间继电器引发的损失