我用大一上学期学习完了C语言,用的是《C语言程序设计》,谭浩强老师出版的第五版。学习完这本书后,我又通过假期继续深造学习了C++,总想利用所学做一款经典游戏,今天我花了一下午的时间,整理出来了这篇文章,希望对你编写这个程序也会有所帮助。(本博文里面的代码均没涉及easyx图形库)
/* 这一次文章中会出现两个程序,第一个程序注重讲解,里面的注释非常多,几乎一句话后面跟着一个。
第二个程序是我重新整理,又加工的,注释也去除的差不多了,运行的效果挺不错的,建议你可以运行一下看看 */
# include
# include //我们需要Windows的API,这个是Windows编程的内容,需要用到句柄的知识(这一段代码是后面的gotoxy()中的),我们可以借助百度直接把这段函数复制过来
# include //控制台函数库 后面的_kbhit函数和_getch函数都会用到它
# include
# 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
# include
# include
# include
# 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;
}
}
以上两个程序就是全部的内容了,有对程序任何的问题都可在下方评论。
小靴子写这篇文章不易,望各路大佬给个赞,给小靴子一点点安慰…………
下面上传的图片是截取的第二个程序的,优点是光标离开了蛇。