控制台的简单贪吃蛇

刚刚把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;
}


运行:




  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值