C++实现基于控制台界面的吃豆子游戏

   2015-06-23 0
核心提示:这篇文章主要介绍了C++实现基于控制台界面的吃豆子游戏,实例分析了吃豆子游戏的原理与C++实现技巧,具有一定参考借鉴价值,需要的朋友可以参考下

本文实例讲述了C++实现基于控制台界面的吃豆子游戏。分享给大家供大家参考。具体分析如下:

程序运行界面如下所示:

ESC键可退出游戏。

main.cpp源文件如下:

#include "lib.h"
#pragma once
extern int level;
int main()
{
 FOOD food;
 WALL wall;
 BODY CurPos;
 HALL hall;
 int iExit = 0;
 while(1)
 {
  if(iExit)
   break;
  Init(&food,&wall,&CurPos,&hall);
  MakeWall(&wall);
  while(1)
  {
   Sleep(200);
   int res = Move(&food,&wall,&CurPos);
   if(1 == res) //重新开局
    break;
   else if(-1 == res) //用户退出
   {
    iExit = 1;
    break;
   }
   ShowScore(&CurPos,&food);
  }
 }
 return 0;
}

lib.h头文件如下:

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <time.h>
//标识用户按下的方向键
#define KEY_UP    WM_USER + 1
#define KEY_DOWN   WM_USER + 2
#define KEY_LEFT   WM_USER + 3
#define KEY_RIGHT   WM_USER + 4
//标识用户当前运动方向
#define DIRECTION_UP  WM_USER + 5
#define DIRECTION_DOWN  WM_USER + 6
#define DIRECTION_LEFT  WM_USER + 7
#define DIRECTION_RIGHT  WM_USER + 8
//标识要打印的元素类型
#define PRINT_WALL   WM_USER + 9
#define PRINT_FOOD   WM_USER + 10
#define PRINT_BODY   WM_USER + 11
#define PRINT_CLEAN   WM_USER + 12
#define KNOCK_WALL   WM_USER + 13
#define KNOCK_FOOD   WM_USER + 14
struct POS
{
 int x;
 int y;
};
struct WALL
{
 POS pos[9999];
 int len;
};
struct FOOD
{
 POS pos[8];
 int len;
 int IsHidden;
};
struct BODY
{
 POS pos;
 int Direction;
};
struct HALL{
 POS pos[200];
 int len;
};
void Init(FOOD *pFood,WALL *pWall,BODY *pBody,HALL *pHall);
//进行一些初始化操作
void Print(POS *pos,int TYPE,int ix = 0);
//完成打印功能
void MakeWall(WALL *pWall);
//生成墙
void MakeFood(HALL *pHall,FOOD *pFood);
//生成食物
int Move(FOOD *pFood,WALL *pWall,BODY *pBody);
//用户移动
void ShowScore(BODY *pBody,FOOD *pFood);
//显示等级 和剩余豆子数
int IsOver(POS pos1,POS pos2,int TYPE);
//判断2点是否重合
int IsKnock(WALL *pWall,BODY *pBody,FOOD *pFood,int TYPE);
//判断是否撞墙、吃到豆子
int GetKey();
//得到用户按键

lib.cpp源文件如下:

