贪吃蛇(c语言)

简介: 贪吃蛇(c语言)

贪吃蛇

#include <stdio.h>
#include <time.h>
#include <windows.h>
#include <stdlib.h>
#include <conio.h> 
#define U 1
#define D 2
#define L 3
#define R 4
void file_out(); 
void tips();
void printscore();
void createfood();
/***********************
@func: 蛇的每个节点 
***********************/
typedef struct snake{
  int x;
  int y;
  struct snake * next;
}snake;
/***********************
@func: 食物的位置信息
***********************/ 
typedef struct foodtype{
  int x;
  int y;
}foodtype;
int       score = 0;      // 总得分 
int       add   = 10;     // 每次增加的分数
int       HighScore = 0;  // 最高分
int       status=R;       // 蛇前进的状态
int       sleeptime = 150;// 每次运行的时间间隔,控制速度 
snake     * head;         // 蛇头
foodtype  * food;         // 食物
snake     * q;            // 遍历蛇时使用的指针
int       gameover=0;  // 游戏结束的状态, 撞墙, 咬到自己,主动退出游戏
HANDLE    hOut;           // 控制台句柄 
/* 黑色 0   深蓝 1   深绿 2    深蓝绿 3   深红 4    紫 5     暗绿 6     
   白 7     灰 8     亮蓝 9    亮绿 10    亮蓝绿 11  红12    粉   13
   黄 14    亮白 15 
*/
/*******************
@func:设置控制台的颜色 
@param bg: 背景色
@param fg: 前景色 
*******************/
void color(unsigned char bg, unsigned char fg){
  WORD wColor = ((bg & 0x0F)<<4 + (fg & 0x0F)); 
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),wColor);
} 
/************************
@func: 设置文字颜色 
************************/
void textcolor(char fg){
  // 恢复原有颜色 
  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED |
                  FOREGROUND_GREEN |
                  FOREGROUND_BLUE);   
  SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),fg);
} 
/*******************
@func:设置光标的位置 
@param x
@param y
*******************/
void gotoxy(int x,int y){
  COORD c;
  c.X = x;
  c.Y = y;
  SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),c);
}
/*******************
@func:不显示控制台光标 
*******************/
void close_cur(){
  hOut=GetStdHandle(STD_OUTPUT_HANDLE);  //获得输出句柄 
  CONSOLE_CURSOR_INFO CursorInfo;
  GetConsoleCursorInfo(hOut,&CursorInfo);//获取控制台光标信息
  CursorInfo.bVisible=0;                 //隐藏控制台光标
  SetConsoleCursorInfo(hOut,&CursorInfo);//设置控制台光标状态
}
/*******************
@func: 创建游戏地图 
0 2            56 (58 59)  // 每个块的w: 2个字符,h: 一个字符 
1
25
(26) 
*******************/
void createmap(){
  int i,j;
  color(5,0);// 深紫色边框 
  gotoxy(0,0);
  for(i =0;i<60;i++) printf(" "); //绘制上边框
  gotoxy(0,26);
  for(i =0;i<60;i++) printf(" "); //绘制下边框
  for(i = 1;i<26;i++) {           //绘制左右边框 
    gotoxy(0,i);
    printf("  ");
    gotoxy(58,i);
    printf("  ");
  }
  color(3,0);
  for(i=2;i<57;i+=2){     //x : 2 4 6 ... 56 
    for(j=1;j<26;j++){  //y : 1 2 3 ... 25
      gotoxy(i,j);
      printf("  ");
    } 
  }
  tips();
} 
/**************************
@func: 游戏界面右侧的得分和小提示 
**************************/ 
void tips(){
  gotoxy(70,4);
  textcolor(11);
  printf("最高记录: %d", HighScore);
  textcolor(13);
  gotoxy(75,11);
  printf("小提示");
  gotoxy(62,13);
  textcolor(6);
  printf("++------------------------------++");
  gotoxy(62,25);
  printf("++------------------------------++");
  textcolor(3);
  gotoxy(66,14);
  printf("每个食物的得分: %d分",add);
  gotoxy(66,16);
  printf("不能撞墙,不能咬到自己");
  gotoxy(66,18);
  printf("用 ↑↓← →分别控制移动");
  gotoxy(66,20);
  printf("F1: 加速   F2: 减速");
  gotoxy(66,22);
  printf("space: 暂停游戏");
  gotoxy(66,24);
  printf("esc:   退出游戏"); 
  printscore();
} 
/*******************
@func: 绘制得分
*******************/
void printscore(){
  gotoxy(72,6);
  textcolor(14);
  printf("得分: %d",score);
}
/********************
@func: 从save.txt中读取最高分 
********************/
void file_out(){
  FILE*fp;
  fp = fopen("save.txt","a+");
  fscanf(fp,"%d",&HighScore);
  fclose(fp);  
} 
/****************************
@func: 初始化蛇, 蛇的尾部坐标为: 24,5 
****************************/ 
void initsnake(){
  snake * tail;
  int i;
  tail = (snake*)malloc(sizeof(snake)); // 动态内存分配
  tail->x = 24;
  tail->y = 5;
  tail->next = NULL; 
  for(i = 1;i<=4;i++){
    head = (snake*)malloc(sizeof(snake));
    head->next = tail;
    head->x = 24+2*i;
    head->y = 5;
    tail = head;
  } 
  while(tail!=NULL){
    gotoxy(tail->x, tail->y);
    color(14,0);
    printf("  ");
    tail=tail->next;
  }
  createfood();
}
/***************
@func: 随机出现食物
1. 食物不能和蛇身重合 
2. 食物的x值坐标要为 偶数
3. 食物要在边界内 
***************/
void createfood(){
  int ifok=0,x=0,y=0;
  while(!ifok){
    x= (rand()%28+1)*2;  // 为偶数 
    y= rand()%25 + 1  ; 
    q= head;
    while(q->next!=NULL){
      if(q->x==x && q->y ==y) break;// 判断蛇身是否和食物重合
      q = q->next;
    }
    if(q->next==NULL) ifok=1;
  }
  gotoxy(x,y);
  food->x = x;
  food->y = y;
  color(12,0);
  printf("  ");
} 
/*****************
@func: 判断是否咬到自己  
蛇头的坐标值和蛇身上的任意坐标值重合 
*****************/ 
int biteself(){
  q = head->next; 
  while(q!=NULL){
    if(q->x==head->x && q->y==head->y){
      return 1;
    }
    q= q->next;
  }
  return 0;
}
/**********************
@func: 撞墙的情况 
**********************/
int cantcrosswall(){
  if(head->x <2||head->x>56|| head->y<1||head->y>25){
    return 1;  
  }
  return 0;
} 
/**************
@func: 蛇加速前进
两种情况蛇会加速前进: 蛇吃到食物 和按<F1>键
加速时时 间间隔减少10 得分加2 
***************/
void speedup(){
  if(sleeptime>=50){
    sleeptime= sleeptime-10;
    add = add+2;
  }
} 
/*****************
@func: <F2> 蛇减速前进
时间间隔 加 10 , 得分值 比之间减少 2分
得分值 最少为 1
*****************/ 
void speeddown(){
  if(sleeptime<200){
    sleeptime += 10;
    add -= 2;
    if(add<1)  add = 1;
  }
}
/***********************
@func: 吃到了食物,移动后最后一块不擦除 
***********************/
void eatfood(snake*head){
  while(head!=NULL){
    gotoxy(head->x, head->y);
    color(14,0);
    printf("  ");
    head= head->next;
  }
  score += add;
  speedup();
  createfood();
}
/**************************
@func: 没有吃到食物,移动后最后一块要擦除 
**************************/ 
void donteatfood(snake*head){
  while(head->next->next!=NULL){ 
    gotoxy(head->x,head->y);
    color(14,0);
    printf("  ");
    head= head->next;
  }
  //擦除最后一块 
  gotoxy(head->next->x, head->next->y);
  color(3,0);
  printf("  ");
  free(head->next); // 释放原本最后一位的指针
  head->next = NULL; 
} 
/*********************
@func: 控制移动 
**********************/
void snakemove(){
  snake* nexthead;
  nexthead = (snake*)malloc(sizeof(snake));
  nexthead->next = head;
  if(status==U){
    nexthead->x = head->x;
    nexthead->y = head->y-1;
  }else if(status==D){
    nexthead->x = head->x;
    nexthead->y = head->y+1;
  }else if(status==R){
    nexthead->x = head->x+2;
    nexthead->y = head->y;
  }else if(status==L){
    nexthead->x = head->x-2;
    nexthead->y = head->y;
  }
  
    if(nexthead->x == food->x && nexthead->y == food->y){// 下一个位置上有食物 
    eatfood(nexthead);
    printscore(); 
  }
  else{
    donteatfood(nexthead);
  }
  
  head = nexthead;
  
  if(cantcrosswall()){
    gameover = 1;
  }
  
  if(biteself()==1){  // 判断是否咬到自己 
    gameover = 2; 
  }
}
/*********************
@func:键盘按键控制,蛇头不能转向与前进方向相反的方向 
*********************/
void keyboardControl(){ 
  while(!gameover){
    if(GetAsyncKeyState(VK_UP)&0x8000 &&status!=D){
      status = U;
    }
    if(GetAsyncKeyState(VK_DOWN)&0x8000&&status!=U){
      status = D;
    }
    if(GetAsyncKeyState(VK_LEFT)&0x8000&&status!=R){
      status = L;
    }
    if(GetAsyncKeyState(VK_RIGHT)&0x8000&&status!=L){
      status = R;
    }
    if(GetAsyncKeyState(VK_SPACE)&0x8000){
      while(1){
        Sleep(300);
        if(GetAsyncKeyState(VK_SPACE)&0x8000){
          break;
        }
      }
    }
    if(GetAsyncKeyState(VK_ESCAPE)&0x8000){
      gameover = 3;
    }
    if(GetAsyncKeyState(VK_F1)&0x8000){
      speedup();
    }
    if(GetAsyncKeyState(VK_F2)&0x8000){
      speeddown();
    } 
    
    Sleep(sleeptime);
    snakemove();
    
  }
} 
/******************
@func: 存储最高分 
*******************/ 
void file_in(){
  FILE*fp;
  fp = fopen("save.txt","w+");
  fprintf(fp,"%d",score);
  fclose(fp);
}
/**********************
@func: 游戏结束 
**********************/
void endgame(){
  int i,j;
  textcolor(4);
  system("cls");
  gotoxy(30,5);
  for(i=0;i<40;i++) printf("+");
  gotoxy(30,20);  
  for(i=0;i<40;i++) printf("+");
  for(i=6;i<20;i++){
    gotoxy(30,i);
    printf("+");
    gotoxy(69,i);
    printf("+");
  }
  textcolor(15);
  gotoxy(45,8);
  printf("游戏结束!");      
  if(gameover==1){
    gotoxy(43,10);
    printf("您因撞墙而死!!");
  }else{
    gotoxy(41,10);
    printf("您因咬到自己而死!!");
  }
  gotoxy(45,12);
  printf("得分: %d",score); 
  if(score>HighScore){
    gotoxy(42,14);
    printf("您已创新的记录!");
    file_in();
  }else{
    gotoxy(40,14);
    printf("您距离最高记录还差:%d分",HighScore-score);
  }
}
int main(){
  close_cur();
  srand((unsigned int)time(NULL));
  food = (foodtype*)malloc(sizeof(foodtype));
  system("mode con cols=98 lines=27");
  file_out();
  createmap();
  initsnake();
  keyboardControl();
  endgame();
  system("pause >nul");
  return 0;
}
相关文章
|
7月前
|
API 定位技术 C语言
贪吃蛇---C语言---详解
贪吃蛇---C语言---详解
|
7月前
|
存储 定位技术 C语言
【c语言】简单贪吃蛇的实现
【c语言】简单贪吃蛇的实现
|
7月前
|
C语言
C语言之实现贪吃蛇小游戏篇(2)
C语言之实现贪吃蛇小游戏篇(2)
59 1
|
7月前
|
API 定位技术 C语言
C语言项目实战——贪吃蛇
贪吃蛇是久负盛名的游戏,它也和俄罗斯方块,扫雷等游戏位列经典游戏的行列。 在编程语言的学习中,我将以贪吃蛇为例,从设计到代码来展示一个C语言项目实战,进而再一步提升读者对C语言的理解和认知。
192 0
|
3月前
|
定位技术 API C语言
C语言——实现贪吃蛇小游戏
本文介绍了一个基于Windows控制台的贪吃蛇游戏的实现方法。首先,需调整控制台界面以便更好地显示游戏。接着,文章详细描述了如何使用Win32 API函数如`COORD`、`GetStdHandle`、`GetConsoleCursorInfo`等来控制控制台的光标和窗口属性。此外,还介绍了如何利用`GetAsyncKeyState`函数实现键盘监听功能。文中还涉及了`&lt;locale.h&gt;`库的使用,以支持本地化字符显示。
65 1
C语言——实现贪吃蛇小游戏
|
2月前
|
存储 API C语言
【C语言】实践:贪吃蛇小游戏(附源码)(一)
【C语言】实践:贪吃蛇小游戏(附源码)
|
2月前
|
C语言 定位技术 API
【C语言】实践:贪吃蛇小游戏(附源码)(二)
【C语言】实践:贪吃蛇小游戏(附源码)
【C语言】实践:贪吃蛇小游戏(附源码)(二)
|
2月前
|
存储 定位技术 API
C语言项目实战:贪吃蛇
C语言项目实战:贪吃蛇
|
2月前
|
C语言
【C语言】实践:贪吃蛇小游戏(附源码)(三)
【C语言】实践:贪吃蛇小游戏(附源码)
|
2月前
|
C语言
C语言贪吃蛇小游戏来啦!
C语言贪吃蛇小游戏来啦!
34 0