知识点总结:
内存管理:
最小单位:bit
最小管理单位:byte
main函数开始,一条一条语句从上往下执行
进制转换:数据本身就是数,不同进制只是表现形式不同
数据类型:int char float double unsigned signed short long
数据占内存段大小 数据存储方式
运算符,表达式,标示符,返回值,值,左值,右值,左操作数,右操作数
流程控制语句:
条件判断: if else switch case
跳转:goto
循环: for while dowhile continue break return
函数: 形参 实参 函数声明 函数定义 函数调用 返回值
指针:值传递 地址传递
地址:首地址 指针 指针变量 解引用* 指针变量的数学运算
数组:定义 访问(下标)
const:常量指针 指针常量
字符串:字符串字面量 字符串指针 字符数组
二维数组,二级指针
动态内存分配
动态数组
队列&栈
结构:结构和结构体 结构体的对齐补齐 typedef
链表
联合&枚举 大小端系统 bool类型
文件操作
预处理
贪吃蛇小游戏:
需求分析:
//贪吃蛇
1.蛇(动态数组,链表)
选择用链表
1.吃食物是插入插足,显示蛇是遍历操作。链表插入效率高,数组查找效率高
2.数组是连续内存段,如果蛇比较长,开辟内存失败风险高
2.食物
变量 数组
3.map地图
二维数组描述;空白:墙:蛇:食物
4.控制
整体:
while(1){
打印地图
接收用户输入
按照用户输入去改变
}
// 图形界面程序.cpp : 定义控制台应用程序的入口点。
//编译环境:Visual studio 2015
#include "stdafx.h"
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<windows.h>
#include<conio.h> //调用 _getch函数
#include<graphics.h> //需安装easyx,百度搜索即可
//MAP
#define ROW 20
#define COL 40
#define Space 20 //宏定义格式大小
enum map {//空白,墙,蛇,食物
space, wall, snake, food
};
IMAGE jpgs[4];
enum direction {//蛇移动方向,上0,下1,左5,右6
up, down, left = 5, right
};
int g_snake_dir = right;//默认移动方向
//初始化地图
int* pMap = NULL;
void InitMap();
void Initsnake();
//点类型
typedef struct MyPoint
{
int row;
int col;
}Point;
//用链表来描述蛇
typedef struct SnakeNode {
Point pos;
struct SnakeNode* next;
}snakeNode;
snakeNode* list = NULL;
//头插法插入结点到蛇链表中
void InsertNode(int row, int col);
//初始化游戏
void InitGame();
//显示游戏
void ShowGame();
//控制游戏
void ctolGame();
//判断某个点是不是蛇,食物,空白,墙
enum map isWhat(int row, int col);
//食物
Point Food[5] = { 0 };
//排除掉墙壁,蛇,食物后的数组
Point* pBuff = NULL;
int index = 0;
//初始化用作排除的函数
//void InitBuff();
//初始化食物
void InitFood();
//更新地图
void UpdateMap();
//蛇移动
void snake_move(int row, int col);
//蛇是否存活
bool isAlive = true;//全局变量
//图形界面蛇
void DrawGame();
int main()
{
InitGame();
while (isAlive) {
ShowGame();
DrawGame();
ctolGame();//有操作跟操作,无操作自动
}
system("cls");
printf("人生自古谁无死,少侠请重新来过!\n");
while (1);
return 0;
}
//图形界面蛇
void DrawGame() {
//system("cls");
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COL; j++) {
putimage(j*Space, i*Space, &jpgs[*(pMap + (i*COL) + j)]);
}
//printf("\n");
}
}
//头插法插入结点到蛇链表中
void InsertNode(int row, int col) {
snakeNode* pNew = (snakeNode*)malloc(sizeof(snakeNode));
pNew->pos.row = row;
pNew->pos.col = col;
pNew->next = list;
list = pNew;
/*if(list){
pNew -> next = list;
list = pNew;
}
else{
pNew -> next = list;
list = pNew;
}*/
}
//初始化地图
void InitMap() {
pMap = (int*)malloc(sizeof(int)*ROW*COL);
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COL; j++) {
//判断这个点是不是蛇
*(pMap + i*COL + j) = isWhat(i, j);
}
//printf("\n");
}
}
//初始化游戏
void InitGame() {
//0 初始化图形界面
//0.1 创建窗口
initgraph(COL * Space, ROW * Space, SHOWCONSOLE);
//0.2加载图片
//加载空白,墙,蛇,食物
loadimage(&jpgs[0], L"space.jpg", Space, Space, true);
loadimage(&jpgs[1], L"wall.jpg", Space, Space, true);
loadimage(&jpgs[2], L"snake.jpg", Space, Space, true);
loadimage(&jpgs[3], L"food.jpg", Space, Space, true);
//1.初始化蛇
Initsnake();
//2.初始化食物
//2.1初始化buff
pBuff = (Point*)malloc(sizeof(Point)*ROW*COL - 2 * ROW - 2 * (COL - 2) - 3);//开辟食物空间
InitFood();
/*
for (int i = 0; i<ROW; i++) {
for (int j = 0;j<COL; j++) {
if (isWhat(i, j) == space) {
pBuff[index].row = i;
pBuff[index].col = j;
index++;
}
}
}
//2.2初始化food
int sui_ji = rand()%index;
Food[0].row = pBuff[sui_ji].row;
Food[0].col = pBuff[sui_ji].col;
//Food[0].row = pBuff[30].row;
//Food[0].col = pBuff[30].col;*/
//3.初始化地图
InitMap();
}
//初始化蛇
//插入三个结点到链表中:分别是(2,2)(2,3)(2,4)->头
void Initsnake() {
for (int i = 0; i<3; i++) {
InsertNode(2, 2 + i);
}
}
//显示游戏
void ShowGame() {
system("cls");
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COL; j++) {
switch (*(pMap + (i*COL) + j)) {
case wall:printf("#"); break;
case snake:printf("*"); break;
case food:printf("@"); break;
case space:printf(" "); break;
}
}
printf("\n");
}
}
//控制游戏
void ctolGame() {
char n;
int snakeDir = g_snake_dir;
//scanf_s("%c", &n);
if (_kbhit()) {
n = _getch();
switch (n) {
case 'w':snakeDir = up; break;
case 'a':snakeDir = left; break;
case 's':snakeDir = down; break;
case 'd':snakeDir = right; break;
}
}
Sleep(300);
if ((snakeDir + g_snake_dir) % 10 == 1) {//用户自杀
isAlive = false;
return;
}
int row;
int col;
switch (g_snake_dir = snakeDir) {
case up: row = (list->pos.row) - 1; col = (list->pos.col); break;
case left: row = (list->pos.row); col = (list->pos.col) - 1; break;
case down: row = (list->pos.row) + 1; col = (list->pos.col); break;
case right: row = (list->pos.row); col = (list->pos.col) + 1; break;
}
switch (isWhat(row, col)) {
case food:
InsertNode(Food[0].row, Food[0].col);
InitFood();
snake_move(row, col); break;
case wall:
case snake:
isAlive = false; return;
case space:
snake_move(row, col); break;
}
/*g_snake_dir = snakeDir;
snake_move(g_snake_dir);//蛇移动
//如果碰到了食物,刷新地图
if (list->pos.row == Food[0].row && list->pos.col == Food[0].col) {
InsertNode(Food[0].row, Food[0].col);
InitFood();}*/
UpdateMap();//更新地图
}
//判断某个点是不是蛇,食物,空白,墙
enum map isWhat(int row, int col) {
if (row == 0 || col == 0 || row == (ROW - 1) || col == (COL - 1))
return wall;
//检查是否是蛇
snakeNode* temp = list;
while (temp) {
if (temp->pos.row == row && temp->pos.col == col) return snake;
temp = temp->next;
}
//检查是否是食物
for (int i = 0; i < 5; i++) {
if (Food[i].row == row && Food[i].col == col)
return food;
}
return space;
}
//初始化食物
void InitFood() {
//获取当前空白格子数目
index = 0;
for (int i = 0; i<ROW; i++) {
for (int j = 0; j<COL; j++) {
if (isWhat(i, j) == space) {
pBuff[index].row = i;
pBuff[index].col = j;
index++;
}
}
}
//2.2初始化food
int sui_ji = rand() % index;
Food[0].row = pBuff[sui_ji].row;
Food[0].col = pBuff[sui_ji].col;
}
//更新地图
void UpdateMap() {
pMap = (int*)malloc(sizeof(int)*ROW*COL);
for (int i = 0; i < ROW; i++) {
for (int j = 0; j < COL; j++) {
//判断这个点是不是蛇
*(pMap + i*COL + j) = isWhat(i, j);
}
}
}
//蛇移动
void snake_move(int row, int col) {
//1.去尾
snakeNode* pTemp = list;
//1.1找到倒数第二个节点
while (pTemp->next->next != NULL)
pTemp = pTemp->next;
//1.2释放最后一个节点内存
free(pTemp->next);
//1.3倒数第二个结点next指向NULL
pTemp->next = NULL;
/*//2.加头(更新到控制函数中)
int row;
int col;
switch (dir) {
case up: row = (list->pos.row) - 1; col = (list->pos.col); break;
case left: row = (list->pos.row); col = (list->pos.col) - 1; break;
case down: row = (list->pos.row) + 1; col = (list->pos.col); break;
case right: row = (list->pos.row); col = (list->pos.col) + 1; break;
}*/
InsertNode(row, col);
}
运行结果: