遊戲:貪吃蛇
阿新 • • 發佈:2018-11-10
一、Game.h
#ifndef __GAME_H__
#define __GAME_H__
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<windows.h>
//蛇移動區域
#define gamewidth 25
#define gameheigth 25
//牆
#define wallwidth (gamewidth+2)
#define wallheigth (gameheigth+2)
//蛇的方向
#define U 1 //上
#define D 2 //下
#define L 3 //左
#define R 4 //右
typedef struct Snake //蛇身的一個節點
{
int x;
int y;
struct Snake *next;
}Snake;
typedef struct Food //食物節點
{
int x;
int y;
}Food;
void Pos(int x, int y); //設定游標位置
void StartInterface(); //開始介面
void CreatWall(); //建立牆
void InitSnake(Snake **pphead); //初始化蛇
void CreateFood(Snake *head, Food **ppfood); //建立食物
void InitGame(Snake **pphead, Food **ppfood); //遊戲初始化
int TouchWall(Snake *head); //判斷是否碰到牆
int BiteSelf(Snake *head); //判斷是否咬到了自己
void Pause(); //暫停
void EndGame(int endflag, int score); //結束遊戲
void MoveSnake(Snake **pphead, Food **ppfood, int direction, int *score, int perscore); //控制蛇前進
void ControlGame(Snake **pphead, Food *food, int score, int perscore, int sleeptime); //控制遊戲
#endif __GAME_H__
二、Game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//設定游標位置
void Pos(int x, int y)
{
COORD pos = { x, y };
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOutput, pos);
CONSOLE_CURSOR_INFO cci;
GetConsoleCursorInfo(hOutput, &cci); //獲取當前游標資訊
cci.bVisible = FALSE; //設定游標不可見
SetConsoleCursorInfo(hOutput, &cci);
}
//開始介面
void StartInterface()
{
system("cls");
Pos((50 - strlen("歡迎來到貪食蛇遊戲") / 2), 13);
printf("歡迎來到貪食蛇遊戲\n");
system("pause");
system("cls");
Pos((50 - strlen("用↑、↓、←、→分別控制蛇的移動, F1 為加速,F2 為減速") / 2), 13);
printf("用↑、↓、←、→分別控制蛇的移動, F1 為加速,F2 為減速");
Pos((50 - strlen("加速將能得到更高的分數") / 2), 15);
printf("加速將能得到更高的分數\n");
system("pause");
system("cls");
}
//建立牆
void CreatWall()
{
int i = 0;
// 上
for (i = 0; i < wallwidth * 2; i = i + 2)
{
Pos(i, 0);
printf("■");
}
// 下
for (i = 0; i < wallwidth * 2; i = i + 2)
{
Pos(i, wallheigth - 1);
printf("■");
}
// 左
for (i = 1; i < wallheigth - 1; i++)
{
Pos(0, i);
printf("■");
}
// 右
for (i = 1; i < wallheigth - 1; i++)
{
Pos((wallwidth - 1) * 2, i);
printf("■");
}
}
//初始化蛇
void InitSnake(Snake **pphead)
{
Snake *tail = (Snake *)malloc(sizeof(Snake));
tail->x = 2;
tail->y = 2;
tail->next = NULL;
for (int i = 1; i < 3; i++) //頭插法
{
*pphead = (Snake *)malloc(sizeof(Snake));
(*pphead)->x = 2 + 2 * i;
(*pphead)->y = 2;
(*pphead)->next = tail;
tail = *pphead;
}
while (tail != NULL)
{
Pos(tail->x, tail->y);
printf("■");
tail = tail->next;
}
}
//建立食物
void CreateFood(Snake *head, Food **ppfood)
{
int flag = 0;
srand((unsigned)time(NULL));
*ppfood = (Food*)malloc(sizeof(Food));
while (1)
{
(*ppfood)->x = (rand() % gameheigth + 1) * 2;
(*ppfood)->y = rand() % gameheigth + 1;
Snake *cur = head;
while (cur)
{
if (cur->x == (*ppfood)->x&&cur->y == (*ppfood)->y) //食物不能和蛇身重合
{
flag = 1;
break;
}
cur = cur->next;
}
if (flag == 0)
{
break;
}
}
Pos((*ppfood)->x, (*ppfood)->y);
printf("■");
}
//遊戲初始化
void InitGame(Snake **pphead, Food **ppfood)
{
StartInterface();
CreatWall();
InitSnake(pphead);
CreateFood(*pphead, ppfood);
}
//判斷是否碰到牆
int TouchWall(Snake *head)
{
if (head->x == 0 || head->x == (wallwidth - 1) * 2 || head->y == 0 || head->y == wallheigth - 1)
{
return 1;
}
return 0;
}
//判斷是否咬到了自己
int BiteSelf(Snake *head)
{
Snake *cur = head->next;
while (cur)
{
if (cur->x == head->x&&cur->y == head->y)
{
return 1;
}
cur = cur->next;
}
return 0;
}
//暫停
void Pause()
{
while (1)
{
Sleep(300);
if (GetAsyncKeyState(VK_SPACE))
{
break;
}
}
}
//控制蛇前進
void MoveSnake(Snake **pphead, Food **ppfood, int direction, int *score, int perscore)
{
Snake *nextnode = (Snake *)malloc(sizeof(Snake));
switch (direction)
{
case U:
{
nextnode->x = (*pphead)->x;
nextnode->y = (*pphead)->y - 1;
}
break;
case D:
{
nextnode->x = (*pphead)->x;
nextnode->y = (*pphead)->y + 1;
}
break;
case L:
{
nextnode->x = (*pphead)->x - 2;
nextnode->y = (*pphead)->y;
}
break;
case R:
{
nextnode->x = (*pphead)->x + 2;
nextnode->y = (*pphead)->y;
}
break;
}
if (nextnode->x == (*ppfood)->x&&nextnode->y == (*ppfood)->y) //下一個位置是食物
{
nextnode->next = *pphead;
*pphead = nextnode;
Snake *cur = *pphead;
while (cur)
{
Pos(cur->x, cur->y);
printf("■");
cur = cur->next;
}
*score += perscore;
free(*ppfood);
CreateFood(*pphead, ppfood); //建立新的食物
}
else //下一個位置不是食物
{
nextnode->next = *pphead;
*pphead = nextnode;
Snake *cur = *pphead;
while (cur->next->next) //找到蛇身倒數第二個節點
{
Pos(cur->x, cur->y);
printf("■");
cur = cur->next;
}
Pos(cur->next->x, cur->next->y);
printf(" ");
free(cur->next);
cur->next = NULL;
}
}
//結束遊戲
void EndGame(int endflag, int score)
{
system("cls");
if (endflag == 1)
{
Pos((50 - strlen("您已結束了遊戲") / 2), 13);
printf("您已結束了遊戲\n");
}
else if (endflag == 2)
{
Pos((50 - strlen("遊戲結束,您撞到牆了") / 2), 13);
printf("遊戲結束,您撞到牆了\n");
}
else if (endflag == 3)
{
Pos((50 - strlen("遊戲結束,您撞到自己了") / 2), 13);
printf("遊戲結束,您撞到自己了\n");
}
Pos((50 - strlen("您的最終得分是: ") / 2), 15);
printf("您的最終得分是:%d\n", score);
}
//控制遊戲
void ControlGame(Snake **pphead, Food *food, int score, int perscore, int sleeptime)
{
Pos(wallwidth * 2 + 10, 12);
printf("不能撞到牆,不能撞到自己");
Pos(wallwidth * 2 + 10, 13);
printf("用↑、↓、←、→分別控制蛇的移動");
Pos(wallwidth * 2 + 10, 14);
printf("F1為加速,F2為減速");
Pos(wallwidth * 2 + 10, 15);
printf("Esc為退出遊戲,Space為暫停");
int direction = R; //蛇的初始前進方向
while (1)
{
Pos(wallwidth * 2 + 10, 10);
printf("得分:%d 每個食物得分:%2d", score, perscore);
if (GetAsyncKeyState(VK_UP) && direction != D)
{
direction = U;
}
else if (GetAsyncKeyState(VK_DOWN) && direction != U)
{
direction = D;
}
else if (GetAsyncKeyState(VK_LEFT) && direction != R)
{
direction = L;
}
else if (GetAsyncKeyState(VK_RIGHT) && direction != L)
{
direction = R;
}
else if (GetAsyncKeyState(VK_F1))
{
if (sleeptime > 100)
{
sleeptime -= 200;
perscore += 5;
}
}
else if (GetAsyncKeyState(VK_F2))
{
if (sleeptime < 500)
{
sleeptime += 200;
perscore -= 5;
}
}
else if (GetAsyncKeyState(VK_SPACE))
{
Pause();
}
else if (GetAsyncKeyState(VK_ESCAPE))
{
EndGame(1, score);
return;
}
MoveSnake(pphead, &food, direction, &score, perscore);
Sleep(sleeptime);
if (TouchWall(*pphead))
{
EndGame(2, score);
return;
}
if (BiteSelf(*pphead))
{
EndGame(3, score);
return;
}
}
}
三、Test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void Menu()
{
printf("**********貪吃蛇遊戲**********\n");
printf("** **\n");
printf("** 1.開始遊戲 **\n");
printf("** 0.退出遊戲 **\n");
printf("** **\n");
printf("******************************\n");
}
int main()
{
system("mode con cols=100 lines=32");
int op = 0;
do{
Menu();
printf("請選擇:");
scanf("%d", &op);
switch (op)
{
case 1:
{
Snake *head = NULL;
Food *food = NULL;
int perscore = 10;
int score = 0;
int sleeptime = 300;
InitGame(&head, &food);
ControlGame(&head, food, score, perscore, sleeptime);
Snake* tail = NULL;
while (head)
{
tail = head->next;
free(head);
head = tail;
}
free(food);
food = NULL;
system("pause");
system("cls");
}
break;
case 0:
{
system("pause");
return 0;
}
break;
}
} while (op);
}