#include "lib.h"
#pragma once
HANDLE hMain_Out;
HANDLE hMain_In;
CONSOLE_CURSOR_INFO info;
int iBeans = 0;
int level = 1;
//extern short wall[17][24];
short wall[17][24] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     0,-1,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,
     0,-1,-1,-1,-1,-1,-1,0,0,0,0,0,0,-1,0,0,0,0,0,-1,-1,-1,0,0,
     0,-1,0,0,0,-1,0,0,0,0,0,0,0,-1,0,0,0,0,0,-1,0,0,0,0,
     0,-1,-1,-1,-1,-1,0,-1,-1,-1,-1,-1,0,-1,0,-1,-1,-1,-1,-1,-1,-1,0,0,
     0,-1,0,0,-1,0,-1,0,0,0,0,-1,0,-1,-1,-1,0,0,0,0,0,0,0,0,
     0,-1,-1,-1,-1,-1,-1,0,0,0,0,-1,0,0,0,-1,0,0,0,0,0,0,0,0,
     0,-1,0,0,0,0,0,0,0,0,0,-1,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,0,
     0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,-1,0,0,-1,0,0,0,0,
     0,0,0,0,0,0,-1,0,0,0,0,0,0,0,-1,0,-1,0,0,-1,0,0,0,0,
     0,0,0,0,0,0,-1,0,0,0,0,0,0,0,-1,0,-1,-1,-1,-1,0,-1,-1,0,
     0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,-1,0,0,
     0,0,0,0,0,-1,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,-1,0,0,
     0,0,-1,-1,-1,-1,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,
     0,-1,-1,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,
     0,0,-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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
