我编写出的第一个C++的小游戏——贪吃蛇

我用大一上学期学习完了C语言,用的是《C语言程序设计》,谭浩强老师出版的第五版。学习完这本书后,我又通过假期继续深造学习了C++,总想利用所学做一款经典游戏,今天我花了一下午的时间,整理出来了这篇文章,希望对你编写这个程序也会有所帮助。(本博文里面的代码均没涉及easyx图形库)

/* 这一次文章中会出现两个程序,第一个程序注重讲解,里面的注释非常多,几乎一句话后面跟着一个。
第二个程序是我重新整理,又加工的,注释也去除的差不多了,运行的效果挺不错的,建议你可以运行一下看看 */

# include <iostream>
# include <Windows.h> //我们需要Windows的API,这个是Windows编程的内容,需要用到句柄的知识(这一段代码是后面的gotoxy()中的),我们可以借助百度直接把这段函数复制过来
# include <conio.h>     //控制台函数库   后面的_kbhit函数和_getch函数都会用到它
# include <ctime> 
# define MAPHEIGHT 60 //地图的长度
# define MAPWIDTH 20 //地图的宽度
# define SNAKESIZE 25 //定义一个蛇的最大长度,在后面用途不大
using namespace std;
//  食物的结构体
struct
{
 int x;
 int y;
}food;  //食物的结构体属性有:食物的xy坐标
//  蛇的结构体
struct
{
 int x[SNAKESIZE]; //蛇头的坐标
 int y[SNAKESIZE];
 int len = 3;  //蛇的长度
}snake;
//   函数的声明区
void printmap();  //打印地图
void creatfood();  //食物产生的一个函数
void gotoxy(int x,int y); //辅助函数:光标的移动
void printsnake(); //打印蛇的函数
void keycontrol();  //按键控制函数
void Score(); //计分函数
int Judge(); //判断函数
//   全局变量区
int key = 'a';  //默认蛇一开始的移动方向是向左走的
static int score = 0;  //我们用静态变量目的是实现分数的累加。
int changeFlag = 0;   //判断方向键是否按下的标志,会出现在我们的keycontrol函数中进行使用
int main(void)
{
 printmap();
 creatfood();
 printsnake();
 while(1)
 {
  if (!Judge())  //如果达到了判断函数的条件实行后直接结束程序
   return 0;
  keycontrol();
  Sleep(300);   //我们可以通过调节Sleep中的数字来改变蛇移动的速度
  Score();   
 }
 return 0;
}
void printmap()
{
 for (int i = 0; i <= MAPHEIGHT; i+=2)
 {
  gotoxy(i,0);
  cout << "■";
 }
 for (int i = 0; i <= MAPHEIGHT; i+=2)
 {
  gotoxy(i, MAPWIDTH);
  cout << "■";
 }
 for (int i = 0; i <= MAPWIDTH;i++)
 {
  gotoxy(0,i);
  cout << "■";
 }
 for (int i = 0; i <= MAPWIDTH; i++)
 {
  gotoxy(MAPHEIGHT, i);
  cout << "■";
 }
}
void creatfood()
{
 srand((unsigned int)time(NULL));
 while (1)
 {
  food.x = rand() % (MAPHEIGHT - 4) + 2;  //因为我们的第一列边框占了两个字节,因此要减去
  food.y = rand() % (MAPWIDTH - 2) + 1; //原因同上,只不过上下行的间距只是一个字节 
  if (food.x % 2 == 0)   //因为我们的蛇头的x方向上占用的是两个字节,因此必须要求食物刷新的位置在x的方向上是偶数
   break;
 }
 gotoxy(food.x, food.y);  //光标移动,打印食物
 cout << "☆";

}
void printsnake()
{
 if (snake.len == 3)       //因为只有一开始调用该函数时,我们才打印蛇头。
 {
  snake.x[0] = MAPHEIGHT / 2;    //蛇头默认出现位置在地图的中间位置
  snake.y[0] = MAPWIDTH / 2;
  gotoxy(snake.x[0], snake.y[0]);
  cout << "■";    //以上的操作目的是为了打印蛇头
 }
 //打印蛇身
 for (static int k = 1; k < snake.len; k++)  //把k定义成static int的格式是让k记住它上次使用后的值,防止二次调用的时候,k的值又从1开始
 {
  snake.x[k] = snake.x[k - 1] + 2;
  snake.y[k] = snake.y[k - 1];
  gotoxy(snake.x[k],snake.y[k]);
  cout << "■";
 }
}
void keycontrol()
{
 if (snake.x[0] == food.x && snake.y[0] == food.y)
 {
  score += 10;
  snake.len++;
  printsnake();
  creatfood();
 }
 if (_kbhit())
 {
  //有按键就进行接收
  fflush(stdin);
  key = _getch();
 }
 if (!changeFlag)
 {
  gotoxy(snake.x[snake.len -1],snake.y[snake.len -1]);
  cout << "  ";  //擦除蛇尾最后一节
 }
 for (int i = snake.len ; i > 0; i--)
 {
  snake.x[i] = snake.x[i - 1];
  snake.y[i] = snake.y[i - 1];
 }
 switch (key)
 {
 case 'w':
 case 'W':
  snake.y[0]--;
  break;
 case 'a':
 case 'A':
  snake.x[0]-=2;
  break;
 case 's':
 case 'S':
  snake.y[0]++;
  break;
 case 'd':
 case 'D':
  snake.x[0]+=2;
  break;
 }
 gotoxy(snake.x[0],snake.y[0]);
 cout << "■";
 changeFlag = 0;
 gotoxy(100,10000);
}
void gotoxy(int x,int y)
{
 //1.找到控制台这个窗口
 HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
 //2.光标的结构体
 COORD coord;
 //3.设置坐标
 coord.X = x;
 coord.Y = y;
 //4.同步到控制台SETCONSOLECURSORPORSITION
 SetConsoleCursorPosition(handle, coord);
}
void Score()
{
 gotoxy(30,10);
 cout << "得分:" << score;
}
int Judge()
{
 if (snake.x[0] == 0 || snake.x[0] == MAPHEIGHT || snake.y[0] == 0 || snake.y[0] == MAPWIDTH)
 {
  system("cls");
  Sleep(1000);
  gotoxy(MAPHEIGHT / 2, MAPWIDTH / 2);
  cout << "Sorry!you failed!" << endl;
  Sleep(1000);
  system("cls");
  gotoxy(MAPHEIGHT / 2, MAPWIDTH / 2);
  cout << "Game Over!" << endl;
  return 0;
 }
 if (score >= 150)
 {
  system("cls");
  Sleep(1000);
  gotoxy(MAPHEIGHT / 2, MAPWIDTH / 2);
  cout << "You win!!!" << endl;
  Sleep(1000);
  return 0;
 }
}




