• 贪吃蛇


      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(); } }
  • 相关阅读:
    多端统一框架Taro基础教程
    golang中的race检测
    【Golang】高性能编程之超时退出协程
    电容充放电时间常数RC计算方法(转)
    meanshift算法详解(转)
    vim 统计字符串在当前文档中出现的次数
    置信区间的理解
    IC 后端仿真: process corner 和 PVT (转)
    STA概念:一文了解NLDM与CCS(转)
    Linux 中 fg、bg、jobs 等指令(转)
  • 原文地址:https://www.cnblogs.com/GoldenEllipsis/p/13417244.html
Copyright © 2020-2023  润新知