找回密码
 立即注册
查看: 86621|回复: 525

[技术交流] C++控制台贪吃蛇源代码(初学者版)

 火.. [复制链接]
 楼主| 发表于 2020-6-26 21:37:29 来自手机 | 显示全部楼层
本帖最后由 jhanker 于 2026-10-23 06:54 编辑

C++语言贪吃蛇源代码
     没有版权问题欢迎随时修改,适合初学者

下面是源代码及下载链接
  1. /*
  2. C++贪吃蛇游戏,zjlj,2015.3.16
  3. */
  4. #define DEBUG 0 //当程序在调试阶段时 DEBUG为 1
  5. #include<iostream>
  6. #include<windows.h>
  7. #include<time.h>
  8. #include<conio.h>
  9. using namespace std;
  10. void readini(FILE **fphead, int *score, char *argv[]) //创建或打开一个和运行文件对应的ini文件,读取最高纪录
  11. {
  12. char filename[200],*pfilename;
  13. int flag=-1,i;
  14.      
  15.     strcpy(filename,argv[0]);
  16.     for(i=0;filename[i]!='\0';i++)
  17. {
  18.   if ('.'==filename[i])flag=1;
  19. }
  20.   
  21. if(1==flag)
  22. {
  23. filename[i-1]='i';
  24.     filename[i-2]='n';
  25. filename[i-3]='i';
  26. }
  27. else
  28. {
  29.   filename[i]='.';
  30. filename[i+1]='i';
  31. filename[i+2]='n';
  32.     filename[i+3]='i';
  33.     filename[i+4]='\0';
  34. }
  35. for(;filename[i]!='\\'&&i>=0;i--)pfilename=&filename[i];
  36.     if ( (*fphead=fopen(pfilename, "rb+"))==NULL)
  37. {
  38.         if ( (*fphead=fopen(pfilename, "wb+"))==NULL)
  39.   {
  40.     printf("无法创建或打开"%s"文件\n",pfilename);
  41.     system("pause");
  42.        exit(0);
  43.   }
  44.     }
  45. else
  46. {
  47.   fread(score,sizeof(int),1,*fphead);
  48. }
  49. }
  50. void writeini(FILE **fphead, int *score, char *argv[])  //打开一个和运行文件对应的ini文件,写入最高纪录
  51. {
  52. char filename[200],*pfilename;
  53. int flag=-1,i;
  54.    
  55.     strcpy(filename,argv[0]);
  56.     for(i=0;filename[i]!='\0';i++)
  57. {
  58.   if ('.'==filename[i])flag=1;
  59. }
  60.   
  61. if(1==flag)
  62. {
  63. filename[i-1]='i';
  64.     filename[i-2]='n';
  65. filename[i-3]='i';
  66. }
  67. else
  68. {
  69.   filename[i]='.';
  70. filename[i+1]='i';
  71. filename[i+2]='n';
  72.     filename[i+3]='i';
  73.     filename[i+4]='\0';
  74. }
  75. for(;filename[i]!='\\'&&i>=0;i--)pfilename=&filename[i];
  76.     if ( (*fphead=fopen(pfilename, "wb+"))==NULL)
  77. {
  78.           printf("无法写入"%s"文件,磁盘写保护!\n",pfilename);
  79.     system("pause");
  80.        exit(0);
  81. }
  82. else
  83. {
  84.   rewind(*fphead);
  85.   fwrite(score,sizeof(int),1,*fphead);
  86.   fclose(*fphead);
  87. }
  88. }
  89. void gotoxy(int x,int y)//光标定位,光标定位函数SetConsoleCursorPosition是左上角位置是0,0然后向左向下延伸
  90. {
  91. COORD pos;
  92. pos.X=2*y;
  93. pos.Y=x;
  94. SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
  95. }
  96. void color(int a)//颜色函数
  97. {
  98. SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),a);
  99. }

  100. void Refresh(int q[][22], int grade, int gamespeed, int length,int score) //  输出贪吃蛇棋盘
  101. {
  102. int i,j;
  103. for(i=0;i<22;i++)
  104. {
  105.   for(j=0;j<22;j++)
  106.   {
  107.    if(q[i][j]==0)//输出棋盘空白
  108.    {
  109.     gotoxy(i,j);
  110.     color(11);
  111.     cout<<"■";
  112.    }
  113.    if(q[i][j]==1||q[i][j]==2)//输出棋盘墙壁
  114.    {  
  115.     gotoxy(i,j);
  116.     color(11);
  117.     cout<<"□";
  118.    }
  119.    if(q[i][j]==3)//输出蛇头
  120.    {  
  121.     gotoxy(i,j);
  122.     color(14);
  123.     cout<<"★";
  124.    }
  125.    if(q[i][j]==4)//输出蛇身
  126.    {  
  127.     gotoxy(i,j);
  128.     color(12);
  129.     cout<<"◆";
  130.    }
  131.      if(q[i][j]==5)//输出果子
  132.    {  
  133.     gotoxy(i,j);
  134.     color(12);
  135.     cout<<"●";
  136.    }
  137.   }
  138.   if(i==0) cout << "\t***********************";
  139.   if(i==1) cout << "\t等级为:" << grade;//显示等级
  140.   if(i==3) cout << "\t自动前进时间";
  141.   if(i==4) cout << "\t间隔为:" << gamespeed << "ms";//显示时间
  142.      if(i==6) cout << "\t历史最高分为:" << score << "分";
  143.   if(i==7) cout << "\t你现在得分为:" << (length+(grade-1)*8)*10 << "分";
  144.   if(i==8) cout << "\t**********************";
  145.      if(i==9) cout << "\t游戏说明:";
  146.      if(i==10) cout << "\t(1)用小键盘方向键控制";
  147.   if(i==11) cout << "\t蛇头运动方向;";
  148.   if(i==12) cout << "\t(2)蛇每吃一个果子蛇身";
  149.   if(i==13) cout << "\t增加一节;";
  150.   if(i==14) cout << "\t(3)蛇咬到自己或碰到墙";
  151.   if(i==15) cout << "\t壁游戏结束。";
  152.   if(i==18) cout << "\t**********************";
  153.      if(i==19) cout << "\tC/C++语言作业:";
  154.      if(i==20) cout << "\tzjlj,2015.03.16 ";
  155. }
  156. }
  157.   
  158. int main(int argc, char *argv[]){
  159.     int tcsQipan[22][22];     //  贪吃蛇棋盘是一个二维数组(如22*22,包括墙壁)
  160.     int i,j,score,directiontemp;
  161. FILE  *fpini;//*fpini 信息文件
  162. readini(&fpini, &score, argv);//读取ini文件的最高纪录
  163. if (score<0)//最高成绩小于零设置为零,初建文件会是负数
  164.   score=0;
  165. while(1)
  166. {
  167.   for(i=1;i<=20;i++)
  168.    for(j=1;j<=20;j++)
  169.     tcsQipan[i][j]=0;    //贪吃蛇棋盘相应坐标标上中间空白部分的标志0
  170.   for(i=0;i<=21;i++)
  171.    tcsQipan[0][i] = tcsQipan[21][i] = 1;      //贪吃蛇棋盘相应坐标标上上下墙壁的标志1
  172.   for(i=1;i<=20;i++)
  173.    tcsQipan[i][0] = tcsQipan[i][21] = 2;      //贪吃蛇棋盘相应坐标标上左右墙壁的标志2
  174.   int tcsZuobiao[2][500];     //蛇的坐标数组
  175.   for(i=0; i<4; i++)
  176.   {
  177.    tcsZuobiao[0][i] = 1;//蛇身和蛇头的x坐标
  178.    tcsZuobiao[1][i] = i + 1;//蛇身和蛇头的y坐标
  179.   }
  180.   int head = 3,tail = 0;//标示蛇头和蛇尾的数组偏移量
  181.   for(i=1;i<=3;i++)
  182.    tcsQipan[1][i]=4;    //蛇身
  183.   tcsQipan[1][4]=3;       //蛇头
  184.   int x1, y1;           // 随机出果子
  185.   srand(time(0));//设置随机种子
  186.   do
  187.   {
  188.    x1=rand()%20+1;
  189.    y1=rand()%20+1;
  190.   }
  191.   while(tcsQipan[x1][y1]!=0);//如果不是在空白处重新出果子
  192.   tcsQipan[x1][y1]=5;//贪吃蛇棋盘相应坐标标上果子的标志5
  193.   color(12);
  194.   cout<<"\n\n\t\t\t\t贪吃蛇游戏即将开始 !"<<endl;//准备开始
  195.   long start,starttemp;
  196.   int grade = 1, length = 4;  //设置初始等级和蛇的初始长度
  197.   int gamespeed = 500;  //设置初始前进时间间隔
  198.   for(i=3;i>=0;i--)
  199.   {
  200.    start=clock();
  201.    while(clock()-start<=1000);
  202.    system("cls");
  203.    if(i>0)
  204.     cout << "\n\n\t\t\t\t进入倒计时:" << i << endl;  //倒计时显示
  205.    else
  206.     Refresh(tcsQipan,grade,gamespeed,length,score);  //初始棋盘显示
  207.   }
  208.   int timeover=1,otherkey=1;//初始化超时时间和按键判断参数
  209.   char direction = 77;  // 设置初始情况下,向右运动
  210.   int x=tcsZuobiao[0][head],y=tcsZuobiao[1][head];//保存蛇头坐标到x,y变量
  211.   while(1)//运行一局游戏
  212.   {
  213.    start = clock();
  214.    while((timeover=((starttemp=clock())-start<=gamespeed))&&!kbhit());//如果有键按下或时间超过自动前进时间间隔则终止循环
  215.    if(direction==72||direction==80||direction==75 ||direction==77)
  216.    directiontemp=direction;//保留上一次方向按键
  217.             //starttemp=gamespeed+start-starttemp;//保留停留时间
  218.    if(timeover)
  219.    {
  220.     #if (DEBUG==1)
  221.     direction = getch();//调试代码
  222.              #else
  223.     if((direction =getch())==-32)
  224.      direction = getch();
  225.        #endif
  226.    }
  227.              #if (DEBUG==1)//调试代码
  228.        start=clock();
  229.     while(clock()-start<=2000);
  230.     gotoxy(24,4);
  231.     cout << "\t按键ASCII代码"<<(int)direction<<"    "<<endl;
  232.              #endif
  233.     if(!(direction==72||direction==80||direction==75 ||direction==77))
  234.     {   
  235.      otherkey=0;//  按键非方向键,otherkey设置为0
  236.     }
  237.     else
  238.     {
  239.      otherkey=1;//  按键为方向键,otherkey设置为1
  240.     }
  241.              if(direction==72 && directiontemp==80)//忽略反方向按键
  242.     {
  243.         direction=32;
  244.      otherkey=0;
  245.                  //start = clock();
  246.         //while(clock()-start<=starttemp);
  247.     }
  248.     else if(direction==80 && directiontemp==72)
  249.    {
  250.         direction=32;//设置按键为非方向键
  251.       otherkey=0;//  按键为非方向键,otherkey设置为0
  252.                 // start = clock();
  253.        //while(clock()-start<=starttemp);//补偿等待时间
  254.     }
  255.     else if(direction==75 && directiontemp==77)
  256.     {
  257.         direction=32;
  258.      otherkey=0;
  259.                  //start = clock();
  260.         //while(clock()-start<=starttemp);
  261.     }
  262.     else if(direction==77 && directiontemp==75)
  263.     {
  264.         direction=32;
  265.      otherkey=0;
  266.                  //start = clock();
  267.         //while(clock()-start<=starttemp);
  268.     }
  269.      
  270.      
  271.     switch(direction)//判断方向键
  272.     {
  273.      case 72: x= tcsZuobiao[0][head]-1; y= tcsZuobiao[1][head];break;      // 向上
  274.      case 80: x= tcsZuobiao[0][head]+1; y= tcsZuobiao[1][head];break;      // 向下
  275.      case 75: x= tcsZuobiao[0][head]; y= tcsZuobiao[1][head]-1;break;      // 向左
  276.      case 77: x= tcsZuobiao[0][head]; y= tcsZuobiao[1][head]+1;break;      // 向右
  277.      default: break;
  278.     }
  279.    
  280.   
  281.     if(x==0 || x==21 ||y==0 || y==21)      // 蛇头碰到墙壁,结束本局游戏
  282.     {  
  283.      gotoxy(22,12);
  284.      cout << "\t游戏已结束!" << endl;
  285.      if(score>=(length+(grade-1)*8)*10)//判断是否破记录
  286.      {
  287.       gotoxy(10,7);
  288.       color(12);
  289.       cout << "闯关失败 加油耶!" << endl;
  290.       fclose(fpini);//关闭ini文件
  291.      }
  292.      else
  293.      {
  294.       gotoxy(10,7);
  295.       color(12);
  296.       cout << "恭喜您打破记录" << endl;
  297.       score=(length+(grade-1)*8)*10;
  298.       writeini(&fpini, &score, argv);//写入ini文件的最高纪录
  299.      }
  300.      gotoxy(23,12);
  301.         cout << "按回车键重新开始,按ESC退出游戏" << endl;//显示的提示
  302.      break;//退出该局游戏
  303.     }
  304.     if(tcsQipan[x][y]!=0&&!(x==x1&&y==y1)&&tcsQipan[x][y]!=3) //   蛇头碰到蛇身,结束本局游戏
  305.     {
  306.      gotoxy(22,12);
  307.      cout << "\t游戏已结束!" << endl;
  308.      if(score>=(length+(grade-1)*8)*10)//判断是否破记录
  309.      {
  310.       gotoxy(10,7);
  311.       color(12);
  312.       cout << "闯关失败 加油耶!" << endl;
  313.       fclose(fpini);//关闭ini文件
  314.      }
  315.      else
  316.      {
  317.       gotoxy(10,7);
  318.       color(12);
  319.       cout << "恭喜您打破记录" << endl;
  320.       score=(length+(grade-1)*8)*10;
  321.       writeini(&fpini, &score, argv);//写入ini文件的最高纪录
  322.      }
  323.      gotoxy(23,12);
  324.      cout << "按回车键重新开始,按ESC退出游戏" << endl;//显示的提示
  325.      break;//退出该局游戏
  326.     }
  327.     /*
  328.     游戏运行时的核心算法开始
  329.     */
  330.     if(x==x1 && y==y1) //  吃果子,长度加1
  331.     {   
  332.      length ++;
  333.      if(length>=8)//长度大于等于8重新计算长度,等级加1
  334.      {
  335.       length -= 8;//重新计算长度
  336.       grade ++;//等级加1
  337.       if(gamespeed>50)//控制最快速度为50
  338.        gamespeed = 550 - grade * 50; // 改变自动前进时间间隔
  339.      }
  340.      tcsQipan[x][y]= 3;//贪吃蛇棋盘相应坐标现在蛇头标志改为蛇头标志3
  341.      tcsQipan[tcsZuobiao[0][head]][tcsZuobiao[1][head]] = 4;//贪吃蛇棋盘相应坐标原来蛇头标志改为蛇身标志4
  342.      head = (head+1)%400;//防止数组越界
  343.      tcsZuobiao[0][head] = x;//蛇头的x坐标
  344.      tcsZuobiao[1][head] = y;//蛇头的y坐标
  345.      do//随机出果子
  346.      {
  347.       x1=rand()%20+1;
  348.       y1=rand()%20+1;
  349.      }
  350.      while(tcsQipan[x1][y1]!=0);//如果不是在空白处重新出果子
  351.      tcsQipan[x1][y1]=5;//贪吃蛇棋盘相应坐标标上果子的标志5
  352.      gotoxy(22,12);
  353.      cout << "\t游戏进行中!" << endl;
  354.      Refresh(tcsQipan,grade,gamespeed,length,score);
  355.     }
  356.     else  //  不吃果子
  357.     {  
  358.      if(otherkey)
  359.      {
  360.       tcsQipan [tcsZuobiao[0][tail]][tcsZuobiao[1][tail]]=0;
  361.       tail=(tail+1)%400;//防止数组越界
  362.       tcsQipan [tcsZuobiao[0][head]][tcsZuobiao[1][head]]=4;
  363.       head=(head+1)%400;//防止数组越界
  364.       tcsZuobiao[0][head]=x;//蛇头的x坐标
  365.       tcsZuobiao[1][head]=y;//蛇头的y坐标
  366.       tcsQipan[tcsZuobiao[0][head]][tcsZuobiao[1][head]]=3;
  367.       gotoxy(22,12);
  368.       cout << "\t游戏进行中!" << endl;
  369.       Refresh(tcsQipan,grade,gamespeed,length,score);
  370.      }
  371.      else
  372.      {
  373.       gotoxy(22,12);
  374.       cout << "\t游戏暂停中!" << endl;
  375.      }
  376.     }
  377.     /*
  378.     游戏运行时的核心算法结束
  379.     */
  380.        }
  381.     while(1)
  382.     {
  383.      while(!kbhit());
  384.      if((direction =getch())==13)//按回车键开始下一局
  385.       break;
  386.      if(direction ==27)//按ESC退出游戏
  387.       exit(0);
  388.     }
  389.        system("cls");//清除屏幕重新开始
  390. }
  391. return 0;
  392. }
