刚刚把C语言基础学完,就想动手做下写个控制台的贪吃蛇。
//head头文件
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <memory.h>
#include <windows.h>
#include <time.h>
#include <stdbool.h>
#include "Snake.h"
#include "map.h"
char ch;//用于保存输入的字符,蛇的移动方向
//蛇的一些相关函数和全局变量的头文件(Snake.h)
#pragma once
typedef struct list
{
//数据域
int x;//数组的x
int y;//数组的y
struct list *next;//指针域
}List;
typedef struct snake
{
List *phead;//头节点,为了方便插入蛇头
List *ptail;//尾节点,为了方便删除蛇尾
}Snake;
BOOL init(Snake **sHead);//初始化
BOOL insert(Snake *sHead, int x, int y);//插入
BOOL deleteSnake(Snake *sHead);//删除尾节点
void setNewSnake(int changeDirection_X, int changeDirection_Y);//重新绘制蛇
void SnackMove();//蛇的移动
void show(Snake *sHead);//显示
void changSnake();//改变蛇的形状
void deathSnake(int new_X,int new_Y);//判断蛇是否死亡
void setReward();//设置奖励
BOOL riseSnake(int new_X,int new_Y);//增长蛇身
int one ;//控制奖励的个数
Snake *mySnake;//蛇
//地图的显示和初始化头文件(map.h)
#include <windows.h>
#define X_MAX 25//数组大小
#define Y_MAX 55
int g_Map[X_MAX][Y_MAX];//地图
void buildMap();//初始化边界
void showMap();//显示地图
void showNum();//显示地图上的数字
void gotoxy(HANDLE hOut, int x, int y);//重置光标位置
//地图的源文件(map.c)
#include "head.h"
//1:墙和蛇身
//0:可行
//2:蛇头
void buildMap()
{
for (int i = 0; i < Y_MAX;i++)
{
g_Map[0][i] = 1;//第一排设置为墙
g_Map[X_MAX - 1][i] = 1;//最后一排设置为墙
}
for (int i = 0; i < X_MAX; i++)
{
g_Map[i][Y_MAX - 1] = 1;//最后一列设置为墙
g_Map[i][0] = 1;//第一列设置为墙
}
}
void showNum()//显示地图上的数字
{
for (int i = 0; i < X_MAX; i++)
{
for (int j = 0; j < Y_MAX; j++)
{
printf("%d ", g_Map[i][j]);
}
printf("\n");
}
}
void gotoxy(HANDLE hOut, int x, int y)
{
COORD pos;
pos.X = x;//横坐标
pos.Y = y;//纵坐标
SetConsoleCursorPosition(hOut, pos);
}
void showMap()
{
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);//定义显示器句柄变量
for (int i = 0; i < X_MAX;i++)
{
for (int j = 0; j < Y_MAX;j++)
{
gotoxy(hOut, j*2, i);
if (g_Map[i][j]==1)
{
printf("%s", "□");
}
else if (g_Map[i][j] == 2)
{
printf("%s", "○");
}
else
{
printf("%s", " ");
}
}
printf("\n");
}
Sleep(100);
if (one>50)//控制奖励存在的时间
{
one = 0;
}
else
{
one++;
}
}
//蛇的源文件(Snake.c)
#pragma once
#include "head.h"
BOOL init(Snake **sHead)
{
if ((*sHead) ==NULL)
{
(*sHead) = (Snake*)calloc(1, sizeof(Snake));//给蛇分配内存
if ((*sHead)==NULL)
{
printf("分配内存失败\n");
return 0;
}
else
{
return 1;
}
}
else
{
return 0;
}
}
BOOL insert(Snake *sHead, int x, int y)
{
if (sHead ==NULL)//没有分配内存
{
printf("蛇没有分配内存\n");
return 0;
}
List *p = calloc(1, sizeof(List));
if (p==NULL)
{
printf("蛇身分配失败\n");
return 0;
}
p->x = x;
p->y = y;
p->next = NULL;
if (sHead->phead == NULL)
{
sHead->phead = p;//赋值蛇头
sHead->ptail = p;//设置蛇尾
return 1;
}
else
{
p->next = sHead->phead;
sHead->phead = p;
return 1;
}
return 0;
}
BOOL deleteSnake(Snake *sHead)//删除尾节点
{
if (sHead==NULL )
{
return 0;
}
else
{
List *pold = sHead->phead;
List *pnew = pold;
while (pold->next!=NULL)
{
pnew = pold;
pold = pold->next;
}
free(pold);
pold = NULL;
pnew->next = NULL;
sHead->ptail = pnew;//重新设置蛇尾
return 1;
}
}
void show(Snake *sHead)//显示
{
List *p = sHead->phead;
while (p)
{
printf("%d,%d\n", p->x, p->y);
p = p->next;
}
}
BOOL riseSnake(int new_X,int new_Y)//增长蛇身
{
if (g_Map[new_X][new_Y]==2)
{
return 1;
}
else
{
return 0;
}
}
void setNewSnake(int changeDirection_X, int changeDirection_Y)
{
g_Map[mySnake->phead->x][mySnake->phead->y] = 1;//将当前蛇头位置设为蛇身
int new_X = mySnake->phead->x + changeDirection_X;//新蛇头的坐标
int new_Y = mySnake->phead->y + changeDirection_Y;//新蛇头的坐标
deathSnake(new_X, new_Y);
if (!riseSnake(new_X, new_Y))//没有奖励才要删除蛇身,否则不用
{
g_Map[mySnake->ptail->x][mySnake->ptail->y] = 0;//将当前蛇尾位置清零
deleteSnake(mySnake);//将蛇尾删除
}
else
{
one = 0;//将奖励设置为0,,重新设置奖励位置
}
insert(mySnake, new_X, new_Y);//将新的位置设置为蛇头
g_Map[mySnake->phead->x][mySnake->phead->y] = 2;//将新蛇头对应地图上的坐标设置
}
void setReward()//设置奖励
{
static int Reward_X=1;//奖励的x轴
static int Reward_Y=1;//奖励的Y轴
if (one==0)
{
time_t ts;
unsigned int num = time(&ts);
srand(num);
g_Map[Reward_X][Reward_Y] = 0;//初始化奖励的值
//(X_MAX - 2)排除最下排的墙壁设置奖励,+1排除最上排的墙壁设置奖励
//(Y_MAX - 2)排除最右列的墙壁设置奖励,+1排除最左列的墙壁设置奖励
while (1)
{
Reward_X = rand() % (X_MAX - 2) + 1;
Reward_Y = rand() % (Y_MAX - 2) + 1;
if (g_Map[Reward_X][Reward_Y]==0)//设置奖励不是蛇身或则墙壁
{
g_Map[Reward_X][Reward_Y] = 2;
break;
}
}
}
}
void judgeHaul(char oldch)//判断是否要改变方向
{
if (oldch == 'w' || oldch == 'W')//向上移动
{
if (ch=='s' || ch=='S')
{
ch = oldch;//保持原来的方向
}
}
else if (oldch == 's' || oldch == 'S')//向下移动
{
if (ch == 'w' || ch == 'W')
{
ch = oldch;//保持原来的方向
}
}
else if (oldch == 'a' || oldch == 'A')//向左移动
{
if (ch == 'd' || ch == 'D')
{
ch = oldch;//保持原来的方向
}
}
else if (oldch == 'd' || oldch == 'D')//向右移动
{
if (ch == 'a' || ch == 'A')
{
ch = oldch;//保持原来的方向
}
}
}
void deathSnake(int new_X, int new_Y)//判断蛇是否死亡
{
if (g_Map[new_X][new_Y]==1)//碰到自身或墙壁死亡
{
system("cls");
for (int i = 0; i < 15;i++)
{
printf("\r\n");
}
for (int i = 0; i < 40; i++)
{
printf("%c",' ');
}
printf("Sorry Game Over\r\n");
Sleep(3000);
exit(0);
}
}
void changSnake()//改变蛇的形状
{
int changeDirection_X = 0;//改变的方向x
int changeDirection_Y = 0;//改变的方向y
if (ch == 'w' || ch == 'W')//向上移动
{
changeDirection_X = -1;
}
else if (ch == 's' || ch == 'S')//向下移动
{
changeDirection_X = 1;
}
else if (ch == 'a' || ch == 'A')//向左移动
{
changeDirection_Y = -1;
}
else if (ch == 'd' || ch == 'D')//向右移动
{
changeDirection_Y = 1;
}
setNewSnake(changeDirection_X, changeDirection_Y);
if (kbhit())//获取键盘输入流
{
char oldch = ch;//保存旧值,因为需要判断
ch = getch();
judgeHaul(oldch);
}
}
void SnackMove()//蛇的移动
{
while (true)
{
setReward();
//system("cls");//刷新屏幕
showMap();//显示地图
changSnake();//改变蛇的位置
}
}
//主函数
#include "head.h"
void Help()
{
printf("按数字1:开始游戏\n");
printf("按数字2:游戏操作\n");
printf("按数字0:退出游戏\n");
}
void GameStart()
{
mySnake = NULL;
init(&mySnake);//初始化蛇
insert(mySnake, X_MAX / 2, Y_MAX / 2 - 2);//给蛇身初始化两个位置
g_Map[X_MAX / 2][Y_MAX / 2 - 2] = 1;
insert(mySnake, X_MAX / 2, Y_MAX / 2 - 1);
g_Map[X_MAX / 2][Y_MAX / 2 - 1]=1;
insert(mySnake, X_MAX / 2, Y_MAX / 2 );//初始化蛇头的位置
g_Map[X_MAX / 2][Y_MAX / 2 ]=2;//在蛇头对应位置上赋值
ch = 'd';//初始化移动方向
buildMap();
system("cls");
}
int main()
{
Help();
int num = 0;
while (1)
{
scanf("%d", &num);
switch (num)
{
case 1:
{
GameStart();
SnackMove();
}
break;
case 0:
printf("将要关闭游戏\n");
Sleep(3000);
return ;
case 2:
printf("上:w,下:s,左:a,右:d\n");
default:
Help();
break;
}
}
return 0;
}
运行: