关于C语言编程新手零基础入门学习,第一个小项目,打造扫雷小游戏

C语言是面向过程的,而C++是面向对象的

C和C++的区别:

C是一个结构化语言,它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现过程(事务)控制)。

C++,首要考虑的是如何构造一个对象模型,让这个模型能够契合与之对应的问题域,这样就可以通过获取对象的状态信息得到输出或实现过程(事务)控制。 所以C与C++的最大区别在于它们的用于解决问题的思想方法不一样。之所以说C++比C更先进,是因为“ 设计这个概念已经被融入到C++之中 ”。

C与C++的最大区别:在于它们的用于解决问题的思想方法不一样。之所以说C++比C更先进,是因为“ 设计这个概念已经被融入到C++之中 ”,而就语言本身而言,在C中更多的是算法的概念。那么是不是C就不重要了,错!算法是程序设计的基础,好的设计如果没有好的算法,一样不行。而且,“C加上好的设计”也能写出非常好的东西。

一直说写个几百行的小项目,于是我写了一个控制台的扫雷,没有想到精简完了代码才200行左右,不过考虑到这是我精简过后的,浓缩才是精华嘛,我就发出来大家一起学习啦,看到程序跑起来能玩,感觉还是蛮有成就感的~哈哈

扫雷应该属于一款大众游戏,从我初中使用计算机开始,它就被集成到了windows系统中,虽然他是这么经典,我还是要介绍一下他的玩法,然后再考虑在控制台中怎么实现它。

小编推荐一个学C语言/C++的学习裙【 二六三,六八八,二七六 】,无论你是大牛还是小白,是想转行还是想入行都可以来了解一起进步一起学习!裙内有开发工具,很多干货和技术资料分享!

1 游戏的主界面,是一个一个小方格,在小方格上单击左键,可以翻开小方格看看后面有什么。

2 在这些小方格的背后隐藏着雷,如果不幸点中了雷,那么就GameOver了。

2 如果点中的不是一个雷,那么就是一块空地,这个时候会出现两种情况:

1)用鼠标点中的空地周围八个点内有雷,那么就显示雷的个数

2)用鼠标点中的空地周围没有雷,这个时候就将周围的空地全部显示出来,遇到该显示数字的空地,就将数字显示出来。(仔细观察你会发现,数字会将空地围起来,这是一句废话,但是也值得想一想这是为什么)

3 在小方格上,点击鼠标的右键,可以将一个空地标记为雷,当然这个功能只是为了方便你记忆你之前确定是雷的地方。(还有左右键都点,和点击右键出现?标记,这里就不谈啦)

4 当空地上剩余的格子数和雷的个数一样多,那么这个时候就应该算是胜利啦。

OK~游戏流程说完了,这个时候该谈谈如何实现了。

1 首先需要一张地图,一般情况下我们都可以用一个二维数组表示一个地图,每一个元素代表着扫雷中的一个小方格。相应元素存储0,那么地图上的这个位置就是空地,相应元素存储1,那么就代表这个位置就一颗雷。

2 在控制台上依照二维数组长度和宽度,打印相应的小方块。

3 然后就用鼠标点击那些小方块,对于控制台来讲,在黑框框的区域中是有坐标的,可以使用一些函数捕获到你点击了屏幕的哪一个坐标。

4 对于控制台来说,打印一个字符,有的字符横向占一个位置比如普通的字母数字,有的字符横向占两个位置比如一些图形字符: ①②③■◆等等,这点在控制台编程的时候要注意。

5 当点击屏幕的时候,获取到点击的坐标后,去二维数组中查看相应的位置是雷还是空地,从而做相应的处理。

1)假如点击到了雷,那么就控制游戏结束

2)假如点击到了空地有两种情况

1)点击的空地周围有雷,那么就将雷的个数显示出来

2)假如点击的空地周围没有雷,那么就使用递归的方法去探测周围的点,探测出与其相连的所有周围有雷的点。

这个是我实现的效果:

下面就是代码啦:

// saolei.cpp : 定义控制台应用程序的入口点。

//

#include "stdafx.h"

#include

#include

#include

#define Boom 10

int a[10][10] = {0};

COORD TempPos[100] ={0};

int nSign = 0;

/************************************

函数名 : WriteWchar

函数作用: 在控制台相应的坐标上显示一串字符

返回值 : void

参数 : int x 横坐标

参数 : int y 纵坐标

参数 : char szString[] 要显示的字符串

说明 :

************************************/

void WriteWchar(int x,int y,char szString[])

{

HANDLE hOut= GetStdHandle(STD_OUTPUT_HANDLE);

COORD pos = {x*2,y};

SetConsoleCursorPosition(hOut,pos);

printf("%s",szString);

}

/************************************

函数名 : DrawNumber

函数作用: 在相应的坐标上,根据传入的数字,打印相应的数字字符

返回值 : void

参数 : COORD pos 要打印的位置

参数 : int nNumber 要打印的数字

说明 :

************************************/

void DrawNumber(COORD pos,int nNumber)

{

switch (nNumber)

{

case 1:

WriteWchar(pos.X,pos.Y,"①");

break;

case 2:

WriteWchar(pos.X,pos.Y,"②");

break;

case 3:

WriteWchar(pos.X,pos.Y,"③");

break;

case 4:

WriteWchar(pos.X,pos.Y,"④");

break;

case 5:

WriteWchar(pos.X,pos.Y,"⑤");

break;

case 6:

WriteWchar(pos.X,pos.Y,"⑥");

break;

case 7:

WriteWchar(pos.X,pos.Y,"⑦");

break;

case 8:

WriteWchar(pos.X,pos.Y,"⑧");

break;

default:

break;

}

}小编推荐一个学C语言/C++的学习裙【 二六三,六八八,二七六 】,无论你是大牛还是小白,是想转行还是想入行都可以来了解一起进步一起学习!裙内有开发工具,很多干货和技术资料分享!

