|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
- #include <stdio.h>
- #include <windows.h>
- #include <conio.h>
- #include <time.h>
- #define frame_height 25 //边框上下长
- #define frame_width 50 //边框左右宽
- #define UP 'w' //宏定义, 将以下出现的up替换成w
- #define DOWN 's' //同上
- #define WEST 'a' //同上
- #define RIGHT 'd' //同上
- struct Food // 定义一个结构体 确认食物坐标
- {
- int x;
- int y;
- }food;
- struct Snake // 定义一个结构体 用数组的方式储存蛇的每一节身体坐标、身体总长度(节点数量)和速度
- {
- int x[100];
- int y[100];
- int speed;
- int length;
- }snake;
- char ch, tempch; //蛇的方向, 蛇暂时的方向(后面改变蛇的方向会用到)
- int i, temp_x, temp_y, temp_x2, temp_y2, score; //i循环用 ,两个暂时的坐标(后面完成蛇的移动会用到), 得分
- int main(void)
- {
- void screen(void); //定义一个函数,用来打印界面
- void initial_data(void); //定义一个函数,用来初始化蛇的身体和食物的位置
- void update_food(void); //定义一个函数,用来生成一个食物
- void move_snake(void); //定义一个函数,用来移动蛇
- void get_speed(void); //定义一个函数,用来确定蛇移动的速度
- int if_dead(void); //定义一个函数,用来确定游戏是否结束
- void end(void); //定义一个函数,用来打印结束画面
- void gotoxy(int x, int y); //定义一个函数,用来移动光标到屏幕上对应的位置(屏幕看成一个坐标系,左上角为原点,向下为X轴,向右为Y轴)
-
- while(1)
- {
- initial_data(); //初始化蛇的身体和食物的位置 ******这里为我了美观所以先初始化再打印界面(我函数中不完善的地方)*********
- screen(); //打印界面 ******按照逻辑应该先打印界面的(之后定义的函数也有很多不符合逻辑的地方请体谅新手qwq)******
- while(1) //游戏开始
- {
- update_food(); //生成食物
- get_speed(); //获得蛇速度
- move_snake(); // 移动蛇
- Sleep(snake.speed); //Sleep(100),程序暂停100毫秒。
- if(if_dead()) //蛇死亡函数返回1,跳出循环即游戏结束
- {
- break;
- }
- }
- end();
- if(getch()==27) //如果输入ESC退出程序即退出游戏
- {
- break;
- }
- else //输入不为ESC键重新开始游戏
- {
- gotoxy(12, 20); //把光标移动到(12,20)这个点
- printf(" "); //这两句清除屏幕中“游戏结束”4个字和“!”一个字符,一个汉字两个字符所以总共打印9个空格覆盖
- continue;
- }
- }
- return 0;
- }
- void screen(void)
- {
- void gotoxy(int x, int y);
- for(i=0 ; i<=24 ; i++) //打印左右边框
- {
- gotoxy(i, 0);
- printf("+");
- gotoxy(i, frame_width - 1);
- printf("+");
- }
- for(i=1; i<=48 ; i++) //打印上下边框
- {
- gotoxy(0, i);
- printf("+");
- gotoxy(frame_height-1, i);
- printf("+");
- }
- gotoxy(6, 60); //打印右侧的界面
- printf("欢迎来到贪吃蛇(简易版)");
- gotoxy(9, 60);
- printf("当前得分:%d ", score);
- gotoxy(12, 60);
- printf("操作:'W'上,'S'下,'A'左,'D'右");
- gotoxy(15, 60);
- printf("按空格键开始(重新开始)");
- gotoxy(18, 60);
- printf("ESC键退出游戏!");
- if(getch() != ' ') //如果输入不是空格键就进入下面那个循环
- {
- while(1) // 直到输入空格键跳出循环,相当于按空格键开始游戏
- {
- if(getch() == ' ')
- {
- break;
- }
- }
- }
- }
- void initial_data(void)
- {
- void gotoxy(int x, int y);
- void update_food(void);
-
- snake.x[0] = frame_width / 3;
- snake.y[0] = frame_height / 3; //蛇的坐标(X,Y)在(25/3, 50/3)处
- snake.length = 3; //蛇有3节
- ch = RIGHT; //蛇的方向向右;
- for(i=1 ; i<=snake.length ; i++) //从第二节蛇身开始每一节的Y坐标都比蛇头少1,循环输入除了蛇头其余身体节点的坐标
- { //这里循环了3次,按道理身体长度为3时除了蛇头应该只要循环两次
- snake.x[i] = snake.x[i-1]; //所以除了蛇目前身体的坐标确定以外,未来吃到食物的一节身体的坐标也是确定的(目前这节身体还不在)。
- snake.y[i] = snake.y[i-1] - 1;//目前确定的点有snake[0],snake[1],snake[2],snake[3],除了snake[3]以外蛇的身体是确实存在的
- gotoxy(snake.x[i-1], snake.y[i-1]);//所以打印了除了snake[3]的节点 (为了方便就简写成snake[i]的形式了,其实是snake.x[i], snake.y[i],以后出现同理)
- printf("*");//我用的“*”来表示蛇的身体,也可以用其他的字符表示
- }
- food.x = snake.x[0];
- food.y = snake.y[0]; //暂定食物在蛇头位置(这里只是为了初始化食物的数据以方便后面调用update_food函数)
- score = 0;
- update_food();
- }
- void update_food(void)
- {
- void gotoxy(int x, int y);
- if(snake.x[0] == food.x && snake.y[0] == food.y)
- {
- while(1)
- {
- srand(time(NULL)); //srand(),time(),rand()详细说明自行百度,这里的作用就是得到一个随机数
- food.x = rand()%23 + 1; //(rand()%23+1实际上是rand()%(24-1)+1,得到一个范围再[1,24)的随机数)
- food.y = rand()%48 + 1;
- for(i=0 ; i<=snake.length - 1 ; i++)//如果食物的随机位置在蛇身位置重新随机一个食物位置
- {
- if(food.x==snake.x[i] && food.y==snake.y[i])
- {
- break;
- }
- if(i == snake.length - 1)
- {
- i = snake.length;
- }
- }
- if(i == snake.length + 1)//直到食物位置不在蛇身位置退出循环
- {
- break;
- }
- }
- gotoxy(food.x, food.y);//光标移动到食物的位置
- printf("o"); //我用的“o”表示食物,也可以用其他字符表示
- }
- }
- void get_speed(void)
- {
- if(snake.length < 5)
- {
- snake.speed = 300;
- }
- else if(snake.length < 10)
- {
- snake.speed = 250;
- }
- else if(snake.length < 15)
- {
- snake.speed = 200;
- }
- else if(snake.length < 20)
- {
- snake.speed = 150;
- }
- else
- {
- snake.speed = 100;
- }
- }
- void move_snake(void)
- {
- void gotoxy(int x, int y);
- temp_x = snake.x[0];
- temp_y = snake.y[0];//暂时把蛇头snake[0]的坐标保存再temp中
- if(kbhit())//kbhit()详细说明自行百度,这里作用是如果键盘输入了字符就判断为真
- {
- tempch = getch();//读入键盘输入的字符
- if(tempch == 'w' || tempch == 's' || tempch == 'a' || tempch == 'd')
- {
- ch = tempch;
- }
- }
- switch(ch)//只移动蛇头,并不是移动整个蛇身
- {
- case 'w' : snake.x[0] = snake.x[0] - 1;break;
- case 's' : snake.x[0] = snake.x[0] + 1;break;
- case 'a' : snake.y[0] = snake.y[0] - 1;break;
- case 'd' : snake.y[0] = snake.y[0] + 1;break;
- }
- if(food.x == snake.x[0] && food.y == snake.y[0])//如果吃到食物,蛇身+1,分数+1
- {
- snake.length = snake.length +1;
- score++;
- gotoxy(9, 69);
- printf("%d", score);
- }
- for(i=snake.length ; i>=2 ; i--)//从未来吃到食物的一节蛇的身体开始,把前一节的身体坐标赋给当前这节,以达到蛇的移动
- { //第二节身体还保持原样, 因为蛇头的位置变动了
- snake.x[i] = snake.x[i-1];
- snake.y[i] = snake.y[i-1];
- }
- snake.x[1] = temp_x;
- snake.y[1] = temp_y;//把蛇头移动前的坐标赋给第二节身体
- gotoxy(snake.x[0], snake.y[0]);
- printf("*");//打印蛇头
- gotoxy(snake.x[snake.length], snake.y[snake.length]);
- printf(" ");//清除“*”未来吃到食物的一节蛇的身体(即移动前,蛇的最后一节身体),不懂的话可以单步调试(我语文学的不太好。。。)
- }
- int if_dead(void)
- {
- for(i=1 ; i<=snake.length-1 ; i++)//蛇头的坐标与蛇身体任意一节的坐标相同的话判断死亡
- {
- if((snake.x[0] == snake.x[i] && snake.y[0] == snake.y[i]))
- {
- return 1;
- }
- }
- if((snake.x[0] == 0 || snake.x[0] == 24) || (snake.y[0] == 0 || snake.y[0] == 49))
- { //蛇头的坐标与边界的坐标一样的话判断死亡
- return 1;
- }
- return 0;
- }
- void end(void)
- {
- void gotoxy(int x, int y);
- gotoxy(snake.x[0], snake.y[0]);
- printf("+");
- gotoxy(food.x, food.y);
- printf(" ");
- for(i=1 ; i<=snake.length-1 ; i++)
- {
- gotoxy(snake.x[i], snake.y[i]);
- printf(" ");
- }//清除蛇和食物
- gotoxy(12, 20);
- printf("游戏结束!");
- }
- void gotoxy(int x, int y) //这个函数作用是把屏幕坐标化,详细说明请自行百度
- {
- HANDLE hout;
- COORD cor;
- hout=GetStdHandle(STD_OUTPUT_HANDLE);
- cor.X=y;
- cor.Y=x;
- SetConsoleCursorPosition(hout,cor);
- }
复制代码 |
|