C语言实现的贪吃蛇小游戏

学习完C语言基础后,当然要做点小东西来巩固一下知识啦~~,之前做的学生信息管理系统是比较小的,搞定之后决定还是做个贪吃蛇的小游戏,这是学习C语言的经典入门小程序,下面简单地说下用C语言开发这个需要用到什么库吧。

贪吃蛇

我刚刚做的时候也是一头雾水,不知道为什么别人能够在控制台应用程序中能够画出这么复杂的界面,经过网上的一番查找,终于知道,C语言是有方法定位光标的位置的。

// 移动光标到指定位置
void Gotoxy(int x, int y)
{
    COORD position = { y, x };
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), position);
}

相信认真去学过C语言的人对这个方法不陌生,没错,我曾经在网上找过实现贪吃蛇的很多资料,但是很多人的代码都只是把gotoxy这个方法的代码打出来,无头无脑,我根本不知道是自定义的代码还是库里自带的方法。
经过多番查找,发现这个方法其实是自己写的,里面的COORD则是库中自带的类型,属于<Windows.h>库,如果要写这个方法,直接饮用这个库就可以了。

整个游戏除了以上的方法是需要摸索来源,其余的代码基本用C语言的基础:数组、结构体和指针。就足以完成。下面是主要的代码:
头文件:SnakeInit.h

#define ROW 23   // 行
#define LINE 50  // 列
#define LENGTH 4; // 蛇的初始长度
#define WAIT_TIME 500; // 蛇的运行速度

int score;                     // 当局分数
int maxScore;                  // 最高分数
int length;                    // 蛇的长度
int xincrement;                // x轴增量
int yincrement;                // y轴增量
int isDigestion;               // 是否已消化食物

int border[ROW][LINE];         // 边界数组

// 蛇结构体
typedef struct Snake {
    int x;
    int y;
    int seq;
    char text[1];
    struct Snake *preNode;
    struct Snake *nextNode;
}snake_t;

// 食物结构体
typedef struct Food {
    int x;
    int y;
    char text[1];
}food_t;

snake_t *snake;               // 蛇
snake_t *lastNode;            // 蛇的最后一个节点
food_t food;                  // 食物

void InitMainView();          // 初始化界面
int IsDied();                 //判断蛇是否已死(撞到边界或吃到自己)
void Gotoxy(int x, int y);    // 将光标跳到指定的坐标
void InitFood();              // 初始化食物
void InitSnake();             // 初始化蛇
void ClearSnake();            // 清除蛇的轨迹
void MoveSnake();             // 移动蛇的位置
void ShowSnake();             // 显示蛇的所有节点
void OperateSnake();          //操作蛇的移动方向
int CheckCoord(int x, int y); //检查能投放食物的位置
void FoodSnake();             //投喂蛇
void AddNode();               // 蛇身添加节点
void RefreshScore();          // 刷新界面分数
void ShowDeadMessage();       //显示蛇死亡信息
void ShowMessage();           //提示信息

源文件:SnakeInit.c

#include <stdio.h>
#include <conio.h>
#include <Windows.h>
#include <conio.h>
#include "SnakeInit.h"

#pragma region 界面方法

// 初始化数组
void InitArray() {
    int i, j;
    for (i = 0;i < ROW;i++) {
        border[i][0] = 1;
        border[i][LINE - 1] = 1;
    }

    for (j = 0;j < LINE;j++) {
        border[0][j] = 1;
        border[ROW - 1][j] = 1;
    }
}

// 初始化界面
void InitMainView() {
    InitArray();
    int i, j;
    for (i = 0;i < ROW;i++) {
        for (j = 0;j < LINE;j++) {
            if (border[i][j] == 0) {
                printf(" ");
            }
            else {
                printf("#");
            }
        }
        printf("\n");
    }
}

// 移动光标到指定位置
void Gotoxy(int x, int y)
{
    COORD position = { y, x };
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), position);
}
#pragma endregion

#pragma region 蛇方法
void InitFood() {
    strcpy(food.text, "*");
}
// 初始化蛇
void InitSnake() {
    length = LENGTH;
    snake = (snake_t *)malloc(sizeof(snake_t));
    snake->preNode = NULL;
    snake->nextNode = NULL;
    snake->x = ROW / 2;
    snake->y = LINE / 2;
    snake->seq = 1;
    strcpy(snake->text, "@");

    int i;
    snake_t *pre = snake;
    for (i = 1;i < length;i++) {
        snake_t *next = (snake_t *)malloc(sizeof(snake_t));
        next->preNode = pre;
        next->nextNode = NULL;
        next->x = pre->x + 1;
        next->y = pre->y;
        next->seq = pre->seq + 1;
        pre->nextNode = next;
        strcpy(next->text, "@");
        pre = next;
    }
    lastNode = pre;
}

// 清楚蛇的移动轨迹
void ClearSnake() {
    Gotoxy(lastNode->x, lastNode->y);
    printf(" ");
}

