求扫雷c语言最简单代码编译小游戏的代码,比如扫雷原代码等?

欢迎加入我们,一同切磋技术。 &
用户名: &&&
密 码: &
共有 9277 人关注过本帖
标题:[原创]我写的一个控制台下的扫雷小游戏源代码
等 级:新手上路
帖 子:765
&&问题点数:0&&回复次数:42&&&
[原创]我写的一个控制台下的扫雷小游戏源代码
/********************************************************
** Highlight software by yzfy(雨中飞燕) http://yzfy.org *
*********************************************************/
//扫雷.cpp : Win32 Console Application
//Compiler: MinGW(GCC), VC6.0, VC2003, VC2005
//Warning: You Can Not Using TC To Compile this file
//Demo Game By yzfy(雨中飞燕) http://yzfy.org
//I'm too lazy to write comments
// header file
#include &iostream&
#include &cstdlib&
#include &ctime&
#include &windows.h&
#include &conio.h&
// defines
#define KEY_UP&&& 0xE048
#define KEY_DOWN&&0xE050
#define KEY_LEFT&&0xE04B
#define KEY_RIGHT 0xE04D
#define KEY_ESC&&&0x001B
#define KEY_1&&&&&'1'
#define KEY_2&&&&&'2'
#define KEY_3&&&&&'3'
#define GAME_MAX_WIDTH&&&100
#define GAME_MAX_HEIGHT&&100
// Strings Resource
#define STR_GAMETITLE &ArrowKey:MoveCursor&&Key1:Open&&\
Key2:Mark&&Key3:OpenNeighbors&
#define STR_GAMEWIN&&&&Congratulations! You Win! Thank you for playing!\n&
#define STR_GAMEOVER&&&Game Over, thank you for playing!\n&
#define STR_GAMEEND&&&&Presented by yzfy . Press ESC to exit\n&
//-------------------------------------------------------------
// Base class
class CConsoleWnd
&&& public:
&&&&&&&&static int TextOut(const char*);
&&&&&&&&static int GotoXY(int, int);
&&&&&&&&static int CharOut(int, int, const int);
&&&&&&&&static int TextOut(int, int, const char*);
&&&&&&&&static int GetKey();
&&& public:
//{{// class CConsoleWnd
&&& //&&int CConsoleWnd::GetKey()
&&& //&&Wait for standard input and return the KeyCode
&&& int CConsoleWnd::GetKey()
&&&&&&&&int nkey=getch(),nk=<font color=;
&&&&&&&&if(nkey&=<font color=||nkey==<font color=)nk=getch();
&&&&&&&&return nk&<font color=?nkey*<font color=+nk:
&&& //&&int CConsoleWnd::GotoXY(int x, int y)
&&& //&&Move cursor to (x,y)
&&& //&&Only Console Application
&&& int CConsoleWnd::GotoXY(int x, int y)
&&&&&&&&COORD
&&&&&&&&cd.X =cd.Y =
&&&&&&&&return SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),cd);
&&& //&&int CConsoleWnd::TextOut(const char* pstr)
&&& //&&Output a string at current position
&&& int CConsoleWnd::TextOut(const char* pstr)
&&&&&&&&for(;*++pstr)putchar(*pstr);
&&&&&&&&return <font color=;
&&& //&&int CConsoleWnd::CharOut(int x, int y, const int pstr)
&&& //&&Output a char at (x,y)
&&& int CConsoleWnd::CharOut(int x, int y, const int pstr)
&&&&&&&&GotoXY(x, y);
&&&&&&&&return putchar(pstr);
&&& //&&int CConsoleWnd::TextOut(const char* pstr)
&&& //&&Output a string at (x,y)
&&& int CConsoleWnd::TextOut(int x, int y, const char* pstr)
&&&&&&&&GotoXY(x, y);
&&&&&&&&return TextOut(pstr);
//-------------------------------------------------------------
//Application class
class CSLGame:public CConsoleWnd
&&& private:
&&& private:
&&&&&&&&int curX,curY;
&&&&&&&&int poolWidth,poolH
&&&&&&&&int bm_gamepool[GAME_MAX_HEIGHT+<font color=][GAME_MAX_WIDTH+<font color=];
&&& public:
&&&&&&&&CSLGame():curX(<font color=),curY(<font color=){poolWidth=poolHeight=<font color=;}
&&&&&&&&int InitPool(int, int, int);
&&&&&&&&int MoveCursor(){return CConsoleWnd::GotoXY(curX, curY);}
&&&&&&&&int DrawPool(int);
&&&&&&&&int WaitMessage();
&&&&&&&&int GetShowNum(int, int);
&&&&&&&&int TryOpen(int, int);
&&& private:
&&&&&&&&int DFSShowNum(int, int);
&&& private:
&&&&&&&&const static int GMARK_BOOM;
&&&&&&&&const static int GMARK_EMPTY;
&&&&&&&&const static int GMARK_MARK;
const int CSLGame::GMARK_BOOM =&&0x10;
const int CSLGame::GMARK_EMPTY=&&0x100;
const int CSLGame::GMARK_MARK =&&0x200;
//{{// class CSLGame:public CConsoleWnd
&&& //&&int CSLGame::InitPool(int Width, int Height, int nBoom)
&&& //&&Initialize the game pool.
&&& //&&If Width*Height &= nBoom, or nBoom&=0,
&&& //&&or Width and Height exceed limit , then return 1
&&& //&&otherwise return 0
&&& int CSLGame::InitPool(int Width, int Height, int nBoom)
&&&&&&&&poolWidth = W poolHeight = H
&&&&&&&&if(nBoom&=<font color= || nBoom&=Width*Height
&&&&&&&&&&&&|| Width &=<font color= || Width &GAME_MAX_WIDTH
&&&&&&&&&&&&|| Height&=<font color= || Height&GAME_MAX_HEIGHT
&&&&&&&&){
&&&&&&&&&&&&return <font color=;
&&&&&&&&// zero memory
&&&&&&&&for(int y=<font color=; y&=Height+<font color=; ++y)
&&&&&&&&&&&&for(int x=<font color=; x&=Width+<font color=; ++x)
&&&&&&&&&&&&{
&&&&&&&&&&&&&&& bm_gamepool[y][x]=<font color=;
&&&&&&&&&&&&}
&&&&&&&&// init seed
&&&&&&&&srand(time(NULL));
&&&&&&&&// init Booms
&&&&&&&&while(nBoom)
&&&&&&&&&&&&int x = rand()%Width + <font color=, y = rand()%Height + <font color=;
&&&&&&&&&&&&if(bm_gamepool[y][x]==<font color=)
&&&&&&&&&&&&{
&&&&&&&&&&&&&&& bm_gamepool[y][x] = GMARK_BOOM;
&&&&&&&&&&&&&&& --nB
&&&&&&&&&&&&}
&&&&&&&&// init cursor position
&&&&&&&&curX = curY = <font color=;
&&&&&&&&MoveCursor();
&&&&&&&&return <font color=;
&&& //&&int CSLGame::DrawPool(int bDrawBoom = 0)
&&& //&&Draw game pool to Console window
&&& int CSLGame::DrawPool(int bDrawBoom = <font color=)
&&&&&&&&for(int y=<font color=;y&=poolH++y)
&&&&&&&&&&&&CConsoleWnd::GotoXY(<font color=, y);
&&&&&&&&&&&&for(int x=<font color=;x&=poolW++x)
&&&&&&&&&&&&{
&&&&&&&&&&&&&&& if(bm_gamepool[y][x]==<font color=)
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&&putchar('.');
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& else if(bm_gamepool[y][x]==GMARK_EMPTY)
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&&putchar(' ');
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& else if(bm_gamepool[y][x]&<font color= && bm_gamepool[y][x]&=<font color=)
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&&putchar('0'+bm_gamepool[y][x]);
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& else if(bDrawBoom==<font color= && (bm_gamepool[y][x] & GMARK_MARK))
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&&putchar('#');
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& else if(bm_gamepool[y][x] & GMARK_BOOM)
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&&if(bDrawBoom)
&&&&&&&&&&&&&&&&&&&&&&&&putchar('*');
&&&&&&&&&&&&&&&&&&&&else
&&&&&&&&&&&&&&&&&&&&&&&&putchar('.');
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&}
&&&&&&&&return <font color=;
&&& //&&int CSLGame::GetShowNum(int x, int y)
&&& //&&return ShowNum at (x, y)
&&& int CSLGame::GetShowNum(int x, int y)
&&&&&&&&int nCount = <font color=;
&&&&&&&&for(int Y=-<font color=;Y&=<font color=;++Y)
&&&&&&&&&&&&for(int X=-<font color=;X&=<font color=;++X)
&&&&&&&&&&&&if(bm_gamepool[y+Y][x+X] & GMARK_BOOM)++nC
&&&&&&&&return nC
&&& //&&int CSLGame::TryOpen(int x, int y)
&&& //&&Try open (x, y) and show the number
&&& //&&If there is a boom, then return EOF
&&& int CSLGame::TryOpen(int x, int y)
&&&&&&&&int nRT = <font color=;
&&&&&&&&if(bm_gamepool[y][x] & GMARK_BOOM)
&&&&&&&&&&&&nRT = EOF;
&&&&&&&&else
&&&&&&&&&&&&int nCount = GetShowNum(x,y);
&&&&&&&&&&&&if(nCount==<font color=)
&&&&&&&&&&&&{
&&&&&&&&&&&&&&& DFSShowNum(x, y);
&&&&&&&&&&&&}
&&&&&&&&&&&&else bm_gamepool[y][x] = nC
&&&&&&&&return nRT;
&&& //&&int CSLGame::DFSShowNum(int x, int y)
&&& //&&Private function, no comment
&&& int CSLGame::DFSShowNum(int x, int y)
&&&&&&&&if((<font color=&x && x&=poolWidth) &&
&&&&&&&&&&&&(<font color=&y && y&=poolHeight) &&
&&&&&&&&&&&&(bm_gamepool[y][x]==<font color=))
&&&&&&&&&&&&int nCount = GetShowNum(x, y);
&&&&&&&&&&&&if(nCount==<font color=)
&&&&&&&&&&&&{
&&&&&&&&&&&&&&& bm_gamepool[y][x] = GMARK_EMPTY;
&&&&&&&&&&&&&&& for(int Y=-<font color=;Y&=<font color=;++Y)
&&&&&&&&&&&&&&&&&&&&for(int X=-<font color=;X&=<font color=;++X)
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&&DFSShowNum(x+X,y+Y);
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&}
&&&&&&&&&&&&else bm_gamepool[y][x] = nC
&&&&&&&&return <font color=;
&&& //&&int CSLGame::WaitMessage()
&&& //&&Game loop, wait and process an input message
&&& //&&return:&&0:&&1: W otherwise: Lose
&&& int CSLGame::WaitMessage()
&&&&&&&&int nKey = CConsoleWnd::GetKey();
&&&&&&&&int nRT = <font color=, nArrow = <font color=;
&&&&&&&&switch (nKey)
&&&&&&&&&&&&case KEY_UP:
&&&&&&&&&&&&{
&&&&&&&&&&&&&&& if(curY&<font color=)--curY;
&&&&&&&&&&&&&&& nArrow=<font color=;
&&&&&&&&&&&&}break;
&&&&&&&&&&&&case KEY_DOWN:
&&&&&&&&&&&&{
&&&&&&&&&&&&&&& if(curY&poolHeight)++curY;
&&&&&&&&&&&&&&& nArrow=<font color=;
&&&&&&&&&&&&}break;
&&&&&&&&&&&&case KEY_LEFT:
&&&&&&&&&&&&{
&&&&&&&&&&&&&&& if(curX&<font color=)--curX;
&&&&&&&&&&&&&&& nArrow=<font color=;
&&&&&&&&&&&&}break;
&&&&&&&&&&&&case KEY_RIGHT:
&&&&&&&&&&&&{
&&&&&&&&&&&&&&& if(curX&poolWidth)++curX;
&&&&&&&&&&&&&&& nArrow=<font color=;
&&&&&&&&&&&&}break;
&&&&&&&&&&&&case KEY_1:
&&&&&&&&&&&&{
&&&&&&&&&&&&&&& nRT = TryOpen(curX, curY);
&&&&&&&&&&&&}break;
&&&&&&&&&&&&case KEY_2:
&&&&&&&&&&&&{
&&&&&&&&&&&&&&& if((bm_gamepool[curY][curX]
&&&&&&&&&&&&&&&&&&&&& ~(GMARK_MARK|GMARK_BOOM))==<font color=)
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&&bm_gamepool[curY][curX] ^= GMARK_MARK;
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&}break;
&&&&&&&&&&&&case KEY_3:
&&&&&&&&&&&&{
&&&&&&&&&&&&&&& if(bm_gamepool[curY][curX] & 0xF)
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&&int nb = bm_gamepool[curY][curX] & 0xF;
&&&&&&&&&&&&&&&&&&&&for(int y=-<font color=;y&=<font color=;++y)
&&&&&&&&&&&&&&&&&&&&&&&&for(int x=-<font color=;x&=<font color=;++x)
&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&if(bm_gamepool[curY+y][curX+x] & GMARK_MARK)
&&&&&&&&&&&&&&&&&&&&&&&&&&& --
&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&if(nb==<font color=)
&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&for(int y=-<font color=;y&=<font color=;++y)
&&&&&&&&&&&&&&&&&&&&&&&&&&& for(int x=-<font color=;x&=<font color=;++x)
&&&&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&&&& if((bm_gamepool[curY+y][curX+x]
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& (0xF|GMARK_MARK)) == <font color=)
&&&&&&&&&&&&&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&nRT |= TryOpen(curX+x, curY+y);
&&&&&&&&&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&}break;
&&&&&&&&&&&&case KEY_ESC:
&&&&&&&&&&&&{
&&&&&&&&&&&&&&& nRT = EOF;
&&&&&&&&&&&&}break;
&&&&&&&&if(nKey == KEY_1 || nKey == KEY_3)
&&&&&&&&&&&&int y=<font color=;
&&&&&&&&&&&&for(;y&=poolH++y)
&&&&&&&&&&&&{
&&&&&&&&&&&&&&& int x=<font color=;
&&&&&&&&&&&&&&& for(;x&=poolW ++x)
&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&&if(bm_gamepool[y][x]==<font color=)break;
&&&&&&&&&&&&&&& }
&&&&&&&&&&&&&&& if(x&=poolWidth) break;
&&&&&&&&&&&&}
&&&&&&&&&&&&if(! (y&=poolHeight))
&&&&&&&&&&&&{
&&&&&&&&&&&&&&& nRT = <font color=;
&&&&&&&&&&&&}
&&&&&&&&if(nArrow==<font color=)
&&&&&&&&&&&&DrawPool();
&&&&&&&&MoveCursor();
&&&&&&&&return nRT;
//-------------------------------------------------------------
&&& //&&main function
&&& int main(void)
&&&&&&&&int x=<font color=, y=<font color=, b=<font color=,n; // define width & height & n_booms
&&&&&&&&CSLGame slG
&&&&&&&&// Init Game
&&&&&&&&&&&&CConsoleWnd::GotoXY(<font color=,<font color=);
&&&&&&&&&&&&CConsoleWnd::TextOut(STR_GAMETITLE);
&&&&&&&&&&&&slGame.InitPool(x,y,b);
&&&&&&&&&&&&slGame.DrawPool();
&&&&&&&&&&&&slGame.MoveCursor();
&&&&&&&&while((n=slGame.WaitMessage())==<font color=) // Game Message Loop
&&&&&&&&&&&&;
&&&&&&&&// End of the Game
&&&&&&&&&&&&slGame.DrawPool(<font color=);
&&&&&&&&&&&&CConsoleWnd::TextOut(&\n&);
&&&&&&&&&&&&if(n==<font color=)
&&&&&&&&&&&&{
&&&&&&&&&&&&&&& CConsoleWnd::TextOut(STR_GAMEWIN);
&&&&&&&&&&&&}
&&&&&&&&&&&&else
&&&&&&&&&&&&{
&&&&&&&&&&&&&&& CConsoleWnd::TextOut(STR_GAMEOVER);
&&&&&&&&&&&&}
&&&&&&&&&&&&CConsoleWnd::TextOut(STR_GAMEEND);
&&&&&&&&while(CConsoleWnd::GetKey()!=KEY_ESC)
&&&&&&&&&&&&;
&&&&&&&&return <font color=;
用mingw或者VC/VS在控制台下编译一下玩玩看(不能用TC/WinTC编译,文件名后缀必须为cpp)。
方向键移动光标,1键是翻开当前格,2键是标记,3键是自动翻开周围8格
偶以前写的一个小东东。。。不想用太多API。。。本意不是玩API。。。
不过因为帖子为连续文本的原因,代码只好用单文件的形式了。
不知道你看完的感觉是什么?给个意见吧
[color=white]
搜索更多相关主题的帖子:
等 级:新手上路
帖 子:560
不懂,顶下!苦啃编程ing·····
来 自:南京师范大学
等 级:贵宾
威 望:12
帖 子:4496
专家分:141
学习需要安静。。海盗要重新来过。。
等 级:新手上路
帖 子:132
建议你多发点你写的码 .
等 级:贵宾
威 望:24
帖 子:4144
专家分:524
有意思 顶一下 呵呵
等 级:新手上路
我运行了,怎么有编译错误啊
等 级:贵宾
威 望:24
帖 子:4144
专家分:524
你用什么编译的?
如果VC6的话可能因为你的库太老出现:
Cannot open include file: 'streambuf': No such file or directory
这样的话你可以把头文件改为:
#include &iostream.h&
#include &cstdlib&
#include &ctime&
#include &windows.h&
#include &conio.h&
#include &stdio.h&
来 自:湖北工业大学
等 级:贵宾
威 望:19
帖 子:3947
专家分:748
发现自己学会敬佩别人了……
有些人,是需要敬佩的……
不是从她开始吧?
专心编程………
飞燕算法初级群:3996098
等 级:论坛游民
帖 子:190
专家分:17
看完 发现,我还有很多看不懂的.
原来 你就是传说中 高手啊.
原来 我还差你很远,虽然我也能编一些.
哎!!我什么时候,也能用自己的思想.编个你一样的..
来 自:湖北工业大学
等 级:贵宾
威 望:19
帖 子:3947
专家分:748
敬佩不是因为自己做不到,也不是看不懂,而是被成果中凝结的心血和思想而感动。
专心编程………
飞燕算法初级群:3996098
版权所有,并保留所有权利。
Powered by , Processed in 0.086763 second(s), 9 queries.
Copyright&, BCCN.NET, All Rights Reserved第1页/共17页
#include &graphics.h&
#include &stdlib.h&
#include &dos.h&
#define LEFTPRESS 0xff01
#define LEFTCLICK 0xff10
#define LEFTDRAG 0xff19
#define MOUSEMOVE 0xff08
/*格子当前处于什么状态,1有雷,0已经显示过数字或者空白格子*//*统计格子周围有多少雷*/
/*右键按下显示红旗的标志,0没有红旗标志,1有红旗标志*/ }Mine[10][10];
int gameAGAIN=0;/*是否重来的变量*/
int gamePLAY=0;/*是否是第一次玩游戏的标志*/
int mineNUM;/*统计处理过的格子数*/
char randmineNUM[3];/*显示数字的字符串*/
int MouseE
int MouseB
int MouseX;
int MouseY;
void Init(void);/*图形驱动*/
void MouseOn(void);/*鼠标光标显示*/
void MouseOff(void);/*鼠标光标隐藏*/
void MouseSetXY(int,int);/*设置当前位置*/
LeftPress(void);/*左键按下*/
RightPress(void);/*鼠标右键按下*/
void MouseGetXY(void);/*得到当前位置*/
void Control(void);/*游戏开始, 重新, 关闭*/
void GameBegain(void);/*游戏开始画面*/
void DrawSmile(void);/*画笑脸*/
void DrawRedflag(int,int);/*显示红旗*/
void DrawEmpty(int,int,int,int);/*两种空格子的显示*/
void GameOver(void);/*游戏结束*/
void GameWin(void);/*显示胜利*/
MineStatistics(int,int);/*统计每个格子周围的雷数*/
ShowWhite(int,int);/*显示无雷区的空白部分*/
void GamePlay(void);/*游戏过程*/
void Close(void);/*图形关闭*/
void main(void)
Control();
第1页/共17页
寻找更多 ""c语言扫雷图形界面源代码
为鼓励上传资源,我们采用积分下载方式,希望您能发布更多更好的资源互相分享
1.上传软件或电子书,源码,资料等,审核后即获2积分;如发布时设了下载需积分,其他用户下载后你将获得相应积分
2.当您首次注册时,可以获送10个下载积分,供您下载资源和熟悉网站下载的使用
3.发现资源有误或其他问题,通过举报按钮反馈后我们将奖励积分
4.您可以在论坛通过发帖等方式获取
5.参加本站可以在有效期内不限次数下载
6.您也(1元=10积分)或
7.我们会不定期举办各种活动,参加活动可以获取积分,请关注下载频道首页公告。
您可能遇到这些“伪问题”:
1.资料无法解压:
请确保所有分卷均下载完毕,如果有未知后缀文件,请搜索相应解压软件;
2.chm文件无内容:
您的电脑锁定了这一文件,请右击文件属性,点击右下方“解除锁定”,关闭文件后再打开;
3.下载不下来:
请尝试重新下载(重新下载不扣积分);
4.杀毒软件报毒:
黑客安全及破解类软件容易报毒,但可正常使用,如担心安全请谨慎使用。
用制作的一个简单的扫雷图形界面源代码
用c语言制作的一个简单的扫雷图形界面源代码
您对本软件有什么意见或着疑问吗?请到您的关注和建议是我们前行的参考和动力
下载地址:
您正在下载:c语言扫雷图形界面源代码
热门最新推荐
您的浏览器不支持嵌入式框架,或者当前配置为不显示嵌入式框架。
文章下载读书扫雷的游戏程序的怎么编写啊
答案长度必须超过10个字,请勿发布无效或违法言论。
(共有3个回答)
曾想了解“扫雷”游戏在幕后所发生的一切吗?嗯,我想过,还由此决定对其进行了研究。本文是我的研究结果,现公之于众。
Win32 API 。
直接读取另一个进程的内存。
注 1 :本文的第一部分包括一些汇编代码,如果你不是很明白,无关要紧,这不是本文的目的,你尽可以跳过不管。然而,如果你想问我有关这些代码的问题,非常欢迎你写信给我。
注 2 :本程序是在 Windows XP 下测试的,所以如果它不能运行在其它的系统下,请注明该系统的信息,好让我们大家都知道。
注 2 之更新 :
本代码现在经过修改后也能在 Windows 2000 下运行。谢谢 Ryan Schreiber 找到了 Win2K 下的内存地址。
winmine.exe
如果你不是一个汇编迷,可以跳到这一步的最后,只看结论。
为了更好地了解“扫雷”幕后所发生的一切,我以一个调试器打开此文件作为开端。我个人最喜欢的调试器是 Olly Debugger v1.08 ,
这是一个非常简单且直观的调试器。总之,我在调试器中打开 winmine.exe ,并查看该文件。
我发现在 Import 区(列出在程序中用到的所有 dll 函数的区域)有下面一行:
8D52C377 DD msvcrt.rand
这就意味着“扫雷”用到了 VC 运行库的随机函数,因此我认为这对我可能有帮助。我搜索了该文件,看看到底在哪里调用了 rand() 函数,不过只在一个地方找到了这个函数:
FF15 B0110001 CALL DWORD PTR DS:[&&msvcrt.rand&]
接着我在这一行单步调用插入了一个断点并运行程序。我发现每当点击笑脸图标时,一个新的布雷图就生成了。布雷图按以下步骤创建:
首先,给布雷图分配一块内存区,并把所有的内存字节都设置成 0x0F ,说明在该单元 (cell) 中没有地雷。
其次,按地雷数遍历每一个地雷:
( 取值在 1 至宽度之间 ) 。
( 取值在 1 至高度之间 ) 。
设置内存块中被选中的单元的值为 0x8F ,这意味着在该单元中有一个地雷。
下面是原码,我已加入了一些注释,并加粗了重点部分。
MOV DWORD PTR DS:[1005334],EAX [0x1005334] =
宽度(即横向格数)
MOV DWORD PTR DS:[1005338],ECX [0x1005338] =
高度(即纵向格数)
CALL winmine.01002ED5
生成空的内存块并进行清除
MOV EAX,DWORD PTR DS:[10056A4]
MOV DWORD PTR DS:[1005160],EDI
MOV DWORD PTR DS:[1005330],EAX [0x1005330] =
地雷的个数
以地雷个数进行循环
PUSH DWORD PTR DS:[1005334] ;
把最大宽度( max width )压入栈
CALL winmine. Mine_Width
max width-1)
(即在 0 和 max width-1 之间随机选一个值)
PUSH DWORD PTR DS:[1005338] ;
把最大高度压入栈
MOV ESI,EAX
INC ESI Mine_Width = Mine_Width + 1
CALL winmine. Mine_Height = 随机化
max height-1)
INC EAX Mine_Height = Mine_Height +1
MOV ECX,EAX 计算单元在内存块(布雷图)中的地址
按这样计算:
单元内存地址
= 0x1005340 + 32 * height + width
TEST BYTE PTR DS:[ECX+ESI+ ; [ 单元内存地址 ] == 是否已是地雷 ?
JNZ SHORT winmine.
如果已是地雷,则重新迭代
否则 , 设置此单元为地雷
LEA EAX,DWORD PTR DS:[EAX+ESI+1005340]
OR BYTE PTR DS:[EAX],80
DEC DWORD PTR DS:[1005330]
JNZ SHORT winmine.
进行下一次迭代
正如你从代码所看到的,我发现了 4 个要点:
读内存地址 [0x1005334] 得出布雷图的宽度。
读内存地址 [0x1005338] 得出布雷图的高度。
读内存地址 [0x1005330] 得出布雷图中地雷的个数。
给出 x 、 y ,它们代表布雷图中的一个单元,位于 x 列, y 行。地址
[0x1005340 + 32 * y + x]
给出了该单元的值,这样我们就进入了下一步。
设计一个解决方案
你可能在想,我将会谈到了哪一种解决方案呢?显然,在发现了所有的地雷信息均可为我所用后,我所要做的就是从内存中读取数据。我决定编写读取这些信息的一个小程序,并给予说明。
它能自己绘出布雷图,显示出每一个被发现的地雷。
那么,怎么设计呢?我所做的就是把地址装到一个指针中(是的,它在 C# 中还存在),并读出其所指的数据,这样行吗?嗯,并不完全如些。因为场合不同,存储这些数据的内存并不在我的应用程序之中。要知道,每一个进程都拥有自己的地址空间,所以它就不会“意外地”访问属于别的程序的内存。因此,为了能读出这此数据,就必须找到一种方法,用来读取另一个进程的内存。
在本例中,这个进程就是“扫雷”进程。
我决定写一个小小的类库,它将接收一个进程,并提供读取该进程内存地址的功能。之所以这样做,是因为我还要在很多程序中用到它,没有必要反反复复地编写这些代码。这样,你就可以得到这个类,并在应用程序中使用它,且是免费的。例如,如果你编写一个调试器,这个类对你会有所帮助。据我所知,所有的调试器都具有读取被调试程序内存的能力。
那么,我们怎么才能读取别的进程的内存呢?答案在于一个叫做 ReadProcessMemory 的 API 。
这个 API 实际上可以让你读取进程内存中的一个指定地址。但在进行此操作之前,必须以特定的模式打开进程,而在完成操作之后,就必须关闭句柄以避免资源泄漏。我们利用 OpenProcess
CloseHandle 这几个 API 的帮助说明,完成了相应的操作。
为了在 C# 中使用 API ,必须使用 P/Invoke ,这意味着在使用 API 之前需要先对其进行声明。一般情况下都很简单,但要是让你以 .NET 的方式实现的话,有时就不那么容易了。我在 MSDN 中找到了这些 API 声明:
HANDLE OpenProcess(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
句柄继承选项
DWORD dwProcessId
BOOL ReadProcessMemory(
HANDLE hProcess,
LPCVOID lpBaseAddress,
内存区基址
LPVOID lpBuffer,
SIZE_T nSize,
要读的字节数
SIZE_T * lpNumberOfBytesRead
已读字节数
BOOL CloseHandle(
HANDLE hObject
这些声明转换为如下的 C# 声明:
[DllImport(&kernel32.dll&)]
public static extern IntPtr OpenProcess(
UInt32 dwDesiredAccess,
Int32 bInheritHandle,
UInt32 dwProcessId
[DllImport(&kernel32.dll&)]
public static extern Int32 ReadProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
[In, Out] byte[] buffer,
UInt32 size,
out IntPtr lpNumberOfBytesRead
[DllImport(&kernel32.dll&)] public static extern Int32 CloseHandle(
IntPtr hObject
如果你想知道在 c++ 和 c# 之间有关类型转换的更多信息,我建议你从
站点搜索此话题:“ Marshaling Data with Platform Invoke ”。
如果你把逻辑上是正确的程序搁在那儿 ,
它便能运行,
但有时还需要一点点的调整。
在声明了这些函数之后,我要做的是用一个简单的类把它们包装起来,并使用这个类。我把声明放在一个叫做 ProcessMemoryReaderApi 的类中,这样做更有条有理。主要的实用类称为 ProcessMemoryReade 。这个类有一个 ReadProcess 属性,它源于 System.Diagnostics.Process 类型,用于存放你要读取其内存的进程。类中有一个方法,用来以读模式打开进程。
public void OpenProcess()
m_hProcess = ProcessMemoryReaderApi.OpenProcess(
ProcessMemoryReaderApi.PROCESS_VM_READ, 1,
(uint)m_ReadProcess.Id);
PROCESS_VM_READ
常量告诉系统以读模式打开进程,
而 m_ReadProcess.Id
声明了我要打开的是什么进程。
在该类中最重要的是一个方法,它从进程中读取内存:
public byte[] ReadProcessMemory(IntPtr MemoryAddress, uint bytesToRead,
out int bytesReaded)
byte[] buffer = new byte[bytesToRead];
IntPtr ptrBytesR
ProcessMemoryReaderApi.ReadProcessMemory(m_hProcess,MemoryAddress,buffer,
bytesToRead,out ptrBytesReaded);
bytesReaded = ptrBytesReaded.ToInt32();
这个函数以所请求的大小声明一个字节数组,并使用 API 读取内存。就这么简单!
最后,下面这个方法关闭了进程。
public void CloseHandle()
iRetValue = ProcessMemoryReaderApi.CloseHandle(m_hProcess);
if (iRetValue == 0)
throw new Exception(&CloseHandle failed&);
现在轮到了有趣的部分。使用这个类就是为了读取“扫雷”的内存并揭开布雷图。要使用类,需要先对其进行初始化:
ProcessMemoryReaderLib.ProcessMemoryReader pReader
= new ProcessMemoryReaderLib.ProcessMemoryReader();
接着,必须设置你想要读取其内存的进程。以下是如何获得“扫雷”进程的例子,这个进程一旦被装入,就被设置为 ReadProcess 属性:
System.Diagnostics.Process[] myProcesses
= System.Diagnostics.Process.GetProcessesByName(&winmine&);
pReader.ReadProcess = myProcesses[0];
我们现在需要做的是:打开进程,读取内存,并在完成后关闭它。下面还是有关操作的例子,它读取代表布雷图宽度的地址。
pReader.OpenProcess();
memory = pReader.ReadProcessMemory((IntPtr)0x,out bytesReaded);
iWidth = memory[0];
pReader.CloseHandle();
在结论部分,我列出了显示布雷图的完整代码。别忘了,我要访问的所有内存位置就是在本文第一部分中所找到位置。
布雷图的资料管理器
System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(Form1));
ProcessMemoryReaderLib.ProcessMemoryReader pReader
= new ProcessMemoryReaderLib.ProcessMemoryReader();
System.Diagnostics.Process[] myProcesses
= System.Diagnostics.Process.GetProcessesByName(&winmine&);
获得“扫雷”进程的第一个实列
if (myProcesses.Length == 0)
MessageBox.Show(&No MineSweeper process found!&);
pReader.ReadProcess = myProcesses[0];
以读内存模式打开进程
pReader.OpenProcess();
int bytesR
int iWidth, iHeight, iM
int iCellA
memory = pReader.ReadProcessMemory((IntPtr)0x,out bytesReaded);
iWidth = memory[0];
txtWidth.Text = iWidth.ToString();
memory = pReader.ReadProcessMemory((IntPtr)0x,out bytesReaded);
iHeight = memory[0];
txtHeight.Text = iHeight.ToString();
memory = pReader.ReadProcessMemory((IntPtr)0x,out bytesReaded);
iMines = memory[0];
txtMines.Text = iMines.ToString();
删除以前的按钮数组
this.Controls.Clear();
this.Controls.AddRange(MainControls);
创建一个按钮数组 ,
用于画出布雷图的每一格
ButtonArray = new System.Windows.Forms.Button[iWidth,iHeight];
for (y=0 ; y&iH y++)
for (x=0 ; x&iW x++)
ButtonArray[x,y] = new System.Windows.Forms.Button();
ButtonArray[x,y].Location = new System.Drawing.Point(20 + x*16, 70 + y*16);
ButtonArray[x,y].Name = &&;
ButtonArray[x,y].Size = new System.Drawing.Size(16,16);
iCellAddress = (0x1005340) + (32 * (y+1)) + (x+1);
memory = pReader.ReadProcessMemory((IntPtr)iCellAddress,1,out bytesReaded);
iIsMine = memory[0];
if (iIsMine == 0x8f)// 如果有雷,则画出地雷位图
ButtonArray[x,y].Image = ((System.Drawing.Bitmap)
(resources.GetObject(&button1.Image&)));
this.Controls.Add(ButtonArray[x,y]);
关闭进程句柄
pReader.CloseHandle();
就是这些,希望你能学到新的东西。
扫雷的代码有大概6页,你还想要吗?
程序如下:#include&stdio.h&#include&stdlib.h&void main(){int a[100];int i
import java.awt.event.ActionE import java.awt.event.ActionL import
你想学编程,为了写游戏或者写外挂而学是不可能的。且不说游戏的复杂程度,仅仅外挂的基本原理,就够你搞上5年了。再用5年去想办法对付nProtect(现在好多游戏都
先C/C++(谭浩强),再VC(windows程序设计),然后你会发现有很多框架可以用了,比如mfc,写些小游戏没问题。
但是绝对不是你玩游戏那么轻松的..加
新手如何学习C语言
第一:一些概念。
C语言是一门程序设计语言,有一些标准,比较重要的是ANSI C(好像是C89)和C99。
数据结构包括逻辑结构和物理
这个坦白地说,非常难,但也不是不可以,就看你有没有恒心了。
需要学习JAVA SE的基础,包括AWT、SWING的一些知识,二进制与文本IO,3D图象,可能还
basic是一种汇编语言,计算机可以直接读懂用它编写的程序。这句话是对的。
1、如你用的XP,能系统还原就系统还原吧2、杀毒2、重装系统
你去新浪或者太平洋游戏网里看看啊,那里有很多攻略和高手指点的办法呢!!
要不要我帮你写一段,你后面没扫描,当然无法获取键值t1:mov p1,#0p1接口高4位为0,低4位输入 mov a,p1 ;读p1 anl a,#0f
大家都关注
(C)2017 列表网&琼ICP备号-12&增值电信业务经营许可证B2-&}

我要回帖

更多关于 c语言扫雷 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信