IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++贪吃蛇双人版 -> 正文阅读

[C++知识库]C++贪吃蛇双人版

初学编程,有很多不规范的代码,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");
}

哈哈就这么多了,总感觉代码有点臃肿。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-10 10:52:59  更:2021-12-10 10:54:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:58:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码