牛刀小试 - C++实现贪吃蛇

参考文档

借鉴了这位大佬的博客及代码,键入代码后发现有很多报错,依次解决后成功运行

c++ 实现贪吃蛇(含技术难点解析和完整代码)

技术点:
C++中_kbhit()函数与_getch()函数
Windows API 坐标结构 COORD
句柄 HANDLE
获取句柄 GetStdHandle
光标的位置控 SetConsoleCursorPosition制
光标定位函数 gotoxy()与清屏函数clrscr()

报错解决

(1) warning C4244: “参数”: 从“time_t”转换到“unsigned int”,可能丢失数据
原因:一个简单的C的Hello World,如果用高版本的VS来编译,会有这种提示,这个是高版的VS默认不让使用scanf,fopen等函数,说是scanf,fopen等函数不安全,而代替其函数的是scanf_s,fopen_s等函数,后边有个"_s"的形式

解决:想要使用,可以在源文件开头加个:

#define _CRT_SECURE_NO_WARNINGS

预编时处理一下,加个宏而已,让其忽略安全检测
(2) warning C4996: ‘kbhit‘: The POSIX name for this item is deprecated.
原因:暂未得知
解决:将kbhit()改为_kbhit(),将getch()改为_getch()

(3)运行报错:
在这里插入图片描述
原因:变量没有初始化。

在这里插入图片描述
解决:随便赋个初值,注意不能与操作按键的值一致

完整代码


/*********************************************************************
程序名: 贪吃蛇
*********************************************************************/
/*********************************************************************
程序名: 贪吃蛇
*********************************************************************/
#define _CRT_SECURE_NO_WARNINGS
#include<cstdio>
#include<iostream>
#include<ctime>
#include<stdlib.h>
#include<windows.h>
#include <conio.h>
using namespace std;
#define frame_width 50
#define frame_height 25

typedef struct{
	int x, y;
} Food;
typedef struct{
	int x[100], y[100], len, state;
} Snake;

void gotoxy(int x, int y);  //最重要的一个函数,控制光标的位置
void print_map();
void get_newfood();//生成新食物
bool check_foodinsnake();//检查新食物有没有在蛇身上
void move_snake(); // 移动食物
void check_foodeating();//是否吃到食物
bool check_snakealive();//贪吃蛇是否还存活


//需要用到的全局变量
int score;
Snake snake;
Food food;
bool check_eaten;

int main()
{
	system("color 0B");
	do
	{
		printf("1:start\t2:exit\n");


		char com2;
		cin >> com2;
		if (com2 == '2')
			break;

		system("cls");
		score = 0, check_eaten = 0;
		print_map();
		//贪吃蛇的每回合运行控制
		while (1)
		{
			check_foodeating();//system("pause");
			move_snake();
			Sleep(max(50, 300 - score));//控制速度(与长度呈反比)
			if (!check_snakealive())
				break;
		}
		printf("Game Over!\n");
	} while (1);
}

void gotoxy(int x, int y)
{
	COORD pos;//COORD是一种自带结构体,表示一个字符在控制台屏幕上的坐标
	HANDLE han = GetStdHandle(STD_OUTPUT_HANDLE); //从标准输出设备里取出一个句柄
	pos.X = y, pos.Y = x;
	SetConsoleCursorPosition(han, pos);//定位光标的函数
}

void print_map()
{
	//打印墙壁
	for (int i = 0; i<frame_height; i++)
	{
		gotoxy(i, 0);
		printf("#");
		gotoxy(i, frame_width);//因为这个标记是长度,从零开始所以最后要减1
		printf("#");
	}
	for (int i = 0; i<frame_width; i++)
	{
		gotoxy(0, i);
		printf("#");
		gotoxy(frame_height, i);
		printf("#");
	}

	//蛇身初始化
	snake.len = 3;
	snake.state = 'w';
	snake.x[1] = frame_height / 2;
	snake.y[1] = frame_width / 2;
	gotoxy(snake.x[1], snake.y[1]);
	printf("@");
	for (int i = 2; i <= snake.len; i++)
	{
		snake.x[i] = snake.x[i - 1] + 1;
		snake.y[i] = snake.y[i - 1];
		gotoxy(snake.x[i], snake.y[i]);
		printf("@");
	}

	//打印初始食物
	get_newfood();

	//打印右边状态栏
	gotoxy(2, frame_width + 3);
	printf("WELCOME TO THE GAME OF RETRO SNAKE");
	gotoxy(4, frame_width + 3);
	printf("UP:   w");
	gotoxy(6, frame_width + 3);
	printf("DOWN: s");
	gotoxy(8, frame_width + 3);
	printf("LEFT: a");
	gotoxy(10, frame_width + 3);
	printf("RIGHT:d");
	gotoxy(12, frame_width + 3);
	printf("Your score:%d", score);
	gotoxy(28, frame_width + 3);
	printf("Made by majin");
}

bool check_foodinsnake()
{
	for (int i = 1; i <= snake.len; i++)
	if (snake.x[i] == food.x&&snake.y[i] == food.y)
		return 1;
	return 0;
}

void get_newfood()
{
	do{
		srand(time(0));
		food.x = rand() % (frame_height - 1) + 1;
		food.y = rand() % (frame_width - 1) + 1;
	} while (check_foodinsnake());
	gotoxy(food.x, food.y);
	cout << "$" << endl;
}