// 界面显示蛇
void ShowSnake() {
    snake_t *snakeNode = snake;
    while (snakeNode->nextNode != NULL) {
        Gotoxy(snakeNode->x, snakeNode->y);
        printf("%s", snakeNode->text);
        snakeNode = snakeNode->nextNode;
    }

    Gotoxy(snakeNode->x, snakeNode->y);
    printf("%s", snakeNode->text);
}

// 界面移动蛇
void MoveSnake() {
    if (lastNode->x == food.x && lastNode->y == food.y) {
        isDigestion = 1;
    }

    snake_t *node = lastNode;
    while (node->preNode != NULL)
    {
        node->x = node->preNode->x;
        node->y = node->preNode->y;
        node = node->preNode;
    }

    node->x += xincrement;
    node->y += yincrement;
}

// 操作蛇的运行方向
void OperateSnake() {
    if (kbhit() == 0) {
        // 没有按下按键
        return;
    }
    char oper = getch();
    switch (oper)
    {
        case 'w': // 上
        case 'W':
            xincrement = -1;
            yincrement = 0;
            break;
        case 's': // 下
        case 'S':
            xincrement = 1;
            yincrement = 0;
            break;
        case 'a': // 左
        case 'A':
            xincrement = 0;
            yincrement = -1;
            break;
        case 'd': // 右
        case 'D':
            xincrement = 0;
            yincrement = 1;
            break;
        default:
            Gotoxy(ROW, 0);
            printf("请输入正确的方向(上[w/W]、下[s/S]、左[a/A]、右[d/D]");
            break;
    }
}

// 蛇是否运行到边界或吃到自己
int IsDied() {
    int result = 0;
    if (snake->x == 0 || snake->x == ROW - 1 || snake->y == 0 || snake->y == LINE - 1) {
        // 走到边界则死亡
        result = 1;
    }
    int x = snake->x + xincrement;
    int y = snake->y + yincrement;
    snake_t *nextNode = snake->nextNode;
    while (nextNode != NULL) {
        if (x == nextNode->x && y == nextNode->y) {
            result = 1;
            break;
        }
        nextNode = nextNode->nextNode;
    }

    return result;
}

// 检查随机投放点是否在蛇的节点上
int CheckCoord(int x, int y) {
    int result = 0;
    snake_t *nextNode = snake;
    while (nextNode != NULL) {
        if (x == nextNode->x && y == nextNode->y) {
            result = 1;
            break;
        }
        nextNode = nextNode->nextNode;
    }
    return result;
}

// 投放食物
void FoodSnake() {
    int x, y;
    do {
        x = rand() % (ROW - 1);
        y = rand() % (LINE - 1);
    } while (CheckCoord(x, y));
    food.x = x;
    food.y = y;
    Gotoxy(food.x, food.y);
    printf("%s", food.text);
}

// 吃掉食物后长度加一
void AddNode() {
    snake_t *newNode = (snake_t *)malloc(sizeof(snake_t));
    newNode->x = food.x;
    newNode->y = food.y;
    strcpy(newNode->text, "@");
    newNode->preNode = lastNode;
    newNode->nextNode = NULL;
    lastNode = newNode;
}
#pragma endregion

#pragma region Message

void RefreshScore() {
    int x = ROW / 2, y = LINE + 2;
    Gotoxy(x, y);
    printf("目前得分:%d", score);
    Gotoxy(x + 2, y);
    printf("最高得分:%d", maxScore);
}

void ShowDeadMessage() {
    Gotoxy(ROW / 2, LINE / 2 - 10);
    printf("蛇已死亡!请按任意键返回。");
    getchar();
    getchar();
}

void ShowMessage() {
    Gotoxy(ROW + 2, 0);
    printf("是否重新开局?(y/n):");
}
#pragma endregion

主函数:main.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#include "SnakeInit.h"

int main(int argc, char *argv[]) {
    while (1) {
        int len = LENGTH; // 初始化蛇的初始长度
        int waittime = WAIT_TIME;
        CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };
        SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);    //隐藏光标

        // 初始化界面
        system("CLS");
        InitMainView();
        RefreshScore();
        InitFood();
        InitSnake();
        ShowSnake();
        FoodSnake();
        xincrement = -1;
        yincrement = 0;
        // 初始化显示蛇
        while (1) {
            OperateSnake();
            if (IsDied()) {
                // 提示蛇已死亡
                ShowDeadMessage();
                break;
            }
            ClearSnake();
            MoveSnake();
            if (isDigestion) {
                AddNode();
                FoodSnake();
                isDigestion = 0;
                score += 10;
                RefreshScore();
            }

            ShowSnake();
            Sleep(waittime);
        }

        // 询问是否继续玩
        char con[1];
        ShowMessage();
        scanf("%c", &con[0]);
        if (con[0] == 'n') {
            break;
        }

        if (score > maxScore) {
            maxScore = score;
            score = 0;
        }
    }

    return 0;
}

本文到这里已经基本结束了,看代码,是不是很简单?除了头文件,两个类就能够把方法写完。本文主要是记录和分享一下代码,代码细节就不一一阐述了。

原文地址:https://www.cnblogs.com/ghm-777/p/11718151.html

时间: 2024-10-14 15:49:32

C语言实现的贪吃蛇小游戏的相关文章

贪吃蛇小游戏 (一)