/************************************

函数名 : GetNumber

函数作用: 获取一个点的四周有几颗雷

返回值 : int

参数 : COORD pos 要探测的点的坐标

说明 :

************************************/

int GetNumber(COORD pos)

{

int nCount = 0;

for(int i = pos.X-1;i<=pos.X+1;i++)

for (int j = pos.Y-1;j<=pos.Y+1;j++)

{

if (a[j][i] == Boom)

{

nCount++;

}

}

return nCount;

}

/************************************

函数名 : Drawmap

函数作用: 打印一下地图

返回值 : void

说明 :

************************************/

void Drawmap()

{

for (int i =0;i<10;i++)

{

for (int j =0;j<10;j++)

{

WriteWchar(j,i,"■");

}

}

}

/************************************

函数名 : Init

函数作用: 随机生成10个地雷,然后存到数组中

返回值 : void

说明 :

************************************/

void Init()

{

srand(time(NULL));

for (int i =0;i<10;i++)

{

int Temp_x = rand()%10;

int Temp_y = rand()%10;

//判断这个地方是不是已经生成一个雷了,如果没有,赋值为雷

if (a[Temp_x][Temp_y]!=Boom)

{

a[Temp_x][Temp_y] = Boom;

}

//如果是雷,就相当于本次生成没有发生过。。。。。

else

{

i--;

}

}

Drawmap();

}

/************************************

函数名 : IsClose

函数作用: 判断是不是已经探测过的点,由于使用的8方向递归的探测,这样避免重复

返回值 : bool

参数 : COORD posTemp

说明 :

************************************/

bool IsClose(COORD posTemp)

{

for (int i =0;i

{

if(TempPos[i].X == posTemp.X&&TempPos[i].Y == posTemp.Y)

return true;

}

return false;

}

/************************************

函数名 : IsKongdi

函数作用: 判断一个点是空地,还是雷,如果是空地,需要做其他处理

返回值 : void

参数 : COORD pos

说明 :

************************************/

bool IsKongdi(COORD pos)

{

int nNumber = 0;

//1 如果是雷,就直接返回一个false说明要挂了

if (a[pos.Y][pos.X] == Boom)

{

return false;

}

//2 如果不是雷,那么就做后续处理

else

{

//2.1先判断一下周围有几颗雷

nNumber = GetNumber(pos);

if (nNumber!=0){

//有几颗雷,就打印这个数字

DrawNumber(pos,nNumber);

return true;

}

else

{

//如果没有雷,那就先画空地出来,然后向周围扩散去探测其他点

WriteWchar(pos.X,pos.Y," ");

}

}

//2.2点到了空地,但是周围没有雷的情况的处理,继续去探测周围8个点

for(int i = -1;i<=1;i++)

for (int j = -1;j<=1;j++)

{

COORD posTemp = {pos.X+i,pos.Y+j};

//是不是越界了

if (i==0&&j==0||posTemp.X==-1||posTemp.Y==-1||posTemp.X==10||posTemp.Y==10)

continue;

//这个点是不是已经探测过了

if (IsClose(posTemp))

continue;

//这个点没有探测过,就将其加入到数组中,然后使其在以后的探测中,存入

TempPos[nSign++] =posTemp;

IsKongdi(posTemp);

}

return true;

}

/************************************

函数名 : GetMousePosition

函数作用: 获取鼠标点击的位置,假如没有获取到,就返回(-1,-1)

返回值 : COORD 鼠标点击的坐标

说明 :

************************************/

COORD GetMousePosition()

{

HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);

INPUT_RECORD stcInput = {0};

DWORD buffer;

COORD pos = {-1,-1};

ReadConsoleInput(hIn,&stcInput,1,&buffer);

if (stcInput.EventType == MOUSE_EVENT)

{

MOUSE_EVENT_RECORD stcMouseEnent = stcInput.Event.MouseEvent;

if (stcMouseEnent.dwButtonState ==FROM_LEFT_1ST_BUTTON_PRESSED )

{

pos = stcMouseEnent.dwMousePosition;

pos.X/=2;

}

}

return pos;

}

int _tmain(int argc, _TCHAR* argv[])

{

Init();

COORD pos;

//开始游戏

while(1)

{

//获取鼠标点击位置

pos = GetMousePosition();

if (pos.X!=-1)

{

//如果鼠标点击的位置被探测过了,就开始下一次循环

if (IsClose(pos))

{

continue;

}

TempPos[nSign++] =pos;

bool bIskongdi = IsKongdi(pos);

//点到雷了,就直接退出游戏了。

if (false ==bIskongdi)

{

system("cls");

WriteWchar(20,10,"you lose");

getchar();

break;

}

//检测是不是赢了,赢的条件就是没有被探测的点的个数和雷的个数相等

if (nSign ==90)

{

system("cls");

WriteWchar(20,10,"you win");

}

}

}

return 0;

}小编推荐一个学C语言/C++的学习裙【 二六三,六八八,二七六 】,无论你是大牛还是小白,是想转行还是想入行都可以来了解一起进步一起学习!裙内有开发工具,很多干货和技术资料分享!

项目不是很长,但是注释我写的还算明白,估计大家都可以看得懂,希望对于新手们有一定的帮助,最后,谢谢大家的支持!!!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容