void move_snake()
{
	char com = 'n';
	while (_kbhit())//键盘有输入
		com = _getch();//从控制台读取一个字符,但不显示在屏幕上
	//没有吃到去除蛇尾
	if (!check_eaten)
	{
		gotoxy(snake.x[snake.len], snake.y[snake.len]);
		printf(" ");
	}
	//将除蛇头外的其他部分向前移动
	for (int i = snake.len; i>1; i--)
		snake.x[i] = snake.x[i - 1],
		snake.y[i] = snake.y[i - 1];
	//移动蛇头
	switch (com)
	{
	case 'w':
	{
				if (snake.state == 's') //如果命令与当前方向相反不起作用
					snake.x[1]++;
				else
					snake.x[1]--, snake.state = 'w';
				break;
	}
	case 's':
	{
				if (snake.state == 'w')
					snake.x[1]--;
				else
					snake.x[1]++, snake.state = 's';
				break;
	}
	case 'a':
	{
				if (snake.state == 'd')
					snake.y[1]++;
				else
					snake.y[1]--, snake.state = 'a';
				break;
	}
	case 'd':
	{
				if (snake.state == 'a')
					snake.y[1]--;
				else
					snake.y[1]++, snake.state = 'd';
				break;
	}
	default: //按其余键保持状态前进
	{
				 if (snake.state == 's')
					 snake.x[1]++;
				 else if (snake.state == 'w')
					 snake.x[1]--;
				 else if (snake.state == 'd')
					 snake.y[1]++;
				 else if (snake.state == 'a')
					 snake.y[1]--;
				 break;
	}
	}
	gotoxy(snake.x[1], snake.y[1]);
	printf("@");
	check_eaten = 0;
	gotoxy(frame_height, 0);
}

void check_foodeating()
{
	if (snake.x[1] == food.x&&snake.y[1] == food.y)
	{
		score += 10;
		check_eaten = 1;
		gotoxy(12, frame_width + 3);
		printf("Your score:%d", score);
		snake.len++;
		get_newfood();
	}
}

bool check_snakealive()
{
	//检查有没有撞到墙
	if (snake.x[1] == 0 || snake.x[1] == frame_height - 1 || snake.y[1] == 0 || snake.y[1] == frame_width - 1)//撞墙
		return 0;
	//检查有没有吃到自己
	for (int i = 2; i <= snake.len; i++)
	if (snake.x[i] == snake.x[1] && snake.y[i] == snake.y[1])
		return 0;
	return 1;
}



运行示例

1

在这里插入图片描述
在这里插入图片描述

  • 28
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很抱歉,动态规划与贪吃蛇拾金币问题并没有直接的关系。不过,我们可以通过编写代码来实现贪吃蛇拾金币的功能。以下是一个简单的C语言贪吃蛇拾金币的实现,其中包含了蛇的移动、金币的生成和吃掉金币等功能。 ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #include <conio.h> #include <windows.h> #define ROW 20 #define COL 30 #define SNAKE_LEN 5 int map[ROW][COL] = {0}; // 地图 int snake[SNAKE_LEN][2] = {0}; // 蛇 int food[2] = {0}; // 食物 int score = 0; // 得分 void init_map() // 初始化地图 { int i, j; for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { if (i == 0 || i == ROW - 1 || j == 0 || j == COL - 1) { map[i][j] = -1; // 边界 } else { map[i][j] = 0; // 空地 } } } } void init_snake() // 初始化蛇 { int i; for (i = 0; i < SNAKE_LEN; i++) { snake[i][0] = 1; snake[i][1] = i + 1; map[1][i + 1] = 1; // 蛇的初始位置 } } void init_food() // 初始化食物 { srand((unsigned)time(NULL)); int x, y; do { x = rand() % (ROW - 2) + 1; y = rand() % (COL - 2) + 1; } while (map[x][y] != 0); food[0] = x; food[1] = y; map[x][y] = 2; // 食物的位置 } void show() // 显示地图 { system("cls"); // 清屏 int i, j; for (i = 0; i < ROW; i++) { for (j = 0; j < COL; j++) { if (map[i][j] == -1) { printf("#"); // 边界 } else if (map[i][j] == 0) { printf(" "); // 空地 } else if (map[i][j] == 1) { printf("*"); // 蛇 } else if (map[i][j] == 2) { printf("$"); // 食物 } } printf("\n"); } printf("Score: %d\n", score); // 显示得分 } void move() // 移动蛇 { int i; int tail[2] = {snake[SNAKE_LEN - 1][0], snake[SNAKE_LEN - 1][1]}; for (i = SNAKE_LEN - 1; i > 0; i--) { snake[i][0] = snake[i - 1][0]; snake[i][1] = snake[i - 1][1]; } if (snake[0][0] == food[0] && snake[0][1] == food[1]) { // 吃到食物 SNAKE_LEN++; score++; init_food(); } snake[0][0] += tail[0] - snake[0][0]; snake[0][1] += tail[1] - snake[0][1]; if (map[snake[0][0]][snake[0][1]] == -1 || map[snake[0][0]][snake[0][1]] == 1) { // 撞墙或撞到自己 printf("Game Over!\n"); exit(0); } map[tail[0]][tail[1]] = 0; map[snake[0][0]][snake[0][1]] = 1; } int main() { init_map(); init_snake(); init_food(); while (1) { show(); move(); Sleep(200); // 控制蛇的速度 if (_kbhit()) { // 按键控制蛇的方向 char c = _getch(); if (c == 'w' && map[snake[0][0] - 1][snake[0][1]] != -1) { snake[0][0]--; } else if (c == 's' && map[snake[0][0] + 1][snake[0][1]] != -1) { snake[0][0]++; } else if (c == 'a' && map[snake[0][0]][snake[0][1] - 1] != -1) { snake[0][1]--; } else if (c == 'd' && map[snake[0][0]][snake[0][1] + 1] != -1) { snake[0][1]++; } } } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值