以上的内容就是我们的第一个程序,(呜呜呜……可能是我电脑的原因,这是我第一次写博客,我沾代码段,想一下子全粘贴上,结果就是老出现问题,耗费了半个多小时一小段一小段粘的,如果你有什么问题,私聊我解决即可)下面的程序则是我的重制版程序,运行的效果挺不错的,建议尝试一下~

# include <iostream>
# include <windows.h>
# include <conio.h>
# include <ctime>
# define MAPLONG 60  //定义地图的长度
# define MAPWIDTH 20 //定义地图的宽度
# define SNAKESIZE 18 //定义好蛇的存储
struct
{
 //☆
 int x;
 int y;
}food;
struct
{
 //■
 int x[SNAKESIZE];
 int y[SNAKESIZE];
 int len = 3;
}snake;
全局变量
int key = 'a';
int game_speed = 500;
int score = 0;
封面设计
void Cover_design();
函数的声明
//1.辅助函数
void gotoxy(int x, int y);
//2.绘制地图的函数
void print_MAP();
//3.产生食物的函数
void creat_food();
//4.打印蛇的函数
void print_snake();
//5.按键设置函数
void set_control();
//6.判断函数
int Judge();
//7.得分函数
void Score();
using namespace std;
int main(void)
{
 Cover_design();
 system("cls");
 print_MAP();
 creat_food();
 print_snake();
 while (1)
 {
  Score();
  Sleep(game_speed);
  set_control();
  if (!Judge())
  {
   Sleep(5000);
   system("pause");
   return 0;
  }
 }
 system("pause");
 return 0;
}
//绘制地图的函数
void print_MAP()
{
 //先打印出左右的两个边框(i,0)和(i,MAPLONG)
 for (int i = 0; i <= MAPWIDTH; i++)
 {
  gotoxy(0,i);
  cout << "■";
 }
 for (int i = 0; i <= MAPWIDTH; i++)
 {
  gotoxy(MAPLONG,i);
  cout << "■";
 }
 for (int i = 0; i <= MAPLONG; i+=2)
 {
  gotoxy(i,0);
  cout << "■";
 }for (int i = 0; i <= MAPLONG; i+=2)
 {
  gotoxy(i,MAPWIDTH);
  cout << "■";
 }
}
//产生食物的函数
void creat_food()
{
 srand((unsigned int)time(NULL));
 while (1)
 {
  food.x = rand() % MAPLONG;
  food.y = rand() % MAPWIDTH;
  if (food.x % 2 == 0 && food.x != 0 && food.x != MAPWIDTH && food.y != 0 && food.y != MAPLONG)
   break;
 }
 gotoxy(food.x,food.y);
 cout << "☆";
}
//打印蛇的函数
void print_snake()
{
 //打印蛇头
 if (snake.len == 3)
 {
  snake.x[0] = MAPLONG / 2;
  snake.y[0] = MAPWIDTH / 2;
  gotoxy(snake.x[0],snake.y[0]);
  cout << "■"; 
 }
 //打印蛇身
 for (static int k = 1; k < snake.len; k++)
 {
  snake.x[k] = snake.x[k - 1] + 2;
  snake.y[k] = snake.y[k - 1];
  gotoxy(snake.x[k],snake.y[k]);
  cout << "■";
 }
}
//按键设置函数
void set_control()
{
 //如果头碰到食物,还会产生一个新食物
 if (snake.x[0] == food.x  &&  snake.y[0] == food.y)
 {
  score += 10;
  snake.len++;
  creat_food();
 }
 if (_kbhit())
 {
  //有按键就进行接收
  fflush(stdin);
  key = _getch();
 }
 gotoxy(snake.x[snake.len - 1], snake.y[snake.len - 1]);
 cout << "  ";  //擦除蛇尾最后一节
 for (int i = snake.len; i > 0; i--)
 {
  snake.x[i] = snake.x[i - 1];
  snake.y[i] = snake.y[i - 1];
 }
 switch (key)
 {
 case 'w':
 case 'W':
  snake.y[0]--;
  break;
 case 'a':
 case 'A':
  snake.x[0] -= 2;
  break;
 case 's':
 case 'S':
  snake.y[0]++;
  break;
 case 'd':
 case 'D':
  snake.x[0] += 2;
  break;
 }
 gotoxy(snake.x[0], snake.y[0]);
 cout << "■";
}
void gotoxy(int x, int y)
{
 //1.找到控制台这个窗口
 HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
 //2.光标的结构体
 COORD coord;
 //3.设置坐标
 coord.X = x;
 coord.Y = y;
 //4.同步到控制台SETCONSOLECURSORPORSITION
 SetConsoleCursorPosition(handle, coord);
}
//判断函数
int Judge()
{
 if (snake.x[0] == 0 || snake.y[0] == 0 || snake.x[0] == MAPLONG || snake.y[0] == MAPWIDTH)
 {
  system("cls");
  Sleep(1000);
  gotoxy(MAPLONG / 2, MAPWIDTH / 2);
  cout << "Sorry!You filled!" << endl;
  gotoxy((MAPLONG / 2)+3, (MAPWIDTH / 2) + 1);
  cout << "Game Over!!!" << endl;
  Sleep(1000);
  return 0;
 }
 if (score >= 100)
 {
  system("cls");
  Sleep(1000);
  gotoxy(MAPLONG / 2, MAPWIDTH / 2);
  cout << "You Win!!!" << endl;
  Sleep(1000);
  return 0;
 }
}
void Score()
{
 gotoxy((MAPLONG) + 8, (MAPWIDTH / 2)- 8);
 cout << "得分:"<<score;
 gotoxy((MAPLONG)+5, (MAPWIDTH));
 cout << "加油!";
}
封面设计
void Cover_design()
{
 cout << "A.快速" << endl;
 cout << "B.中速" << endl;
 cout << "C.慢速" << endl;
 char select;
 cin >> select;
 switch (select)
 {
 case 'A':
  game_speed = 100;
  break;
 case 'B':
  game_speed = 300;
  break;
 case 'C':
  game_speed = 500;
  break;
 }
}


以上两个程序就是全部的内容了,有对程序任何的问题都可在下方评论。
小靴子写这篇文章不易,望各路大佬给个赞,给小靴子一点点安慰…………
下面上传的图片是截取的第二个程序的,优点是光标离开了蛇。在这里插入图片描述开始界面,可以调制蛇移动的速度
吃到星星会变长
当分数达到100分,游戏结束!

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值