/**********************************
* 功能:
* 判断用户与墙相撞或吃到食物
***********************************/
int IsKnock(WALL *pWall,BODY *pBody,FOOD *pFood,int TYPE)
{
 if(KNOCK_WALL == TYPE)
 {
  int i;
  for(i = 0 ; i < pWall->len ; ++i)
  {
   if(IsOver(pBody->pos,pWall->pos[i],KNOCK_WALL))
    return 1; //与墙相撞
  }
 }
 else if(KNOCK_FOOD == TYPE)
 {
  int i;
  for(i = 1 ; i <= pFood->len ; ++i)
  {
   if(IsOver(pFood->pos[i],pBody->pos,KNOCK_WALL))
    return i; //与食物相撞
  }
 }
 return 0;
}
/**********************************
* 功能:
* 用户移动
***********************************/
int Move(FOOD *pFood,WALL *pWall,BODY *pBody)
{
 BODY prePos = *pBody;
// POS prePos = pBody->pos;
 int iKey = GetKey();
 if(-1 == iKey) //用户退出
  return -1;
 if(iKey)
 {
  pBody->Direction = iKey + 4;
  iKey = 0;
 }
 if(0 == iKey)
 {
  if(DIRECTION_UP == pBody->Direction)
   --pBody->pos.y;
  else if(DIRECTION_DOWN == pBody->Direction)
   ++pBody->pos.y;
  else if(DIRECTION_LEFT == pBody->Direction)
   --pBody->pos.x;
  else if(DIRECTION_RIGHT == pBody->Direction)
   ++pBody->pos.x;
 }
 
 if(IsKnock(pWall,pBody,pFood,KNOCK_WALL))
 {
  *pBody = prePos;
  return 0;
 }
 int ix = IsKnock(pWall,pBody,pFood,KNOCK_FOOD);
 if(ix)
 {
  ++iBeans;
  //删除初吃掉的食物
  int i;
  for(i = ix ; i <= (pFood->len - 1) ; ++i)
   pFood->pos[i] = pFood->pos[i + 1];
  --(pFood->len);
  if(0 == pFood->len) //当局完成
  {
   ++level;
   return 1;
  }
 }
 Print(&prePos.pos,PRINT_CLEAN); //先删除上一个输出
 Print(&pBody->pos,PRINT_BODY);
 return 0;
}
/**********************************
* 功能:
* 判断2点是否重合
***********************************/
int IsOver(POS pos1,POS pos2,int TYPE)
{
 if(KNOCK_WALL == TYPE) //pos1,the body. pos2,the wall
  if((pos1.x == pos2.x && pos1.y == pos2.y) || (pos2.x + 1 == pos1.x && pos2.y == pos1.y))
   return 1;
 return 0;
}
/**********************************
* 功能:
* 生成墙
***********************************/
void MakeWall(WALL *pWall)
{
 int x,y;
 int ix = 0;
 for(x = 0 ; x <= 16 ; ++x)
 {
  for(y = 0 ; y <= 23 ; ++y)
  {
   if(0 == wall[x][y])
   {
    pWall->pos[ix].x = 2 * y;
    pWall->pos[ix].y = x;
    Print(&pWall->pos[ix++],PRINT_WALL);
   }
  }
 }
 pWall->len = ix; //更新墙的数量
}
/**********************************
* 功能:
* 完成初始化操作
***********************************/
void Init(FOOD *pFood,WALL *pWall,BODY *pBody,HALL *pHall)
{
 //得到控制台标准输入输出句柄
 hMain_Out = GetStdHandle(STD_OUTPUT_HANDLE);
 hMain_In = GetStdHandle(STD_INPUT_HANDLE);
 //隐藏光标
 GetConsoleCursorInfo(hMain_Out,&info);
 info.bVisible = FALSE;
 SetConsoleCursorInfo(hMain_Out,&info);
 //初始化结构体
 pFood->len = 0;
 pWall->len = 0;
 pHall->len = 0;
 //改变控制台大小
 system("mode con cols=50 lines=21");
 //走廊结构体赋值
 int x,y;
 int ix = 0;
 for(x = 0 ; x < 17 ; ++x)
 {
  for(y = 0 ; y < 24 ; ++y)
  {
   if(wall[x][y]) //非墙
   {
    pHall->pos[ix].x = 2 * y;
    pHall->pos[ix++].y = x;
   }
  }
 }
 pHall->len = ix;
 pBody->pos.x = 2;
 pBody->pos.y = 1;
 pBody->Direction = DIRECTION_DOWN;
 printf("%d %d\n",pHall->pos[0].x,pHall->pos[0].y);
 //输出食物
 int i;
 MakeFood(pHall,pFood);
 for(i = 1 ; i <= 7 ; ++i)
 {
  Print(&pFood->pos[i],PRINT_FOOD,i);
 }
}
/**********************************
* 功能:
* 得到用户按键
***********************************/
int GetKey()
{
 if(GetAsyncKeyState(VK_UP))
  return KEY_UP;
 if(GetAsyncKeyState(VK_DOWN))
  return KEY_DOWN;
 if(GetAsyncKeyState(VK_LEFT))
  return KEY_LEFT;
 if(GetAsyncKeyState(VK_RIGHT))
  return KEY_RIGHT;
 if(GetAsyncKeyState(VK_ESCAPE))
  return -1; //用户退出
 return 0;//用户没有有效按键
}
/**********************************
* 功能:
* 完成打印功能
***********************************/
void Print(POS *p,int TYPE,int ix)
{
 COORD pos;
 pos.X = p->x;
 pos.Y = p->y;
 SetConsoleCursorPosition(hMain_Out,pos);
 if(PRINT_WALL == TYPE)
  printf("■");
 else if(PRINT_FOOD == TYPE)
  printf("%d",ix);
 else if(PRINT_BODY == TYPE)
  printf("\1");
 else if(PRINT_CLEAN == TYPE)
  printf(" ");
}
/**********************************
* 功能:
* 显示等级 和剩余豆子数
***********************************/
void ShowScore(BODY *pBody,FOOD *pFood)
{
 COORD pos;
 pos.X = 0;
 pos.Y = 18;
 SetConsoleCursorPosition(hMain_Out,pos);
 printf("\tBeans left : %d | pos : x=%d,y=%d\n",pFood->len,pBody->pos.x,pBody->pos.y);
 printf("\t\tLevel : %d",level);
// for(int i = 1 ; i <= pFood->len ; ++i)
//  printf("(x=%d,y=%d)",pFood->pos[i].x,pFood->pos[i].y);
}
/**********************************
* 功能:
* 生成食物
***********************************/
void MakeFood(HALL *pHall,FOOD *pFood)
{
 srand((unsigned)time(NULL));
 int tot;
 for(tot = 1 ; tot <= 7 ; ++tot)
 {
  int ixFood = rand() * pHall->len / RAND_MAX;
  pFood->pos[tot].x = pHall->pos[ixFood].x;
  pFood->pos[tot].y = pHall->pos[ixFood].y;
 }
 pFood->len = 7;
}

