初学编程,有很多不规范的代码,bug可能也有点多,见笑了。直接上代码。
主函数我就放在最前面了
#include "snake.h"
#include "map.h"
#include "Food.h"
int nOpe = 0;
/*
双人贪吃蛇 操控键 玩家1 wsad 玩家2 ikjl 分别是上下左右。
撞到对方或者自己的身体时死亡,撞墙不会死亡。
如果两条蛇都撞死,游戏结束。并作出胜负判断。
请不要随意撞墙,否则都会暂停
项目逻辑:
1、用一个二维COORD数组存蛇。下标是【2】【100】,2表示分别存储player1,player2,
100是蛇的最大长度
2、双蛇的操作其实我也说不太清楚,借鉴了网上的思维。只有一个输入,所以有一蛇撞两
蛇停的问题。
大概的意思就是,获得一个Ope,判断如果是wsad就操作player1,如果是ikjl就操作player2。
3、既然用了二维数组,数据操作也就很好理解了,其实和操作单蛇是完全一样的,我这里
没有用循环结构,直接复制粘贴的,
这是因为数据就两个的原因,大家不要模仿。
4、我在分类上其实有一点问题,就是把Snake类作为主类的,它包含了map和Food。一般
要用map为主类。
5、没有菜单,大家可以自己加,游戏反正全打包了,就一个创建一个对象,调用Game
就可以
*/
int main()
{
snake obj1;
obj1.Game();
}
稍微整合了以下的控制台输入函数,它也包含了所有后面要用的宏,write.h和write.cpp
#pragma once
#include<windows.h>
#include <iostream>
#define 上 1
#define 下 2
#define 左 3
#define 右 4
#define MapX 50
#define MapY 40
#define 空地 0
#define 食物 1
#define 障碍物 2
#define 自己 3
//画笔
void fnWriteChar(int x, int y, const char* szCh, WORD color = 1 | 8);
void fnWriteNum(int x, int y, int nNum, WORD color);
#include "write.h"
void fnWriteChar(int x, int y, const char* szCh, WORD color )
{
//获得输出句柄;
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos = { x * 2,y };
SetConsoleCursorPosition(hOut, pos);
SetConsoleTextAttribute(hOut, color);
printf("%s", szCh);
}
void fnWriteNum(int x, int y, int nNum, WORD color)
{
//获得输出句柄;
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos = { x * 2,y };
SetConsoleCursorPosition(hOut, pos);
SetConsoleTextAttribute(hOut, color);
printf("%d", nNum);
}
简单的食物生成,不能移动的字符,food.h和food.cpp
#pragma once
#include"Write.h"
class CFood
{
public:
CFood();
//改变食物数量
void SetFoodNum(int nNum);
void fnCreatFood(int nMap[MapX][MapY]);
private:
int nFoodExit;
};
#include "Food.h"
CFood::CFood():nFoodExit(0)
{
}
//改变食物数量
void CFood::SetFoodNum(int nNum)
{
nFoodExit = nNum;
}
//生成食物
void CFood::fnCreatFood(int nMap[MapX][MapY])
{
int FoodX = rand() % (MapX - 2) + 1;
int FoodY = rand() % (MapY - 2) + 1;
if (nFoodExit == 0)
{
if (nMap[FoodX][FoodY] == 空地)
{
nMap[FoodX][FoodY] = 食物;
fnWriteChar(FoodX, FoodY, "★", 6);
nFoodExit = 1;
return;
}
}
}
map.h和map.cpp,这里用了个public的数据成员其实不太好,没改了。
#pragma once
#include"write.h"
class map
{
public:
//初始化
void fnInitGame();
//画地图
void fnDrawMap();
public:
int g_Map[MapX][MapY];
};
#include "map.h"
void map::fnInitGame()
{
for (int i = 0; i < MapX; i++)
{
for (int j = 0; j < MapY; j++)
{
if (i == 0 || j == 0 || i == MapX - 1 || j == MapY - 1)
{
g_Map[i][j] = 障碍物;
}
else
{
g_Map[i][j] = 空地;
}
}
}
}
//画地图
void map::fnDrawMap()
{
for (int i = 0; i < MapX; i++)
{
for (int j = 0; j < MapY; j++)
{
if (g_Map[i][j] == 障碍物)
{
fnWriteChar(i, j, "※", 7);
}
else if (g_Map[i][j] == 自己)
{
fnWriteChar(i, j, "■");
}
/*else if (g_Map[i][j] == 食物)
{
fnWriteChar(i, j, "★",6);
}*/
}
}
}
snake.h和snake.cpp
#pragma once
#include<conio.h>
#include "write.h"
#include"Food.h"
#include"map.h"
class snake
{
public:
snake();
int fnGetPlayerInfo1(int Ope);
int fnWaitChar1();
//覆盖蛇
void fnClearSnake(int nmap[MapX][MapY]);
//移动蛇
int fnMoveSnake(int dir, int nmap[MapX][MapY]);
// 画蛇
void fnDrawSnake(int nmap[MapX][MapY]);
void Game();
private:
COORD g_snake[2][100];
//蛇的方向和长度
int g_nDir;
int g_nlenth;
int g_nDir1;
int g_nlenth1;
//存活判断
int nlive1;
int nlive2;
//包了map和food对象
CFood food;
map map;
};
#include "snake.h"
snake::snake()
{
g_snake[0][0].X = 10;
g_snake[0][0].Y = 10;
g_snake[0][1].X = 10;
g_snake[0][1].Y = 9;
g_snake[0][2].X = 10;
g_snake[0][2].Y = 8;
g_snake[0][3].X = 10;
g_snake[0][3].Y = 7;
g_nDir = 2;
g_nlenth = 4;
nlive1=1;
g_snake[1][0].X = 15;
g_snake[1][0].Y = 10;
g_snake[1][1].X = 15;
g_snake[1][1].Y = 9;
g_snake[1][2].X = 15;
g_snake[1][2].Y = 8;
g_snake[1][3].X = 15;
g_snake[1][3].Y = 7;
g_nDir1 = 2;
g_nlenth1 = 4;
nlive2=1;
}
//获得用户输入
int snake::fnWaitChar1()
{
if (_kbhit())
{
char temp = _getch();
if ((g_nDir == 上 || g_nDir == 下) && (temp == 'w' || temp == 's'))
{
return 0;
}
if ((g_nDir == 左 || g_nDir == 右) && (temp == 'a' || temp == 'd'))
{
return 0;
}
if ((g_nDir1 == 上 || g_nDir1 == 下) && (temp == 'i' || temp == 'k'))
{
return 0;
}
if ((g_nDir1 == 左 || g_nDir1 == 右) && (temp == 'j' || temp == 'l'))
{
return 0;
}
else return temp;
}
}
int snake::fnGetPlayerInfo1(int Ope)
{
switch (Ope)
{
case 'w':
return g_nDir = 上;
break;
case 's':
return g_nDir = 下;
break;
case 'a':
return g_nDir = 左;
break;
case 'd':
return g_nDir = 右;
break;
case 'i':
return g_nDir1 = 上;
break;
case 'k':
return g_nDir1 = 下;
break;
case 'j':
return g_nDir1 = 左;
break;
case 'l':
return g_nDir1 = 右;
break;
default:
break;
}
return 1;
}
//覆盖蛇
void snake::fnClearSnake(int nmap[MapX][MapY])
{
if (nlive1)
{
for (int i = 0; i < g_nlenth; i++)
{
fnWriteChar(g_snake[0][i].X, g_snake[0][i].Y, " ");
}
nmap[g_snake[0][g_nlenth - 1].X][g_snake[0][g_nlenth - 1].Y] = 空地;
}
if (nlive2)
{
for (int i = 0; i < g_nlenth1; i++)
{
fnWriteChar(g_snake[1][i].X, g_snake[1][i].Y, " ");
}
nmap[g_snake[1][g_nlenth - 1].X][g_snake[1][g_nlenth - 1].Y] = 空地;
}
}
//移动蛇
int snake::fnMoveSnake(int dir,int nmap[MapX][MapY])
{
int tempX = g_snake[0][0].X;
int tempY = g_snake[0][0].Y;
int tempX1 = g_snake[1][0].X;
int tempY1 = g_snake[1][0].Y;
//蛇1的判断
switch (g_nDir)
{
case 上:
tempY--;
break;
case 下:
tempY++;
break;
case 左:
tempX--;
break;
case 右:
tempX++;
break;
}
if (nmap[tempX][tempY] == 障碍物)
{
return 0;
}
else if (nmap[tempX][tempY] == 食物)
{
g_nlenth++;
nmap[tempX][tempY] = 空地;
food.SetFoodNum(0);
fnWriteNum(56, 2, (g_nlenth-4)*10, 6);
}
else if (nmap[tempX][tempY] == 自己)
{
for (int i = 0; i < g_nlenth; i++)
{
fnWriteChar(g_snake[0][i].X, g_snake[0][i].Y, " ");
nmap[g_snake[0][i].X][g_snake[0][i].Y] = 空地;
}
nlive1 = 0;
}
//蛇2的判断
switch (g_nDir1)
{
case 上:
tempY1--;
break;
case 下:
tempY1++;
break;
case 左:
tempX1--;
break;
case 右:
tempX1++;
break;
}
if (nmap[tempX1][tempY1] == 障碍物)
{
return 0;
}
else if (nmap[tempX1][tempY1] == 食物)
{
g_nlenth1++;
nmap[tempX1][tempY1] = 空地;
food.SetFoodNum(0);
fnWriteNum(56, 4, (g_nlenth1 - 4) * 10, 6);
}
else if (nmap[tempX1][tempY1] == 自己)
{
for (int i = 0; i < g_nlenth; i++)
{
fnWriteChar(g_snake[1][i].X, g_snake[1][i].Y, " ");
nmap[g_snake[1][i].X][g_snake[1][i].Y] = 空地;
}
nlive2 = 0;
}
//蛇1改变坐标
if (nlive1)
{
for (int i = g_nlenth - 1; i >= 0; i--)
{
g_snake[0][i + 1].X = g_snake[0][i].X;
g_snake[0][i + 1].Y = g_snake[0][i].Y;
}
g_snake[0][0].X = tempX;
g_snake[0][0].Y = tempY;
}
//蛇2
if (nlive2)
{
for (int i = g_nlenth1 - 1; i >= 0; i--)
{
g_snake[1][i + 1].X = g_snake[1][i].X;
g_snake[1][i + 1].Y = g_snake[1][i].Y;
}
g_snake[1][0].X = tempX1;
g_snake[1][0].Y = tempY1;
}
}
//画蛇
void snake::fnDrawSnake(int nmap[MapX][MapY])
{
if (nlive1)
{
for (int i = 0; i < g_nlenth; i++)
{
fnWriteChar(g_snake[0][i].X, g_snake[0][i].Y, "■", 6);
}
nmap[g_snake[0][0].X][g_snake[0][0].Y] = 自己;
}
//画蛇2
if (nlive2)
{
for (int i = 0; i < g_nlenth1; i++)
{
fnWriteChar(g_snake[1][i].X, g_snake[1][i].Y, "■", 5);
}
nmap[g_snake[1][0].X][g_snake[1][0].Y] = 自己;
}
}
//最后把上面的整合一下,获得游戏主体函数
void snake::Game()
{
//初始化
map.fnInitGame();
map.fnDrawMap();
fnWriteChar(50, 2, "玩家1 积分:");
fnWriteChar(50, 4, "玩家2 积分:");
while (nlive1==1||nlive2==1)
{
fnClearSnake(map.g_Map);
int op1 = fnWaitChar1();
int dir1 = fnGetPlayerInfo1(op1);
fnMoveSnake(dir1, map.g_Map);
fnDrawSnake(map.g_Map);
Sleep(100);
food.fnCreatFood(map.g_Map);
}
//游戏结束输出结果
system("cls");
fnWriteChar(0,0, "比赛结果:",6);
printf("\n玩家1积分:%d", (g_nlenth - 4) * 10);
printf("\n玩家2积分:%d",(g_nlenth1 - 4) * 10);
if ((g_nlenth - 4) * 10 > (g_nlenth1 - 4) * 10)
{
printf("\n玩家1胜利!!!");
}
else if ((g_nlenth - 4) * 10 < (g_nlenth1 - 4) * 10)
{
printf("\n玩家2胜利!!!");
}
else
{
printf("\n打成平手!!!");
}
system("pause");
}
哈哈就这么多了,总感觉代码有点臃肿。
|