利用C/C++实现较完整贪吃蛇游戏
记得在大一时刚学习c/c++语言,学到一半突然想用这门语言做一些小游戏出来,首先想到的便是贪吃蛇。于是本人利用空余时间写出了这么一个简单的小游戏。
由于当时的我还没有能力构造出用户界面,故直接使用dos界面运行。那么问题来了,如何让一个字符在dos界面上自由移动???对于这个问题我采用的解决方案是实现gotoxy函数来控制指针位置从而实现字符的移动。那么我们就先来实现这个函数。
gotoxy 函数并非系统函数,我将其储存于 gotoxy.h 的头文件中方便调用。
gotoxy.h
#include <windows.h> void gotoxy(int x,int y) { COORD pos; pos.X = x - 1; pos.Y = y - 1; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos); }
现在我们已经能够利用 gotoxy 函数对指针进行控制,那么实现字符的移动则只需将原来位置的字符清除,然后利用此函数移动指针到想去的坐标后打印字符即可。
在对此函数进行测试的时候,我发现了一个重要的问题,因为代码是一行一行的运行,那么在等待我输入方向的时候,其他代码是无法执行的,这意味这我的蛇只能是我给一下方向它移动一下,那么该如何使得字符在等待我输出方向的同时自行移动呢???对于这个问题有两个解决方案:一、创建线程(对于当时的我来说线程还很陌生) 二、利用 kbhit() 非阻塞函数(百度一下,你就知道)。当然我选择的是第二个方案,再配合使用 getch() 函数即可完美实现方向的输入。
该游戏的两个难点都解决了,话不多说 ↓
(由于没有涉及什么算法,加之年少,代码显得过于冗长)
这里主要运用到的知识有这些:结构体,srand(), rand(), kbhit(), getch(), Sleep().
/*******************http://blog.csdn.net/lcsy000**********************/ #include<iostream> #include"gotoxy.h" #include<windows.h> #include<conio.h> #include<time.h> using namespace std; char direction_a,direction_b; //方向a、b,用于方向的限制 int scores,num,fool_x,fool_y,speed=100; //得分、num用于蛇身起步、食物x坐标、食物y坐标 bool end; //结束标记 struct node //蛇身结点 { int x,y; node *next; }*head=NULL,*p,*tail; void init(); //初始化开始界面 void start(); //游戏开始入场 void init_snake(); //初始化蛇身 void delete_snake(); //删除蛇身 void control(); //方向控制 void move(); //蛇身移动 void limit(); //方向限制 void panduan(); //配合limit限制方向 void fool(); //食物的出现以及食物被吞 void isEnd(); //结束判断 void zhuangwei(); //撞尾判断 void zhuangqiang(); //撞墙判断 int main () { srand((unsigned)time(NULL)); init(); cin>>direction_a; if(direction_a!='y'&&direction_a!='Y') return 0; do { system("cls"); //清除屏幕 end=false; start(); delete_snake(); init_snake(); scores=0; num=0; fool_x=(rand() % (79-2+1))+ 2; fool_y=(rand() % (22-2+1))+ 2; gotoxy(fool_x,fool_y); cout<<"0"; direction_a=getch(); while(direction_a!='d'&&direction_a!='s'&&direction_a!='w') direction_a=getch(); while(true) { if(num&&direction_a!='d'&&direction_a!='s'&&direction_a!='w'&&direction_a!='a') { direction_a=direction_b; } control(); fool(); Sleep(speed); if(kbhit()) //kbhit 非阻塞函数 { direction_a=getch(); //使用 getch 函数获取键盘输入 limit(); } panduan(); num=1; zhuangqiang(); zhuangwei(); if(end) break; } }while(direction_a=='y'||direction_a=='Y'); return 0; } void init() { gotoxy(35,8); cout<<"★贪 吃 蛇★"; gotoxy(36,10); cout<<"开始请输入y:"; } void start() { for(int i=0;i<=79;i++) { Sleep(10); cout<<"*"; gotoxy(i+1,24); cout<<"*"; gotoxy(i+2,1); } gotoxy(1,2); for(int i=0;i<=21;i++) { Sleep(20); cout<<"*"; for(int j=0;j<=77;j++) cout<<" "; cout<<"*"; } } void init_snake() { int n=3; head=new node; tail=head; head->x=40; head->y=12; while(n--) { p=new node; tail->next=p; p->x=tail->x-1; p->y=tail->y; tail=p; } tail->next=NULL; node *q=head->next; gotoxy(head->x,head->y); cout<<'#'; while(q!=NULL) { gotoxy(q->x,q->y); cout<<'*'; q=q->next; } } void delete_snake() { while(head!=NULL) { node *q=head; head=q->next; delete q; } } void move() { gotoxy(tail->x,tail->y); cout<<" "; gotoxy(head->next->x,head->next->y); cout<<'*'; gotoxy(head->x,head->y); cout<<'#'; node *q=tail; tail=head; while(tail->next!=q) { tail=tail->next; } tail->next=NULL; delete q; } void control() { node *q=new node; q->next=head; q->x=head->x; q->y=head->y; head=q; switch(direction_a) { case 'w': head->y--;break; case 's': head->y++;break; case 'a': head->x--;break; case 'd': head->x++;break; default : break; } move(); } void limit() { if(direction_b=='s'&&direction_a=='w') direction_a='s'; if(direction_b=='w'&&direction_a=='s') direction_a='w'; if(direction_b=='a'&&direction_a=='d') direction_a='a'; if(direction_b=='d'&&direction_a=='a') direction_a='d'; } void panduan() { if(direction_a=='s') direction_b='s'; if(direction_a=='w') direction_b='w'; if(direction_a=='d') direction_b='d'; if(direction_a=='a') direction_b='a'; } void fool() { node *q; if(head->x==fool_x&&head->y==fool_y) { fool_x=(rand() % (79-2+1))+ 2; fool_y=(rand() % (22-2+1))+ 2; gotoxy(fool_x,fool_y); cout<<"0"; num=0; scores++; node *q=new node; q->x=tail->x; q->y=tail->y; tail->next=q; tail=q; tail->next=NULL; } q=head; while(q!=NULL) { if(q->x==fool_x&q->y==fool_y) { fool_x=(rand() % (79-2+1))+ 2; fool_y=(rand() % (22-2+1))+ 2; gotoxy(fool_x,fool_y); cout<<"*"; q=head; continue; } q=q->next; } } void isEnd() { end=true; Sleep(600); system("cls"); gotoxy(35,8); cout<<"您 输 啦 ~"; gotoxy(33,10); cout<<"您的分数为: "<<scores; gotoxy(31,12); cout<<"重新开始请输入y:"; cin>>direction_a; } void zhuangwei() { node *q=head->next; while(q!=NULL) { if(head->x==q->x&&head->y==q->y) { isEnd(); break; } q=q->next; } } void zhuangqiang() { if(head->x==80||head->x==1||head->y==24||head->y==1) isEnd(); }
效果图:
>
由于考虑到游戏的各种 BUG 故自定义函数很多,有兴趣的朋友可以自行改动一些函数对比效果。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持猪先飞。
相关文章
- vector是表示可以改变大小的数组的序列容器,本文主要介绍了C++STL标准库std::vector的使用详解,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2022-03-06
- 这篇文章主要介绍了C++中取余运算的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-23
- 这篇文章主要介绍了C++ string常用截取字符串方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
- 本文通过例子,讲述了C++调用C#的DLL程序的方法,作出了以下总结,下面就让我们一起来学习吧。...2020-06-25
- 本篇文章主要介绍了C++中四种加密算法之AES源代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。...2020-04-25
- 整数拆分,指把一个整数分解成若干个整数的和。本文重点给大家介绍C++ 整数拆分方法详解,非常不错,感兴趣的朋友一起学习吧...2020-04-25
- 这篇文章主要介绍了C++中Sort函数详细解析,sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变...2022-08-18
- 这篇文章主要介绍了C++万能库头文件在vs中的安装步骤(图文),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-23
- 这篇文章主要介绍了C++ bitset用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
- 本篇文章小编并不是为大家讲解string类型的用法,而是讲解我个人比较好奇的问题,就是string 类型占几个字节...2020-04-25
- 这篇文章主要为大家详细介绍了C++ Eigen库计算矩阵特征值及特征向量,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-04-25
- 这篇文章主要介绍了C++ pair的用法实例详解的相关资料,需要的朋友可以参考下...2020-04-25
- 这篇文章主要介绍了VSCode C++多文件编译的简单使用方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-03-29
- 虽然C++11引入了智能指针的,但是开发人员在与内存的斗争问题上并没有解放,如果我门实用不当仍然有内存泄漏问题,其中智能指针的循环引用缺陷是最大的问题。下面通过实例代码给大家介绍c++中的循环引用,一起看看吧...2020-04-25
- 这篇文章主要给大家介绍了关于C++随机点名生成器的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
- map容器是C++ STL中的重要一员,删除map容器中value为指定元素的问题是我们经常与遇到的一个问题,下面这篇文章主要给大家介绍了关于利用C++如何删除map容器中指定值的元素的相关资料,需要的朋友可以参考借鉴,下面来一起看看吧。...2020-04-25
- 这篇文章主要介绍了C++ 约瑟夫环问题案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...2021-08-15
- 这篇文章主要介绍了C++中cin的用法详细,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
- 本篇文章是对C++中的常见编译错误进行了详细的分析介绍,需要的朋友参考下...2020-04-25
- 这篇文章主要介绍了c++优先队列(priority_queue)用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25