希望本文所述对大家的C++程序设计有所帮助。

 
标签: C++ 控制台 游戏
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • Aurelius vs mORMot vs EntityDAC Delphi 的
    Aurelius vs mORMot vs EntityDAC   Delphi 的 ORM框架:http://www.tmssoftware.com/site/aurelius.asp#product-buy-onlinehttps://synopse.info/fossil/wiki/Synopse+OpenSourcehttps://www.devart.com/entitydac/download.htmlkbmMW  http://www.compo
    02-09
  • 【Ruby】Mac gem的一些坑
    前言自上一次升级MacOS系统后出现jekyll无法构建的问题,当时处理半天。谁知道最近又升级了MacOS,荒废博客多时,今天吝啬写了一篇准备发布,构建报错,问题重新。还是记录下,以防下次升级出问题。问题描述安装jekyll静态博客需要在Ruby环境下运行,于是参照
    02-09
  • iOS oc 调用 swift
    如股票oc要调用swift里面的代码 需要包含固定这个头文件项目名称 LiqunSwiftDemo-Swift.h         #ProjectName#-Swift.h固定的写法swift 目的 是取代oc 但是 不会完全取代 只是前端的替换LiqunSwiftDemo-Swift 点进去 可以看到 所有的swift代码 都产生
    02-09
  • objective-c NSTimer 定时器
    -(void)initTimer{//时间间隔NSTimeInterval timeInterval =3.0 ;//定时器repeats 表示是否需要重复,NO为只重复一次NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:timeInterval target:self selector:@selector(mobileAnimation) userInfo:nil
    02-09
  • Objective-C  日记③ 字符串
    Objective-C 日记③ 字符串
    一、创建字符串、类方法   公式创建NSString  +(id) stringWithFormat:(NSString *) format,……;eg:  NSString *height;  height=[NSString stringWithFormat:@"高度是: %d 长度: %d",10,20];得到的字符串:“高度是: 10 长度: 20” 注意:  省
    02-09
  • Objective-C KVC机制
    Objective-C KVC机制http://blog.csdn.net/omegayy/article/details/7381301全部推翻重写一个版本,这是我在公司内做技术分享的文档总结,对结构、条理做了更清晰的调整。 1.    基本概念MODEL主要是英文文档里面经常出现的一些概念,讲解一下,方便英文
    02-09
  • objective-c 加号 减号 - +
    “加号代表static”是错误的说法,可能跟你那样表达的人其实意思是:“前置加号的方法相当于Java 里面的静态方法”。在Oc中,方法分为类方法和实例方法。前置加号(+)的方法为类方法,这类方法是可以直接用类名来调用的,它的作用主要是创建一个实例。有人把
    02-09
  • Objective-C  日记①
    Objective-C 日记①
    1、Xcode的.m扩展名表示文件含有Object-C代码,C以.c文件,C++以.cpp文件2、头文件声明:C使用:#include,O-C使用#import(当然你也可以使用#include) 3、输出方式:  C:printf("",参数);  O-C:NSLog(@"",参数); 4、布尔类型  C:bool 具有true
    02-09
  • ASP.NET MVC 操作AD 获取域服务器当前用户姓
    #region 根据当前登录域账号 获取AD用户姓名和所在OU目录/// summary/// 根据当前登录域账号 获取AD用户姓名和所在OU目录/// /summary/// param name="searchUser"要搜索的当前用户名/param/// param name="paths"out返回该用户所在OU目录/param/// param nam
    02-09
  • swift和OC - 拆分数组 和 拆分字符串
    1. 拆分数组 /// 根据 数组 截取 指定个数返回 多个数组的集合func splitArray( array: [Date], withSubSize subSize: Int) - [[Date]] {//数组将被拆分成指定长度数组的个数let count = array.count% subSize == 0 ? (array.count/ subSize) : (array.count
    02-08
点击排行