你还在觉得c语言编程很无聊吗?
我们来用c语言编写一个简单的小游戏 贪吃蛇 ,想必大家都玩过吧!
下面完全是个人知道和了解的相关知识,希望不足的地方有大神可以指出,一起讨论学习!
本人也是初次用c语言做这样的小游戏,这个贪吃蛇是比较简单的,主要用链表完成的
我在看到原版代码的时候也是好多地方不明白,我当时不明白的地方都做了注释,下面的代码是本人自己参考源代码自己写的,经过调试可以正常运行!
为了你看完代码懒得看下面的内容,我把带码里我认为新鲜的东西写在前面:
首先是游戏界面显示时必须的光标定位,代码中为COORD,这是定义在<windows.h>中的一个结构体,其源代码为
typedef struct _COORD
{
SHORT X; //horizontal coordinate水平坐标
SHORT Y; //vertical coordinate 垂直坐标
}COORD;
下面我们引用一段代码:
void Pos(int x, int y) // 光标定位 { COORD pos; HANDLE hOutput; pos.X = x; pos.Y = y; hOutput = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleCursorPosition(hOutput, pos); }
这是一段运用windows api相关知识的代码,所谓API全称是
Application Programming Interface,应用程序编程接口,其实就是一些已经写好的子程序,说白了就是操作系统为程序员提供的一组函数库,程序员可以通过调用api简单的实现一些操作系统提供的已经写好了的功能。我们来说一下我们的代码其中,HANDLE hOutput是声明了一个句柄对象,对于句柄的概念和功能大家自行google.hOutput = GetStdHandle(STD_OUTPUT_HANDLE); 这句的意思是用句柄对象接收一个标准输出设备句柄。标准输出句柄的参数SetConsoleCursorPosition(hOutput, pos); 这句的意思是在标准输出设备hOutput上定位坐标pos然后大家就可以结合下面的代码进一步了解它们在代码中的具体作用啦!第二个本人认为新鲜的东西就是kbhit() 函数名:kbhit() 功 能及返回值: 检查当前是否有键盘输入,若有则返回一个非0值,否则返回0 用 法:int kbhit(void); 包含头文件: include <conio.h>
贪吃蛇源码
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include<conio.h>
#include <time.h>
#include <string.h>
#define Key_Right 'd'//按键向右
#define Key_Left 'a'//按键向组左
#define Key_Up 'w'//按键向上
#define Key_Down 's'//按键向下
#define Key_Space ' '//暂停键 空格
//标记状态量
#define R 1
#define L 2
#define W 3
#define D 4
typedef struct node
{
int x;
int y;
struct node *next;
}Snake;//蛇身结构体
//必要的全局变量
Snake *head; //蛇头
Snake *p; //遍历蛇身
int score=0; //记录分数
int food_x, food_y; //食物位置坐标
int Status = R; //初始状态量
int key; //接收字符
int endgamestatus = 0; //判断游戏是否结束的状态量
//
//全局函数声明
void Pos(int x, int y); //光标定位符
void CreatMap();//创建地图
void CreatFood(); //生成食物
void CrossWall(); //蛇头与墙相撞
int BitSelf(); //舌头与自身相撞
void SnakeMoving(); //蛇移动
void Endgame(); //游戏结束
void gamecircle(); //游戏循环
void pause();//游戏暂停
void Pos(int x, int y) // 光标定位符
{
COORD pos;
HANDLE hOutput;
pos.X = x;
pos.Y = y;
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOutput, pos);
}
void CreatMap()//创建地图
{
for(int i = 0; i < 54; ++i)
{
for(int j = 0; j < 26; ++j)
{
Pos(i, 0);
printf("*");
Pos(i, 26);
printf("*");
Pos(0, j);
printf("*");
Pos(54, j);
printf("*");
}
}
}
void CreatFood()
{
srand(time(NULL));
food_x = rand()%50+2;
food_y = rand()%24+2;
Pos(food_x, food_y);
printf("@");
}
void InitSnake()//蛇身初始化
{
Snake *tail; //蛇尾
head = (Snake *)malloc(sizeof(Snake));
head->x = 25;
head->y = 5;
head->next = NULL;
for(int i = 1; i < 4; ++i)
{
tail = (Snake *)malloc(sizeof(Snake));
tail->x = 25 + i*1;
tail->y = 5;
tail->next = head;
head = tail;
}
while(tail)
{
Pos(tail->x, tail->y);
printf("@");
tail = tail->next;
}
}
void CrossWall()//撞墙
{
if(head->x == 0 || head->x == 54 || head->y == 0 || head->y == 26)
{
endgamestatus = 1;
Endgame();
}
}
int BitSelf()//撞到自己身体
{
p = head->next;
while(p)
{
if(p->x == head->x && p->y == head->y)
{
return 1;
}
p = p->next;
}
return 0;
}
void SnakeMoving()
{
Snake *newhead;
newhead = (Snake *)malloc(sizeof(Snake));
CrossWall();
if(BitSelf())
{
endgamestatus = 2;
Endgame();
}
if(Status == R)
{
if(head->x == food_x && head->y == food_y)
{
score += 10;
newhead->x = head->x+1;
newhead->y = head->y;
newhead->next = head;
head = newhead;
p = head;
while(p)
{
Pos(p->x, p->y);
printf("@");
p = p->next;
}
CreatFood();
}
else
{
newhead->x = head->x+1;
newhead->y = head->y;
newhead->next = head;
head = newhead;
p = head;
while(p->next->next)
{
Pos(p->x,p->y);
printf("@");
p=p->next;
}
Pos(p->next->x, p->next->y);
printf(" ");
free(p->next);
p->next=NULL;
}
}
if(Status == L)
{
if(head->x == food_x && head->y == food_y)
{
score += 10;
newhead->x = head->x-1;
newhead->y = head->y;
newhead->next = head;
head = newhead;
p = head;
while(p)
{
Pos(p->x, p->y);
printf("@");
p = p->next;
}
CreatFood();
}
else
{
newhead->x = head->x-1;
newhead->y = head->y;
newhead->next = head;
head = newhead;
p = head;
while(p->next->next)
{
Pos(p->x,p->y);
printf("@");
p=p->next;
}
Pos(p->next->x,p->next-> y);
printf(" ");
free(p->next);
p->next=NULL;
}
}
if(Status == W)
{
if(head->x == food_x && head->y == food_y)
{
score += 10;
newhead->x = head->x;
newhead->y = head->y-1;
newhead->next = head;
head = newhead;
p = head;
while(p)
{
Pos(p->x, p->y);
printf("@");
p = p->next;
}
CreatFood();
}
else
{
newhead->x = head->x;
newhead->y = head->y-1;
newhead->next = head;
head = newhead;
p = head;
while(p->next->next)
{
Pos(p->x,p->y);
printf("@");
p=p->next;
}
Pos(p->next->x,p->next-> y);
printf(" ");
free(p->next);
p->next=NULL;
}
}
if(Status == D)
{
if(head->x == food_x && head->y == food_y)
{
score += 10;
newhead->x = head->x+1;
newhead->y = head->y;
newhead->next = head;
head = newhead;
p = head;
while(p)
{
Pos(p->x, p->y);
printf("@");
p = p->next;
}
CreatFood();
}
else
{
newhead->x = head->x;
newhead->y = head->y+1;
newhead->next = head;
head = newhead;
p = head;
while(p->next->next)
{
Pos(p->x,p->y);
printf("@");
p=p->next;
}
Pos(p->next->x, p->next->y);
printf(" ");
free(p->next);
p->next=NULL;
}
}
}
void Endgame()
{
system("cls");
Pos(13,13);
if(endgamestatus == 1)
printf("撞墙啦!");
if(endgamestatus == 2)
printf("撞到自己啦!");
Pos(13,14);
printf("你的游戏得分为: %d",score);
exit(0);
}
void gamecircle()
{
Pos(57,4);
printf("操作说明");
Pos(57,5);
printf("w a s d分别对应上 左 下 右 ");
Pos(57,6);
printf("按空格键暂停");
while(1)
{
Pos(57,7);
printf("游戏分数:%d",score);
if(kbhit())
key=getch();
switch(key)
{
case Key_Right:
if(Status!=L)
Status=R;
break;
case Key_Left:
if(Status!=R)
Status=L;
break;
case Key_Up:
if(Status!=D)
Status=W;
break;
case Key_Down:
if(Status!=W)
Status=D;
break;
case Key_Space:
pause();
break;
default:
break;
}
Sleep(300);
SnakeMoving();
}
}
void Welcome()
{
Pos(27,13);
printf("欢迎来到贪吃蛇游戏");
system("pause");
system("cls");
/* Pos(50,9);
printf("欢迎大家对源代码进行修改");
Pos(50,11);
printf("开发出更多好玩的玩法");*/
Pos(50,12);
system("pause");
system("cls");
}
void pause()//暂停
{
while(1)
{
if((key=getchar()) == ' ')
break;
}
}
int main()
{
Welcome();
CreatMap();
CreatFood();
InitSnake();
gamecircle();
return 0;
}
void Pos(int x, int y) // 光标定位符
{
COORD pos;
HANDLE hOutput;
pos.X = x;
pos.Y = y;
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOutput, pos);
}