复制代码

下载链接

运行效果图

运行效果图
小甲鱼最新课程 -> https://ilovefishc.com
回复 顶 5 踩 1

使用道具 举报

 楼主| 发表于 2020-7-1 11:46:31 | 显示全部楼层
上传了运行效果图,看看是不是符合您的需求
小甲鱼最新课程 -> https://ilovefishc.com
回复 顶 踩

使用道具 举报

发表于 2020-7-1 15:42:43 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2020-7-1 17:59:11 | 显示全部楼层
答案
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2020-7-1 18:01:39 | 显示全部楼层
答案
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2020-7-1 18:16:23 | 显示全部楼层
大佬请受在下一拜
小甲鱼最新课程 -> https://ilovefishc.com
回复 顶 踩

使用道具 举报

发表于 2020-7-1 22:12:16 | 显示全部楼层
答案
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2020-7-2 09:51:40 | 显示全部楼层
。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2020-7-3 13:30:15 | 显示全部楼层
LH魔王 发表于 2020-7-1 18:16
大佬请受在下一拜

不敢当,不敢当
小甲鱼最新课程 -> https://ilovefishc.com
回复 顶 踩

使用道具 举报

发表于 2020-7-5 11:56:59 | 显示全部楼层
我也看看
小甲鱼最新课程 -> https://ilovefishc.com
回复 顶 踩

