• C语言练手游戏-控制台输出一个会移动的坦克


    把C语言的知识融合起来做一个练手的小游戏项目,将自己掌握到的数据结构、数组、函数、宏定义等知识综合利用,增加对语法的熟练程度。

    操作系统: windows 10 x64
    编译IDE : VS2015

      // 实现一个能在屏幕上自由移动的坦克.cpp : 定义控制台应用程序的入口点。
    
    
    #include "stdafx.h"
    #include <windows.h>
    #include <conio.h>
    
    
    //方向宏定义
    #define  UP    0
    #define  DOWN  1
    #define  LEFT  2
    #define  RIGHT 3
    
    
    
    //全局数组,画地图用
    int g_map[40][40] = { 0 };
    
    
    //坦克数据结构
    typedef struct _TANKINFO
    {
    	unsigned int nNosX;                   //坦克X坐标 
    	unsigned int nNosY;					  //坦克Y坐标 
    	unsigned int nLevel;				  //坦克等级
    	unsigned int nMaxHP;				  //坦克最大血值
    	unsigned int nCurlHP;				  //坦克当前血值
    	unsigned int nOldSpeed;				  //坦克原始速度
    	unsigned int nSpeed;				  //坦克当前速度
    	unsigned int nDirection;			  //坦克方向
    	unsigned int nGodirection;			  //坦克想要改变的方向
    	unsigned int nKill;					  //坦克杀敌数
    	unsigned int nDie;					  //坦克死亡数
    	unsigned int wColor;				  //坦克颜色
    	unsigned int nIndex;				  //坦克在数组中的数值
    	unsigned int nBulletType;			  //初始坦克的子弹类型
    	bool         bSubSpeed;				  //是否被减速
    	char*        szForm;				  //坦克组成的样子
    	char*        szBuff;				  //状态
    }TANKINFO,*PTANKINFO;
    
    TANKINFO tank;
    
    
    //坦克样式结构,上下左右方向
    int tankstyle[4][3][3] =
    {
    	//方向向上的坦克
    	{
    		{0,1,0},
    		{1,1,1},
    		{1,0,1}
    
    	},
    
    	//方向向下的坦克
    	{
    		{1,0,1},
    		{1,1,1},
    		{0,1,0}
    	},
    
    	//方向向左的坦克
    	{
    		{0,1,1},
    		{1,1,0},
    		{0,1,1}
    	},
    
    	//方向向右的坦克
    	{
    		{1,1,0},
    		{0,1,1},
    		{1,1,0}
    	}
    };
    
    //血量绘画
    char *m_blood[10] = {" ①","②","③","④","⑤","⑥","⑦","⑧","⑨","⑩" };
    
    
    //按键接收
    char KeyBoardMonitor() 
    {
    	char ch;
    	if (_kbhit())
    	{
    		ch = _getch();
    	}
    	else
    	{
    		return 0;
    	}
    	return ch;
    }
    
    //画图函数
    void writeChar(int High, int Wide, char * pszChar, WORD wArr)
    {
    	//设置光标属性
    	CONSOLE_CURSOR_INFO cci;
    	cci.dwSize = 1;        // 光标百分比厚度(1~100)
    	cci.bVisible = FALSE; //是否显示光标
    	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci);
    	//设置坐标
    	COORD loc;
    	loc.X = Wide * 2; //X的值是Wide的2倍;
    	loc.Y = High;
    	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), wArr);
    	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), loc);
    	printf(pszChar);  //打印时需要注意有些特殊字符是占2个字节
    }
    
    
    //清除坦克
    void clsTank() 
    {
    	for (unsigned int y = tank.nNosY - 1,i=0;  y <= tank.nNosY + 1;  y++,i++)
    	{
    		for (unsigned int x = tank.nNosX-1,j=0;x<= tank.nNosX+1;x++,j++)
    		{
    			//用坦克的方向对照坦克模型数组,把坦克在界面上画出来
    			writeChar(y, x, "  ",FOREGROUND_GREEN);
    
    		}
    	}
    }
    
    //绘画坦克
    void DrawTank()
    {
    	for (unsigned int y = tank.nNosY - 1, i = 0; y <= tank.nNosY + 1; y++, i++)
    	{
    		for (unsigned int x = tank.nNosX - 1, j = 0; x <= tank.nNosX + 1; x++, j++)
    		{
    			//用坦克的方向对照坦克模型数组,把坦克在界面上画出来
    			writeChar(y, x, tankstyle[tank.nDirection][i][j] == 1 ? "█" : "  ", FOREGROUND_RED);
    
    		}
    	}
    }
    
    
    //坦克撞墙检测
    bool allowMove() 
    {
    	if ((tank.nNosX <= 1)
    		||
    		(tank.nNosX >= 38)                                            //画图边界判断
    		||
    		(tank.nNosY <= 2)
    		||
    		(tank.nNosY >= 38)
    		)
    	{
    		return false;
    	}
    	return true;
    }
    
    //移动坦克
    void moveTank() 
    {
    
    
    	clsTank();
    
    	//碰撞检查
    	if (allowMove() == false)
    	{
    		MessageBoxA(0, "撞墙啦!", "扑街", 0);
    		clsTank();
    		DrawTank();
    	}
    
    
    		if (tank.nDirection != tank.nGodirection)
    		{
    			tank.nDirection = tank.nGodirection;                                //根据键盘获取到的键盘赋值到现有的方向
    		}
    		else
    		{
    
    			switch (tank.nGodirection)
    			{
    			case UP:
    			{
    				tank.nNosY--;
    				break;
    			}
    
    			case DOWN:
    			{
    				tank.nNosY++;
    				break;
    			}
    
    			case LEFT:
    			{
    				tank.nNosX--;
    				break;
    			}
    
    			case RIGHT:
    			{
    				tank.nNosX++;
    				break;
    			}
    			}
    		}
    	
    
    	DrawTank();
    
    }
    
    //画出地图
    void DrawMap() 
    {
    	//遇到四周,那么写入1
    	for (int row = 0; row < 40; row++)
    	{
    		for (int col = 0; col < 40; col++)
    		{
    			if ((row == 0)
    				||
    				(row == 39)
    				||
    				(col == 0)
    				||
    				(col == 39)
    				)
    			{
    				g_map[row][col] = 1;
    			}
    			else
    			{
    				g_map[row][col] = 0;
    
    			}
    		}
    	}
    	//输出所有的地图
    	for (int row = 0; row < 40; row++)
    	{
    		for (int col = 0; col < 40; col++)
    		{
    			if (g_map[row][col] == 1)
    			{
    				printf("■");
    			}
    			else
    			{
    				printf("  ");
    			}
    		}
    		printf("
    ");
    	}
    
    }
    
    
    int main()
    {
    	//给坦克赋值
    	tank.nNosX = 10;
    	tank.nNosY = 10;
    	
    	//画出地图
    	DrawMap();
    	//画出坦克
    	DrawTank();
    
    	char ch;
    	while(true)
    	{
    		ch = KeyBoardMonitor();
    		if (ch == 0)
    		{
    			continue;
    		}
    		if (ch == VK_ESCAPE) 
    		{
    			break;
    		}
    		switch (ch)
    		{
    		case 'w':
    		{
    			tank.nGodirection = UP;
    		}
    		break;
    		case 's':
    		{
    			tank.nGodirection = DOWN;
    		}
    		break;
    		case 'a':
    		{
    			tank.nGodirection = LEFT;
    		}
    		break;
    		case 'd':
    		{
    			tank.nGodirection = RIGHT;
    		}
    		break;
    		}
    		moveTank();
    	}
    
    
        return 0;
    }
    
    
    

    运行效果

  • 相关阅读:
    高级人力资源管理最喜欢的工具;笔迹分析测试的六大好处
    我与时尚MM的那些事儿
    当幸福来敲门
    perl 模板
    一些R函数【自己使用过,保存】
    关于异步加载、缓存图片、软引用等
    android线程同步
    现半透明的popupwindow
    android中的MotionEvent 及其它事件处理
    android客户端从服务器端获取json数据并解析
  • 原文地址:https://www.cnblogs.com/17bdw/p/6048060.html
Copyright © 2020-2023  润新知