构造函数(推箱子)
// 推箱子(构造函数).cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#include <iostream>
using namespace std;
#define KEY_DOWN(vk_code) GetAsyncKeyState(vk_code)&0x8000?1:0
//使用枚举来控制箭头移动与菜单切换
//枚举和结构体可以放在main函数外
enum{
E_MENU_START,
E_MENU_SETTING,
E_MENU_EXIT
};
enum{
E_GAME_MENU,
E_GAME_MAP,
E_GAME_SETTING
};
//定义玩家的结构体
struct SPlayer
{
//定义结构体属性成员变量)
int nRow;
int nCol;
int nRowBk;
int nColBk;
//用构造函数初始化对象
SPlayer(int nInRow,int nInCol) //用于初始化,传入两个参数(行、列)
{
nRow = nInRow;
nCol = nInCol;
nRowBk = nInRow;
nColBk = nInCol;
}
//用函数重写备份坐标的方法
void backup()
{
nRowBk = nRow;
nColBk = nCol;
}
void revert()
{
nRow = nRowBk;
nCol = nColBk;
}
};
struct SBox
{
int nBoxRow;
int nBoxCol;
int nBoxRowBk;
int nBoxColBk;
SBox(int nInBoxRow, int nInBoxCol)
{
nBoxRow = nInBoxRow;
nBoxCol = nInBoxCol;
nBoxRowBk = nInBoxRow;
nBoxColBk = nInBoxCol;
}
void backup()
{
nBoxColBk = nBoxRow;
nBoxColBk = nBoxCol;
}
void revert()
{
nBoxRow = nBoxRowBk;
nBoxCol = nBoxColBk;
}
};
struct SGoal
{
int nGoalRow;
int nGoalCol;
SGoal(int nInGoalRow, int nInGoalCol)
{
nGoalRow = nInGoalRow;
nGoalCol = nInGoalCol;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
int arrMap[15][20] = {
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
};
//定义应放在main函数中
//玩家的定义
//SPlayer player;
//玩家对象属性的访问:对象名.属性名
/*
player.nRow = 7;//定义玩家的行
player.nCol = 10;//定义玩家的列
player.nRowBk = 0;
player.nColBk = 0;
*/
//对象的定义,可以同时访问属性
SPlayer player(7, 10);
// SPlayer player1(8, 9);
// SPlayer player2(8, 9);
//定义箱子
//因为箱子的数量有多个,定义为数组
/*
SBox arrBox[3];
for (int k = 0; k < 3; k++)
{
arrBox[k].nBoxRow = 7;
arrBox[k].nBoxCol = 7 + k;//不能是arrBox[k].nBoxCol += 7;因为它是一个未定值
}
*/
//数组的定义:数组类型+数组名称[个数]
SBox arrBox[3] = { SBox(7,7), SBox(7, 8), SBox(7, 9) };
//定义坑
/*
SGoal arrGoal[3];
for (int k = 0; k < 3; k++)
{
arrGoal[k].nGoalRow = 5;
arrGoal[k].nGoalCol = 5 + k;//不能是arrBox[k].nBoxCol += 7;因为它是一个未定值
}
*/
SGoal arrGoal[3] = { SGoal(12, 10), SGoal(12, 5), SGoal(12, 7) };
int nMenuState = 0;//用于控制箭头
int nGameState = 0;//用于切换菜单
while (true)//用于进行循环刷新
{
//菜单界面
if (E_GAME_MENU == nGameState)//如果界面的值为0,当前为菜单界面
{
//把数据换成枚举值
/*
if (KEY_DOWN(VK_DOWN))//检测是否按下向下箭头
{
nMenuState++;//控制箭头的值增加1
if (nMenuState > 2)//因为菜单一共只有三个选项,所以当控制箭头的数量大于2时,重新赋值为0,返回到箭头的初始位置
{
nMenuState = 0;
}
}
*/
if (KEY_DOWN(VK_DOWN))//检测是否按下向下箭头
{
nMenuState++;//控制箭头的值增加1
if (nMenuState > E_MENU_EXIT)//因为菜单一共只有三个选项,所以当控制箭头的数量大于2时,重新赋值为0,返回到箭头的初始位置
{
nMenuState = E_MENU_START;
}
}
else if (KEY_DOWN(VK_UP))//同上
{
nMenuState--;
if (nMenuState < E_MENU_START)
{
nMenuState = E_MENU_EXIT;
}
}
if (KEY_DOWN(VK_RETURN))//检测是否按下Enter键
{
if (E_MENU_START == nMenuState)//如果当前箭头位置为游戏开始
{
nGameState = E_GAME_MAP;//设置界面的值为1,从菜单界面切换为地图界面
}
else if (E_MENU_SETTING == nMenuState)//如果当前箭头位置为游戏设置
{
nGameState = E_GAME_SETTING;//设置界面的值为2,从菜单界面切换为游戏设置界面
}
else if (E_MENU_EXIT == nMenuState){
nGameState = E_GAME_MENU;
}
}
//画出菜单
cout << "■■■■■■■■■■■■■■■■■■■■" << endl;//因为放在while(true)里面,所以这里会一直运行
cout << "■■■■■■■■■■■■■■■■■■■■" << endl;
if (0 == nMenuState)//画箭头位置
{
cout << "■■■ ->游戏开始 ■■■" << endl;
cout << "■■■ 游戏设置 ■■■" << endl;
cout << "■■■ 游戏退出 ■■■" << endl;
}
else if (1 == nMenuState)
{
cout << "■■■ 游戏开始 ■■■" << endl;
cout << "■■■ ->游戏设置 ■■■" << endl;
cout << "■■■ 游戏退出 ■■■" << endl;
}
else if (2 == nMenuState){
cout << "■■■ 游戏开始 ■■■" << endl;
cout << "■■■ 游戏设置 ■■■" << endl;
cout << "■■■ ->游戏退出 ■■■" << endl;
}
cout << "■■■■■■■■■■■■■■■■■■■■" << endl;
cout << "■■■■■■■■■■■■■■■■■■■■" << endl;
}
//地图界面
if (E_GAME_MAP == nGameState)
{
//在玩家移动前对坐标进行备份,把坐标赋给值的变量
/*
player.nRowBk = player.nRow;//nPlayerRow = 3; nPlayerCol = 3
player.nColBk = player.nCol;
*/
//调用备份函数对玩家坐标进行备份
player.backup();
for (int k = 0; k < 3; k++)
{
/*
arrBox[k].nBoxRowBk = arrBox[k].nBoxRow;
arrBox[k].nBoxColBk = arrBox[k].nBoxCol;
*/
arrBox[k].backup();
}
if (KEY_DOWN(VK_SPACE))//按空格键
{
nGameState = E_GAME_MENU;//返回菜单界面
}
//数据更新,要在渲染的前面
//设置按键让小人移动
if (KEY_DOWN(VK_UP))
{
player.nRow--;//玩家向上移动,nPlayerRow = 2
}
else if (KEY_DOWN(VK_DOWN))
{
player.nRow++;
}
else if (KEY_DOWN(VK_LEFT))
{
player.nCol--;
}
else if (KEY_DOWN(VK_RIGHT))
{
player.nCol++;
}
//检测玩家是否撞墙
if (1 == arrMap[player.nRow][player.nCol]) //当玩家的值为1
{
/*
player.nRow = player.nRowBk;//把现在玩家的值赋值给之前的索引,nPlayerRow = 3,位置不变
player.nCol = player.nColBk;
*/
player.revert();
}
//实现玩家推箱子
for (int k = 0; k < 3; k++)
{
if (arrBox[k].nBoxRow == player.nRow && arrBox[k].nBoxCol == player.nCol)
{
arrBox[k].nBoxRow += (player.nRow - player.nRowBk);
arrBox[k].nBoxCol += (player.nCol - player.nColBk);
}
}
//检测箱子是否撞墙
for (int k = 0; k < 3; k++)
{
if (1 == arrMap[arrBox[k].nBoxRow][arrBox[k].nBoxCol])
{
/*
arrBox[k].nBoxRow = arrBox[k].nBoxRowBk;
arrBox[k].nBoxCol = arrBox[k].nBoxColBk;
player.nRow = player.nRowBk;
player.nCol = player.nColBk;
*/
//箱子返回备份坐标
arrBox[k].revert();
//玩家返回备份坐标
player.revert();
}
}
//检测是否两个箱子相遇
for (int k = 0; k < 3; k++)
{
for (int j = 0; j < 3; j++)
{
if (k != j)
{
if (arrBox[k].nBoxRow == arrBox[j].nBoxRow && arrBox[k].nBoxCol == arrBox[j].nBoxCol)
{
//箱子要返回备份坐标
/*
arrBox[k].nBoxRow = arrBox[k].nBoxRowBk;
arrBox[k].nBoxCol = arrBox[k].nBoxColBk;
arrBox[j].nBoxRow = arrBox[j].nBoxRowBk;
arrBox[j].nBoxCol = arrBox[j].nBoxColBk;
*/
arrBox[k].revert();
arrBox[j].revert();
//玩家返回备份坐标
/*
player.nRow = player.nRowBk;
player.nCol = player.nColBk;
*/
player.revert();
}
}
}
}
//检测三个箱子都进洞
//统计,用一个变量记录
int nDrawEnd = 0;
for (int k = 0; k < 3; k++)
{
for (int m = 0; m < 3; m++)
{
if (arrBox[k].nBoxRow == arrGoal[m].nGoalRow && arrBox[k].nBoxCol == arrGoal[m].nGoalCol)
{
nDrawEnd++;
break;
}
}
}
//渲染
//二维数组的遍历
for (int i = 0; i < 15; i++) //行数为15
{
for (int j = 0; j < 20; j++)//列数为20
{
//else if中不能有for循环,但是又需要画多个箱子
//用一个bool值判断是否画箱子
bool bDrawBox = false;
bool bDrawGoal = false;
for (int k = 0; k < 3; k++)
{
if (i == arrBox[k].nBoxRow && j == arrBox[k].nBoxCol) //当箱子的行为当前的行,列为当前的列,画箱子
{
//由于这里不能直接画箱子,因为画箱子要放在else if的条件中,所以定义一个状态位,把状态位改为true
bDrawBox = true;
break;
}
}
for (int m = 0; m < 3; m++)
{
if (i == arrGoal[m].nGoalRow && j == arrGoal[m].nGoalCol)
{
bDrawGoal = true;
break;
}
}
//判断第i行第j列应该画什么
if (1 == arrMap[i][j])//把数字为1的地方替换为■,作为墙壁
{
cout << "■";
}
else if (i == player.nRow && j == player.nCol)//如果当前的行为玩家的行,当前的列为玩家的列(当前的位置为玩家的位置)
{
cout << "人";
}
else if (bDrawBox)//状态位为true,执行画箱子的操作
{
cout << "箱";
}
else if (bDrawGoal)
{
cout << "洞";
}
else
{
cout << " ";//数字为0的地方设为空格
}
}
cout << endl;//换行,排列成二维数组的形状
}
//在二维数组外面画“游戏结束”
if (nDrawEnd >= 3)
{
nGameState = 3;
//cout << "游戏结束";
}
}
//设置界面
if (2 == nGameState)
{
if (KEY_DOWN(VK_SPACE))
{
nGameState = 0;
}
cout << "我是设置页面" << endl;
}
//退出界面
else if (3 == nGameState)
{
cout << "我是退出页面" << endl;
if (KEY_DOWN(VK_SPACE))
{
nGameState = 0;
}
}
system("cls");
}
system("pause");
return 0;
}
构造函数(贪吃蛇)
// 贪吃蛇(构造函数).cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <time.h>
#include <vector>
using namespace std;
#define KEY_DOWN(vk_code) GetAsyncKeyState(vk_code)&0x8000?1:0
int arrMap[15][15] = {
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
};
//控制方向的枚举值
enum
{
E_DIR_NONE
};
int nDir = E_DIR_NONE;
//节点的结构体
struct SNode{
int nNodeRow;
int nNodeCol;
int nNodeRowBk;
int nNodeColBk;
SNode()
{
nNodeRow = 0;
nNodeCol = 0;
nNodeRowBk = 0;
nNodeColBk = 0;
}
SNode(int nInRow, int nInCol)
{
nNodeRow = nInRow;
nNodeCol = nInCol;
nNodeRowBk = nInRow;
nNodeColBk = nInCol;
}
//节点的备份
void backup()
{
nNodeRowBk = nNodeRow;
nNodeColBk = nNodeCol;
}
};
//蛇的结构体
struct SSnake
{
int nRow;
int nCol;
int nSpeed;
int nDir;
//用于传入参数
SSnake(int nInRow,int nInCol)
{
nRow = nInRow;
nCol = nInCol;
}
//节点的容器
vector<SNode> vecSnake;
//速度的构造函数
SSnake (int nInSpeed)
{
//初始化压蛇头
vecSnake.push_back(SNode(5,5));
nInSpeed = nInSpeed;
nDir = 0;
}
//蛇头的备份
void backupHead()
{
vecSnake[0].backup();
}
//移动
void move()
{
if (nDir <= 3)
{
if (0 == nDir)
{
vecSnake[0].nNodeRow--;
}
else if (1 == nDir)
{
vecSnake[0].nNodeRow++;
}
else if (2 == nDir)
{
vecSnake[0].nNodeCol--;
}
else if (3 == nDir)
{
vecSnake[0].nNodeCol++;
}
}
}
//是否碰到蛇头,蛇吃食物
bool isExistHead(int nInRow,int nInCol)
{
if (vecSnake[0].nNodeRow == nInRow && vecSnake[0].nNodeCol == nInCol)
{
return true;
}
return false;
}
//长身体
void addBody()
{
vecSnake.push_back(SNode());
}
//跟随
void follow()
{
for (int i = 1; i < vecSnake.size(); i++)
{
//备份当前这一节的坐标
/* vecSnake[i].nNodeRowBk = vecSnake[i].nNodeRow;
vecSnake[i].nNodeColBk = vecSnake[i].nNodeCol;*/
vecSnake[i].backup();
}
for (int i = 0; i < vecSnake.size() - 1; i++)
{
//把当前节的坐标给下一节
vecSnake[i + 1].nNodeRow = vecSnake[i].nNodeRowBk;
vecSnake[i + 1].nNodeCol = vecSnake[i].nNodeColBk;
}
}
//渲染蛇
bool isExist(int nRow,int nCol)
{
for (int k = 0; k < vecSnake.size(); k++)
{
if (nRow == vecSnake[k].nNodeRow && nCol == vecSnake[k].nNodeCol)
{
return true;
}
}
return false;
}
//蛇头撞墙
void isCrashWall()
{
if (1 == arrMap[vecSnake[0].nNodeRow][vecSnake[0].nNodeCol])
{
cout << "Game over!" << endl;
}
}
//蛇头撞身体
void isCrashSelf()
{
for (int i = 1; i < vecSnake.size(); i++)
{
if ((vecSnake[0].nNodeRow == vecSnake[i].nNodeRow) && (vecSnake[0].nNodeCol == vecSnake[i].nNodeCol))
{
cout << "Game over!" << endl;
}
}
}
};
//食物的结构体
struct SFood{
int nFoodRow;
int nFoodCol;
SFood(int nInFoodRow, int nInFoodCol)
{
nFoodRow = nInFoodRow;
nFoodCol = nInFoodCol;
}
//食物随机生成
void randPos()
{
/*sFood.nFoodRow = rand() % 13 + 1;
sFood.nFoodCol = rand() % 13 + 1;*/
nFoodRow = rand() % 13 + 1;
nFoodCol = rand() % 13 + 1;
}
};
//创建一个snake对象,给两次循环的速度
SSnake snake(2);
SFood sFood(5,6);
int _tmain(int argc, _TCHAR* argv[])
{
//因为只压入了一个蛇头,所以此时的vecSnake[0]就是蛇头
//初始化蛇头的方向
/*vecSnake[0].nNodeRow = 5;
vecSnake[0].nNodeCol = 5;
vecSnake[0].nNodeRowBk = 0;
vecSnake[0].nNodeColBk = 0;*/
//定义蛇的长度变量
//int nLen = 1;
//随机种子初始化
srand(time(nullptr));
//初始化食物
//SFood sFood;
//数据更新,要在渲染的前面
//刷新
while (true)
{
//蛇头移动之前要进行坐标备份
/*vecSnake[0].nNodeRowBk = vecSnake[0].nNodeRow;
vecSnake[0].nNodeColBk = vecSnake[0].nNodeCol;*/
snake.backupHead();
//数据更新,要在渲染的前面
//让蛇根据按键的方向一直动
snake.move();
//设置按键让贪吃蛇改变方向
if (KEY_DOWN(VK_UP))
{
snake.nDir = 0;
}
else if (KEY_DOWN(VK_DOWN))
{
snake.nDir = 1;
}
else if (KEY_DOWN(VK_LEFT))
{
snake.nDir = 2;
}
else if (KEY_DOWN(VK_RIGHT))
{
snake.nDir = 3;
}
//随机生成食物
//sFood.randPos();
//蛇吃食物
//if (vecSnake[0].nNodeRow == sFood.nFoodRow && vecSnake[0].nNodeCol == sFood.nFoodCol)
if (snake.isExistHead(sFood.nFoodRow,sFood.nFoodCol))
{
//再次随机生成食物,让食物的位置变化
/*sFood.nFoodRow = rand() % 13 + 1;
sFood.nFoodCol = rand() % 13 + 1;*/
sFood.randPos();
//把身体压入容器中,这里要用到前面构造的一个无参的构造函数
snake.addBody();
}
//身体跟随蛇头
snake.follow();
//检测蛇头是否幢墙
snake.isCrashWall();
//蛇头与蛇身的碰撞
snake.isCrashSelf();
//渲染
for (int i = 0; i < 15; i++)
{
for (int j = 0; j < 15; j++)
{
if (1 == arrMap[i][j])
{
cout << "■";
}
else if (snake.isExist(i,j))
{
cout << "蛇";
}
else if (i == sFood.nFoodRow && j == sFood.nFoodCol)
{
cout << "肉";
}
else
{
cout << " ";
}
}
cout << endl;//数组换行输出
}
Sleep(60);
system("cls");
}
system("pause");
return 0;
}