贪吃蛇

  c语言学了好久了,想写一个贪吃蛇游戏,但是,真的不知道如何下手,只好网上下了一个别人写的初级的贪吃蛇代码来研究!看完代码,发现,代码真的不难理解,真正难的就是思路

  贪吃蛇,要能移动,转弯,吃食物,长大,死亡;移动规则,不能在原有方向上往相反方向移动,在地图内上下左右移动,死亡规则是,不能碰自己身体,不能碰墙壁

  用什么窗口,如何在窗口上显示一个地图,如何在地图上显示一条蛇,如何在地图上显示食物,用什么表示蛇及食物,如何操控蛇的移动,代码中,窗口用的是控制台窗口,"绘图"其实是打印文本,这需要用到windows系统API的若干函数,有控制台光标定位函数,窗口句柄获取函数,文本颜色设定函数,获取按下的按键信息函数,这些函数可以通过微软的MSDN,查找到如何使用的帮助文件

  蛇及食物是有坐标数据的链表结构体,然后按照模块化设计思想,构造游戏结构,一个循环体创建地图,初始化蛇,调用随机数srand函数并随机生成食物,操控下上左右按键控制蛇移动方向(蛇自动移动),蛇死亡后选择是否重新开始游戏

  1、snake.c,main函数

#include "snake.h"
#include <time.h>
int main()
{
    int ctrl = 1;
    while (ctrl)
    {
        createMap();
        initsnack();
        srand((unsigned)time(NULL));
        createfood();
        key();
        gotoxy(60, 26);
        color(3);
        printf("输入0结束游戏游戏,输入1重新开始:");
        scanf("%d", &ctrl);
        system("cls");
    }
    return 0;
}

  2、snake.h,包含库头文件、蛇结构体,蛇及食物结构体指针全局变量、共用函数的声明

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

/* snack链表结构体 */
typedef struct snack
{
    int x;              //x坐标
    int y;              //y坐标
    struct snack *next; //指向下一个snack结构
} snack;

snack *head; //全局蛇头指针
snack *food; //全局食物指针

/*print.c*/
void gotoxy(int x, int y);
int color(WORD c);
void createMap();
void print_snack(snack *ss);
void initsnack();
void createfood();

/*move.c*/
void isfood();
void snack_move();
int kill();
void key();

  3、print.c,打印地图、初始化并打印蛇及食物、光标定位、颜色设定

#include "snake.h"
 /* 光标定位 */
void gotoxy(int x, int y)
{ 
    COORD c;
    c.X = x;
    c.Y = y;
        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}
/* 设定颜色 */
int color(WORD c)
{
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c);
    return 0;
}
/* 建地图 */
void createMap()
{   
    int i, j;
    for (i = 0; i < 58; i += 2) //地图上下边界
    {
        color(5);
        gotoxy(i, 0);
        printf("");
        gotoxy(i, 26);
        printf("");
    }
    for (i = 1; i < 26; i++) //地图左右边界
    {
        gotoxy(0, i);
        printf("");
        gotoxy(56, i);
        printf("");
    }
    for (i = 2; i < 56; i += 2) //地图内部
    {
        for (j = 1; j < 26; j++)
        {
            color(3);
            gotoxy(i, j);
            printf("");
        }
    }
}
/* 打印蛇身体 */
void print_snack(snack *ss)//传入蛇头指针
{   
    while (ss != NULL) //遍历蛇体
    {
        gotoxy(ss->x, ss->y);
        color(14);
        printf("");
        ss = ss->next;
    }
}
/* 初始化蛇 */
void initsnack()
{  
    snack *tail;
    int i;
    tail = (snack *)malloc(sizeof(snack)); //分配内存
    tail->x = 20;                          //出生点
    tail->y = 15;
    tail->next = NULL;
    for (i = 1; i < 4; i++) //头插法加长蛇身
    {
        head = (snack *)malloc(sizeof(snack));     
        head->x = 20 + 2 * i;
        head->y = 15;
                head->next = tail; 
        tail = head;
    }
    print_snack(tail); //打印蛇体
}
/* 生成并打印食物 */
void createfood()
{  
    snack *tem_food, *ss;
    tem_food = (snack *)malloc(sizeof(snack));
    tem_food->x = rand() % 52 + 2; //食物坐标取随机数
    while ((tem_food->x % 2) != 0) //保证x为奇数使食物对齐地图网格
    {
        tem_food->x = rand() % 52 + 2;
    }
    tem_food->y = rand() % 24 + 1;
    ss = head;
    while (ss != NULL) //判断食物是否与蛇体重合
    {
        if (ss->x == tem_food->x && ss->y == tem_food->y)
        {
            free(tem_food);
            createfood(); //重合的话释放内存并重新生成食物
        }
        ss = ss->next;
    }
    gotoxy(tem_food->x, tem_food->y);
    food = tem_food;
    color(12);
    printf(""); //打印食物
}

  4、move.c,蛇的移动、按键操控及获取 、吃食物、死亡

#include "snake.h"
/*限制在本文件内使用*/
static int score;  /*吃到食物得分score*/
static enum {U,D,L,R} status = R; /*蛇移动的方向,初始为右*/
/*吃到食物得分,否则删除蛇尾*/
void isfood()
{
    /* 判断蛇是否吃到食物 */
    snack *tail = head;
    if (head->x == food->x && head->y == food->y) //蛇头与食物坐标重合即吃到食物
    {
        print_snack(head); //打印蛇体
        free(food);        //释放内存
        score += 1;
        gotoxy(60, 1);
        color(2);
        printf("得分:%d", score); //打印得分+1
        createfood();              //重新创建食物
        gotoxy(58, 26);            //光标移走
    }
    else
    {
        while (tail->next->next != NULL)
        {
            tail = tail->next;
        }
                gotoxy(58, 26); /*移走光标*/
        gotoxy(tail->next->x, tail->next->y);
        color(3);
        printf("");       //不是食物的话在蛇尾处补上地图                    
        free(tail->next);  //释放蛇尾
        tail->next = NULL; //上一节成为蛇尾
        print_snack(head); //打印蛇体      
                gotoxy(58, 26); /*移走光标*/
    }
}
/* 蛇的移动 */
void snack_move()
{    
    snack *next_head; /*新蛇头*/
    next_head = (snack *)malloc(sizeof(snack));
    if (status == U) //向上移动
    {    
        next_head->x = head->x;
        next_head->y = head->y - 1;
    }
    if (status == D) //向下移动
    {   
        next_head->x = head->x;
        next_head->y = head->y + 1;
    }
    if (status == L) //向左移动
    {
        next_head->x = head->x - 2; 
        next_head->y = head->y;
    }
    if (status == R) //向右移动
    {
        next_head->x = head->x + 2; 
        next_head->y = head->y;
    }
    next_head->next = head;  /*头插法*/
    head = next_head;
    isfood();  /*不是食物, 删除蛇尾*/
}
/* 判断是否死亡 */
int kill()
{  
    int flag = 0;
    snack *s;
    s = head->next;
    if (head->x == 0 || head->x == 56 || head->y == 0 || head->y == 26) //撞墙判断
    {
        flag = 1;
    }
    while (s->next != NULL)
    {
        if (head->x == s->x && head->y == s->y) //撞到自己身体判断
        {
        flag = 1;
        break; } s
= s->next; } return flag; } /* 判断键盘按键 */ void key() { int sleeptime = 200; //间隔时间 status = R; //初始向右移动 score = 0; gotoxy(60, 1); color(2); printf("得分:%d", score); //打印初始分 while (1) //获取按键指令 { if (GetAsyncKeyState(VK_UP) && status != D) { status = U; } else if (GetAsyncKeyState(VK_DOWN) && status != U) { status = D; } else if (GetAsyncKeyState(VK_LEFT) && status != R) { status = L; } else if (GetAsyncKeyState(VK_RIGHT) && status != L) { status = R; } if (kill()) //失败跳出循环 { gotoxy(60, 5); color(FOREGROUND_RED); printf("You are dead!"); break; } Sleep(sleeptime); snack_move(); } }
原文地址:https://www.cnblogs.com/GoldenEllipsis/p/13417244.html