使用道具 举报

发表于 2020-7-5 17:52:29 来自手机 | 显示全部楼层
可以看看源代码吗
小甲鱼最新课程 -> https://ilovefishc.com
回复 顶 踩

使用道具 举报

发表于 2020-7-5 17:53:15 来自手机 | 显示全部楼层
谢谢~
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2020-7-5 18:34:16 来自手机 | 显示全部楼层
来看看。。。。。
小甲鱼最新课程 -> https://ilovefishc.com
回复 顶 踩

使用道具 举报

发表于 2020-7-6 10:16:38 | 显示全部楼层
看看。。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2020-7-6 10:54:31 | 显示全部楼层
回复
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2020-7-6 13:05:10 | 显示全部楼层
看看
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2020-7-7 14:24:23 | 显示全部楼层
peng12 发表于 2020-7-5 17:52
可以看看源代码吗

回复了就有源代码了
小甲鱼最新课程 -> https://ilovefishc.com
回复 顶 踩

使用道具 举报

发表于 2020-7-7 15:09:22 | 显示全部楼层
来学习
小甲鱼最新课程 -> https://ilovefishc.com
回复 顶 踩

使用道具 举报

发表于 2020-7-7 15:44:34 | 显示全部楼层
不晓得
小甲鱼最新课程 -> https://ilovefishc.com
回复 顶 踩

使用道具 举报

发表于 2020-7-9 16:36:05 | 显示全部楼层
学习学习
小甲鱼最新课程 -> https://ilovefishc.com
回复 顶 踩

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|鱼C工作室 ( 粤ICP备18085999号-1 )

GMT+8, 2026-11-5 16:09

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表