• 01、C语言--贪吃蛇案例


    贪吃蛇游戏

    贪食蛇(也叫贪吃蛇)是一款经典的小游戏。初始是像素版本,后来又衍生出3D版本、多人对战版本等。
    这里使用C语言来实现DOS下的贪吃蛇小游戏。

    开发工具:Visual Studio 2019
    开发语言:C语言

    游戏开始后,会在中间位置出现一条只有一个个节点的贪吃蛇,并随机出现一个食物。
    贪吃蛇开始移动后,和大部分游戏一样,你可以通过W、A、S、D四个键来控制移动方向。
    当贪吃蛇出界或者撞到自己时,游戏结束。
    游戏源码如下所示:
    snake.h

    #ifndef __SNAKE_H__
    #define __SNAKE_H__
    
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include <time.h>
    #include <conio.h>
    #include <Windows.h>
    
    #define WIDTH 60    // 宽度
    #define HEIGHT 20   // 高度
    // 身体的对象
    struct BODY {
    	int X;    // x坐标
    	int Y;    // y坐标
    };
    
    // 定义蛇对象
    struct SNACK {
    	struct BODY body[WIDTH * HEIGHT];	// 蛇的最大长度
    	int length;	// 蛇的长度
    } snake;
    
    // 定义食物对象
    struct FOOD {
    	int X;
    	int Y;
    } food;
    
    int score = 0;  // 分数
    
    int keyX = 0;	// 用户按下WASD按键得到的坐标值
    int keyY = 0;
    
    int lastX = 0;		// 蛇尾的坐标。
    int lastY = 0;
    
    int sleepSecond = 400;
    
    // 声明函数
    void initSnack(void);
    void initFood(void);
    void initUI(void);
    void playGame(void);
    void initWall(void);
    void showScore(void);
    #endif
    

    Snake.c

    #define _CRT_SECURE_NO_WARNINGS
    #include "snake.h"
    
    int main() {
    	// 去除光标。
    	CONSOLE_CURSOR_INFO cci;
    	cci.dwSize = sizeof(cci);
    	cci.bVisible = FALSE;  // TRUE :
    	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci);
    
    	srand(time(NULL)); // 置随机种子
    	initSnack();	// 初始化蛇
    	initFood();		// 初始化食物
    	initWall();		// 画墙
    	initUI();		// 初始化UI
    	playGame();		// 启动游戏
    	showScore();	// 打印分数
    	system("pause");
    	return EXIT_SUCCESS;
    }
    
    // 开始游戏
    void playGame(void) {
    	char key = 'd';
    	// 判断蛇是否撞墙
    	while (snake.body[0].X >= 0 && snake.body[0].X < WIDTH
    		&& snake.body[0].Y >= 0 && snake.body[0].Y < HEIGHT){
    		// 刷新UI
    		initUI();
    		// 接收用户按键输入 A S D W
    		if (_kbhit()){	// 不阻塞判断用户输入
    			key = _getch();
    		}
    		switch (key) {
    			case 'w': keyX = 0; keyY = -1; break;
    			case 's': keyX = 0; keyY = +1; break;
    			case 'd': keyX = +1; keyY = 0; break;
    			case 'a': keyX = -1; keyY = 0; break;
    			default: break;
    		}
    
    		// 如果蛇头和蛇身体的位置完全一致,则判定为相撞
    		for (size_t i = 1; i < snake.length; i++) {
    			if (snake.body[0].X == snake.body[i].X
    				&& snake.body[0].Y == snake.body[i].Y) {
    				return;		// 游戏结束。
    			}
    		}
    
    		// 蛇头撞食物
    		if (snake.body[0].X == food.X && snake.body[0].Y == food.Y){
    			// 食物消失,身体增长,加分,加速
    			initFood();
    			snake.length++;
    			score += 10;
    			sleepSecond -= 10;	// 加速
    		}
    
    		// 存储蛇尾坐标
    		lastX = snake.body[snake.length - 1].X;
    		lastY = snake.body[snake.length - 1].Y;
    
    		// 蛇移动就是前一节身体赋值给后一节即可
    		for (size_t i = snake.length - 1; i > 0; i--) {
    			snake.body[i].X = snake.body[i - 1].X;
    			snake.body[i].Y = snake.body[i - 1].Y;
    		}
    		// 蛇头坐标根据用户按键而改变
    		snake.body[0].X += keyX;
    		snake.body[0].Y += keyY;
    		Sleep(sleepSecond);
    	}
    	return;
    }
    
    // 初始化墙
    void initWall(void) {
    	for (size_t i = 0; i <= HEIGHT; i++){
    		for (size_t j = 0; j <= WIDTH; j++){
    			if (j == WIDTH) {
    				printf("|");
    			} else if (i == HEIGHT) {
    				printf("_");
    			} else {
    				printf(" ");
    			}
    		}
    		printf("
    ");
    	}
    }
    
    // 显示分数
    void showScore(void) {
    	// 将光标默认位置移动至 不干扰游戏的任意位置。
    	COORD coord;
    
    	coord.X = 0;
    	coord.Y = HEIGHT + 2;
    	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
    
    	printf("Game Over!!!
    ");
    	printf("成绩为:%d
    
    
    ", score);
    }
    
    // 初始化蛇
    void initSnack(void) {
    	snake.length = 2;
    	// 初始化蛇头的位置
    	snake.body[0].X = WIDTH / 2;
    	snake.body[0].Y = HEIGHT / 2;
    	// 初始化一节蛇身的位置
    	snake.body[1].X = (WIDTH / 2) - 1;
    	snake.body[1].Y = HEIGHT / 2;
    	return;
    }
    
    // 初始化界面控件
    void initUI(void) {
    	// 画蛇
    	COORD coord = {0};    // 光标移动的位置
    	for (size_t i = 0; i < snake.length; i++) {
    		coord.X = snake.body[i].X;
    		coord.Y = snake.body[i].Y;
    		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
    		if (i == 0)
    			putchar('@');
    		else
    			putchar('*');
    	}
    
    	// 去除蛇尾
    	coord.X = lastX;
    	coord.Y = lastY;
    	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
    	putchar(' ');
    
    	// 画食物
    	coord.X = food.X;
    	coord.Y = food.Y;
    	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
    	putchar('&');
    }
    
    // 初始化食物
    void initFood(void) {
    	food.X = rand() % WIDTH;	// 0 - 59
    	food.Y = rand() % HEIGHT;	// 0 - 20
    	return;
    }
    
  • 相关阅读:
    第2章 类模板:2.3 类模板的局部使用
    第2章 类模板:2.2 类模板Stack的使用
    第2章 类模板:2.1 类模板Stack的实现
    第1章 函数模板:1.6 但是,我们不应该…?
    第1章 函数模板:1.5 重载函数模板
    第1章 函数模板:1.4 默认模板参数
    第1章 函数模板:1.3 多模板参数
    第1章 函数模板:1.2 模板参数的推导
    第1章 函数模板:1.1 初识函数模板
    第31课 std::atomic原子变量
  • 原文地址:https://www.cnblogs.com/pengjingya/p/14965372.html
Copyright © 2020-2023  润新知