贪吃蛇是一款儿时爱不释手的游戏.近日修行,想玩玩游戏开发.便简单写了个控制台版的贪吃蛇. 程序的简单框架: 建立一张固定大小的MAP,保存输出信息. 当信息有变动时,用system("cls")进行清屏操作,再重新输出实现伪动态. 重点算法在蛇身的移动,转向与增长.三者均基于链表实现. 移动与转向:通过判定移动方向,确定下一步移动的位置后,新建表头结点.将新表头结点置为表头.删除末尾结点. 增长:通过判断尾部移动方向,确定位置后在尾部添加节点. 熟练运用链表的同学,相信也是小菜一碟了.

一个简单的“贪吃蛇”小游戏

一个简单的“贪吃蛇”小游戏 页面结构 简单的21x21的方块,页面结构 id为container的div包含所21个class名为row的div,每个row代表贪吃蛇的一整行,每个row中又包含21个div,代表这一行的每一个div方格,如果这个方格是空的话,div的类名为blank,如果这一个方格表示“贪吃蛇”的“食物”,div的类名为food,如果这一个方格表示“蛇”,div的类名为snake. CSS JS 然后我们思考下一个贪吃蛇游戏需要那些参数, 首先,界面中可见的元素无非就是空方格,

贪吃蛇小游戏的初步尝试制作

这里利用二维数组做为地图,利用集合来存放蛇头和蛇尾的位置坐标,初步实现一个需要键盘控制的贪吃蛇小游戏. 首先,Main函数下面需要一个大循环来让游戏失败的时候能够重新开始,这里我们用了定义了一个bool型的sc,判断sc的true和flase来确定游戏是否开始: static void Main(string[] args)        { bool sc = true; while (sc) //大循环,用于游戏失败重新开始            { 下面是定义一个集合snake_x来存放蛇

使用Html5+JS做的贪吃蛇小游戏

学习了Html5的Canvas的使用,和JS创建对象,做了一个贪吃蛇小游戏,来巩固JS面向对象编程和Canvas的用法. Node.js 1 /** 2 * 格子类,组成贪吃蛇和舞台 3 */ 4 function Node(x,y){ 5 this.x=x; 6 this.y=y; 7 /** 8 * 比较两个格子是否重合 9 */ 10 this.equals=function(x,y){ 11 return this.x==x&&this.y==y; 12 } 13 } Snake.

Java版贪吃蛇小游戏的实现

使用的IDE eclipse JDK版本 1.6 辅助类 Coordinate.java package com.nn.util; /** *坐标点 */ public class Coordinate { public int x; public int y; public Coordinate(int newX, int newY) { x = newX; y = newY; } public boolean equals(Coordinate other) { if (x == other

贪吃蛇小游戏java实现代码分析

贪吃蛇小游戏java实现代码分析 贪吃蛇的小游戏,网上的代码比较多,今天周五,在教研室没啥事做,在电脑中发现了一个贪吃蛇的小游戏,于是就看了下实现的源码,发现别人写的代码确实挺好的,自己也是边加注释边进行理解的去看别人实现的游戏源码,发现还是挺有意思的.自己花了一个下午的时间看了源码,也加了一点小小的功能,于是,不写篇博客觉得对不起自己也,哈哈哈. 此游戏代码的思路非常的清晰,也相当好理解,没有太多难的地方,不过有很多值得学习的地方,因为,这份源码中,对java.awt包中的很多类的很多方法都进

用C写一个功能较为完善的贪吃蛇小游戏

主要功能: 方向控制-食物与增长-变速 1 #include<stdio.h> 2 #include<time.h>//种子-随机数 3 #include<windows.h>//system函数,控制台句柄 4 #include<conio.h>//按键 5 //界面(欢迎界面-游戏界面-结束得分界面)-驱动-方向控制-食物 6 //位置锁定-打印-删除 7 int snake_x[520]={0}; 8 int snake_y[520]={0}; 9 i

js+jQuery实现贪吃蛇小游戏

这是我第一次这么认真的去写一个程序.今天老师布置的编程任务是实现一个贪吃蛇的小游戏,一开始感觉很茫然的,因为以前都没有这么系统的去做过一个编程任务.后来理清思路去做,感觉问题也并不是那么的难. 首先,第一步肯定是要编写出我们的的静态页面. 第二步,让我们的贪吃蛇先从一个开始动起来. 第三步,让我们通过键盘去控制他的运动方向. 第四步,让我们去判断我们的贪吃蛇有没有撞墙,有没有吃到自己,因为这已经犯规了. 第五步,给我们的贪吃蛇随机生成一个‘食物’. 第六步,实现每当我们的贪吃蛇吃了一个食物,他都

html5面向对象做一个贪吃蛇小游戏

canvas加面向对象方式的贪吃蛇 2016-08-25 这个小游戏可以增加对面向对象的理解,可以加强js逻辑能力,总之认真自己敲一两遍收获还是不少啊!!适合刚学canvas的同学练习!! 废话不多说,直接来讲思路和代码. ----------------------------------------------------------------------------------------------------------------- 开发思路:首先要有蛇吃的食物,就是一个个canv