亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C語言開發(fā)簡易版掃雷小游戲

 更新時間:2015年12月11日 08:53:35   作者:AnnsShadoW  
本文給大家分享的是一個使用C語言開發(fā)的命令行下的簡易版掃雷小游戲,本身沒有什么太多的技術(shù)含量,只不過是筆者的處女作,所以還是推薦給大家,希望對大家學(xué)習(xí)C能夠有所幫助。

前言:

  想起來做這個是因為那時候某天知道了原來黑框框里面的光標(biāo)是可以控制的,而且又經(jīng)常聽人說起這個,就鍛煉一下好了。

  之前就完成了那1.0的版本,現(xiàn)在想放上來分享卻發(fā)現(xiàn)有蠻多問題的,而且最重要的是沒什么注釋【果然那時候太年輕】!現(xiàn)在看了也是被那時候的自己逗笑了,就修改了一些小bug,增加了算是詳盡而清楚的注釋,嗯,MSDN上面對各種函數(shù)的解釋很詳細(xì)的【又鍛煉一下英語】,順便讓開頭和結(jié)尾的展示“動”了起來,就當(dāng)作1.5的版本好了。

  這個只是給出了一個實現(xiàn)的思路,其中肯定也有很多不合理的地方和可優(yōu)化之處,希望能供大家參考和交流。

過程:

  期間也是遇到了蠻多困惑的。

  1.最先的是怎么知道按了方向鍵,左查右找,說法有好幾個版本呢,就想看能不能自己測試一下自己的好了,再查再找,好了,感謝寫了測試方向鍵的人;

  2.再比如說怎么消除窗口中一行的緩沖,因為不消除就一直在哪,視覺效果不好,翻查了一下資料,就寫了delLine()這個來做這個事情了;

  3.設(shè)定顏色時,在cmd里面help color知道了顏色的參數(shù),但是通過數(shù)字0-9來設(shè)定的太暗了,發(fā)現(xiàn)有更亮的,比如0A,在setColor()里面用它卻說類型不對,于是上MSDN,發(fā)現(xiàn)還可以用宏,就想通過如'BACKGROUND_INTENSITY  | BACKGROUND_RED '之類來完成,就想怎么去代替那個宏,覺得每次寫一長串好麻煩。然后換了各種類型的參數(shù)類型和不定長參數(shù)什么的,發(fā)現(xiàn)還是不行,后來一想,萬一它支持?jǐn)?shù)字10呢,A不就是10么?!一測,成了;

  4.還有一些判斷狀態(tài)的順序,嗯啊,這些要先想好再下手,不然左改右改很麻煩呢;

  5.別的困惑不怎么記得了。。。

代碼:

  下面分別給出LittleMines【好弱的名字】,測試顏色,測試方向鍵的代碼。【反映說有行號不好復(fù)制,那取消好了】

/*********************************
* c語言命令行+方向鍵簡易版掃雷
* Author:AnnsShadoW
* Version:1.5
* Time:2015-11-29
********************************/

/********************************
* 運行環(huán)境:Windows10-64bit
* 編譯環(huán)境:Codeblocks-13.12
********************************/

//用到的都導(dǎo)進去吧
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
#include <windows.h>

//定義各種判斷狀態(tài)的ASCII碼
//MINE是定義翻開格子中的‘*'號
#define MINE   42
#define ESC    27
#define ENTER   13
#define SPACE   32
#define UP    72
#define DOWN   80
#define LEFT   75
#define RIGHT   77

//定義類型狀態(tài),方便后續(xù)判斷
#define bool int
#define true 1
#define false 0
#define ROW    10
#define COLUMN   10
#define ALL_MINES  15

//當(dāng)前位置的結(jié)構(gòu)體
typedef struct currentPosition_struct
{
 int x;
 int y;
} currentPosition;

//每一個小格的結(jié)構(gòu)體
typedef struct blockCondition_struct
{
 //是否被覆蓋了
 bool beCovered;
 //以它為中心周圍的雷數(shù)
 int minesNum;
} blockCondition;

//光標(biāo)的位置數(shù)組
currentPosition cursorPos[ROW][COLUMN];
//雷區(qū)地圖的數(shù)組
blockCondition minesMap[ROW][COLUMN];
//剩下的格子數(shù)
int leftBlocksNum = ROW * COLUMN;
//光標(biāo)在光標(biāo)位置、雷區(qū)地圖中的下標(biāo)
int index_x = 0, index_y = 0;

//設(shè)置窗口前后背景色
void setColor(unsigned short color);
//開頭的歡迎“動畫”
void welcomeToMyGame();
//游戲地圖初始化
void gameInitailize();
//以某格子為中心計算驚天雷數(shù)量
void countMines();
//獲取鍵盤的輸入
void keyBoardInput();
//指定光標(biāo)的位置
void setCurPos(int y, int x);
//移動光標(biāo)的位置
void moveCursor(int y, int x);
//檢測每一步的結(jié)果
bool checkResult(int y, int x);
//輸出游戲界面
void printMap();
//游戲退出后的“動畫”
void gameOver(char *str);
//刪除窗口中一行的緩沖
void delLine(int y);


int main()
{
 setColor(10);
 system("cls");
 welcomeToMyGame();
 gameInitailize();
 countMines();
 printMap();

 for(;;)
 {
  setCurPos(cursorPos[index_y][index_x].y, cursorPos[index_y][index_x].x);
  keyBoardInput();
 }

 return EXIT_SUCCESS;
}

void setColor(unsigned short color)
{
 HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
 //對設(shè)置之后的輸出有效
 SetConsoleTextAttribute(hCon, color);
};

void welcomeToMyGame()
{
 int i = 0;
 char introductions0[] = "LittleMines";
 char introductions1[] = "--";
 char introductions2[] = "Version 1.5";
 char introductions3[] = "Author:AnnsShadow,thank you ╮( ̄▽ ̄)╭";

 //控制臺窗口默認(rèn)大小是80*25,所以能達到最大的位置是[79,24]
 for(i = 0; i <= 5; ++i)
 {
  //每次輸出之前都清屏,就會有看起來是動的效果
  system("cls");
  //縱坐標(biāo)不斷加,形成向下效果
  setCurPos(i, (80 - strlen(introductions0)) / 2);
  printf("%s", introductions0);
  //緩沖一下,太快了看不到呢
  Sleep(50);
 }

 //為了對稱,從邊邊78開始到中間39好了
 for(i = 78; i >= 39; --i)
 {
  //上面用了5行了,大于它吧
  setCurPos(7, i);
  printf("%s", introductions1);
  setCurPos(7, 78 - i);
  printf("%s", introductions1);
  Sleep(40);
 }

 //從左邊一步步進入屏幕中間
 for(i = 0; i <= (80 - strlen(introductions2)) / 2; ++i)
 {
  //要刪除這一行緩沖的原因:
  //上一次循環(huán)的輸出會影響到下一次,如輸出VVVVVVVVVVersion1.0
  //換成中文就不會,中文要兩個字節(jié)才能顯示完整呀
  delLine(9);
  //這里就會有閃閃發(fā)亮的效果哦
  Sleep(10);
  setCurPos(9, i);
  printf("%s", introductions2);
  Sleep(50);
 }

 //從底部進入
 for(i = 24; i >= 12; --i)
 {
  setCurPos(i, (80 - strlen(introductions3)) / 2);
  printf("%s", introductions3);
  Sleep(20);
  //刪除上一次的緩沖,不加1的話最后一行就會殘留,其它都不見了
  delLine(i + 1);
  Sleep(50);
 }

 Sleep(500);
 char help0[] = "動?。骸r(╯▽╰)╭";
 char help1[] = "點擊啊:Space / Enter (ΘェΘ)";
 char help2[] = "不玩啦:Esc (>﹏<)";
 char help3[] = "<<愿你玩的開心 _(:з」∠)_>>";
 setCurPos(14, (80 - strlen(help0)) / 2);
 setColor(14);
 printf("%s", help0);
 setCurPos(15, (80 - strlen(help1)) / 2);
 printf("%s", help1);
 setCurPos(16, (80 - strlen(help2)) / 2);
 printf("%s", help2);
 setCurPos(17, (80 - strlen(help3)) / 2);
 setColor(15);
 printf("%s", help3);
 getch();
}

void gameInitailize()
{
 int i = 0, j = 0;
 int allMines = ALL_MINES;
 //設(shè)置隨機值
 srand((unsigned int)time(NULL));

 //雷區(qū)地圖初始化
 for(i = 0; i < ROW; ++i)
 {
  for(j = 0; j < COLUMN; ++j)
  {
   minesMap[i][j].beCovered = true;
   minesMap[i][j].minesNum = 0;
  }
 }

 //放置驚天雷!
 while(allMines)
 {
  i = rand() % ROW;
  j = rand() % COLUMN;

  if(minesMap[i][j].minesNum == 0)
  {
   //這個‘-1'就作為判斷驚天雷的依據(jù)了
   minesMap[i][j].minesNum = -1;
   --allMines;
  }
 }

 //光標(biāo)位置初始化
 for(i = 0; i < ROW; ++i)
 {
  for(j = 0; j < COLUMN; ++j)
  {
   cursorPos[i][j].x = j * 6 + 3;
   cursorPos[i][j].y = i * 2 + 1;
  }
 }
}

void countMines()
{
 int i = 0, j = 0, m = 0, n = 0;
 //以格子為中心周圍的雷數(shù)
 int minesNum = 0;

 for(i = 0; i < ROW; ++i)
 {
  for(j = 0; j < COLUMN; ++j)
  {
   //遇到驚天雷就放棄統(tǒng)計吧
   if(minesMap[i][j].minesNum == -1)
    continue;
   minesNum = 0;
   //九宮格嘛,那3次好了
   for(m = -1; m <= 1; ++m)
   {
    //行溢出了沒,不能算沒有的哦
    if(i + m < 0 || i + m >= ROW)
    {
     continue;
    }

    for(n = -1; n <= 1; ++n)
    {
     //這次就是看列溢出了沒
     if(j + n < 0 || j + n >= COLUMN)
     {
      continue;
     }
     //周邊有驚天雷趕緊加起來
     if(minesMap[i + m][j + n].minesNum == -1)
     {
      ++minesNum;
     }
    }
   }
   minesMap[i][j].minesNum = minesNum;
  }
 }
}

void keyBoardInput()
{
 bool lose;
 int key1 = getch();

 /*****************************
 測試之后才知道方向鍵兩個字節(jié)
 第一個字節(jié)ASCII 0x00e0 224
 第二個字節(jié)分別是:
 上:0x0048 72
 下:0x0050 80
 左:0x012b 75
 右:0x012d 77
 *****************************/

 if(key1 == 224)
 {
  int key2 = getch();

  switch(key2)
  {
  case UP:
   moveCursor(index_y - 1, index_x);
   break;

  case DOWN:
   moveCursor(index_y + 1, index_x);
   break;

  case LEFT:
   moveCursor(index_y, index_x - 1);
   break;

  case RIGHT:
   moveCursor(index_y, index_x + 1);
   break;

  default:
   break;
  }
 }
 else
 {
  switch(key1)
  {
  case ENTER:
  case SPACE:
   lose = checkResult(index_y, index_x);
   system("cls");
   printMap();

   if(lose)
   {
    setColor(13);
    printf("|    誒喲,還差一點點哦! ╥﹏╥     |\n");
    printf("|     按\"r\"重玩,Esc不玩啦。     |\n");
    printf("[%c]-------------------------------------------------------[%c]\n", MINE, MINE);
    setColor(10);
    Sleep(1000);
    char key3 = getch();

    if(key3 == 'r' || key3 == 'R')
    {
     //重來,跟main中過程是一樣的
     setColor(10);
     gameInitailize();
     countMines();
     printMap();
    }
   }
   //剩余的格子比雷還要多,可以繼續(xù)玩
   else if(leftBlocksNum > ALL_MINES)
   {
    setColor(13);
    printf("|     哎喲,挺不錯哦~ ( ̄0  ̄)    |\n");
    printf("[%c]-------------------------------------------------------[%c]\n", MINE, MINE);
    setColor(10);
   }
   //來到這你已經(jīng)贏了
   else
   {
    setColor(13);
    printf("|     喲,恭喜你贏了(/≧▽≦/)    |\n");
    printf("|     按\"r\"重玩,Esc就不玩啦。     |\n");
    printf("[%c]-------------------------------------------------------[%c]\n", MINE, MINE);
    setColor(10);
    Sleep(1000);
    char key3 = getch();

    if(key3 == 'r' || key3 == 'R')
    {
     setColor(10);
     gameInitailize();
     countMines();
     printMap();
    }
   }

   break;

  case ESC:
   system("cls");
   gameOver("\t\t\t啦啦啦~很逗很扯吧~最后感謝你的玩耍呀(≧Д≦)\n\n\n\n\n\n\n\n");

  default:
   break;
  }
 }
}


void setCurPos(int y, int x)
{
 //在窗口緩沖中定義每個位置的狀態(tài)
 COORD currentPosition;
 currentPosition.Y = y;
 currentPosition.X = x;
 //所以現(xiàn)在的位置是在{y,x}
 SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), currentPosition);
}

void moveCursor(int y, int x)
{
 //限定能走的地方
 if((x >= 0 && x < COLUMN) && (y >= 0 && y < ROW))
 {
  setCurPos(cursorPos[y][x].y, cursorPos[y][x].x);
  index_x = x;
  index_y = y;
 }
}

bool checkResult(int y, int x)
{
 int i = 0, j = 0;

 //檢測有沒有溢出地圖了
 if(x < 0 || x >= COLUMN || y < 0 || y >= ROW)
 {
  return false;
 }

 //就是你了!被選中的格子!
 minesMap[y][x].beCovered = false;

 //被驚天雷炸了
 if(minesMap[y][x].minesNum == -1)
 {
  minesMap[y][x].minesNum = 9;
  return true;
 }

 //如果沒有雷,就當(dāng)作空格吧
 if(minesMap[y][x].minesNum > 0 && minesMap[y][x].minesNum < 9)
 {
  return false;
 }

 //九宮格,3x3咯
 for(i = -1; i <= 1; ++i)
 {
  //檢查一下在這一行溢出了沒吧
  if(y + i < 0 || y + i >= ROW)
  {
   continue;
  }

  for(j = -1; j <= 1; ++j)
  {
   //這次就到列了吧
   if(x + j < 0 || x + j >= COLUMN)
   {
    continue;
   }
   //如果下一個是沒開過的,就檢查它吧
   if(minesMap[y + i][x + j].beCovered)
   {
    minesMap[y + i][x + j].beCovered = false;
    checkResult(y + i, x + j);
   }
  }
 }

 return false;
}

void printMap()
{
 system("cls");
 char help0[] = "←↑↓→";
 char help1[] = "動啊";
 char help2[] = "Space / Enter";
 char help3[] = "點擊啊";
 char help4[] = "Esc 不玩啦";
 //因為要輸出提示,所以地圖不能太大了,10x10就差不多了
 setColor(14);
 setCurPos(4, 62);
 printf("%s", help0);
 setCurPos(6, 62);
 printf("%s", help1);
 setCurPos(9, 62);
 printf("%s", help2);
 setCurPos(11, 62);
 printf("%s", help3);
 setCurPos(14, 62);
 printf("%s", help4);
 setCurPos(0, 0);
 setColor(10);

 int i = 0, j = 0, k = 0;
 leftBlocksNum = 0;
 setColor(11);
 printf("[開]--");
 setColor(10);

 for(k = 1; k < COLUMN - 1; ++k)
 {
  printf("+-----");
 }
 setColor(11);
 printf("+--[心]\n");
 setColor(10);

 for(i = 0; i < ROW; ++i)
 {
  for(j = 0; j < COLUMN; ++j)
  {
   if(minesMap[i][j].beCovered)
   {
    ++leftBlocksNum;
    //這個輸出的就是格子被覆蓋的時候輸出的圖形,可以換成1-6試試
    //1-4是正方形的4個角,5-6是雙豎線和雙橫線
    printf("| %c ", 3);
   }
   else if(minesMap[i][j].minesNum == -1 || minesMap[i][j].minesNum == 9)
   {
    printf("| %c ", MINE);
   }
   else if(minesMap[i][j].minesNum == 0)
   {
    printf("| %c ", ' ');
   }
   else
   {
    printf("| %d ", minesMap[i][j].minesNum);
   }
  }

  printf("|\n");

  if(i < ROW - 1)
  {
   for(k = 0; k < COLUMN; ++k)
   {
    printf("+-----");
   }

   printf("+\n");
  }
 }
 setColor(11);
 printf("[就]--");
 setColor(10);

 for(k = 1; k < COLUMN - 1; ++k)
 {
  printf("+-----");
 }
 setColor(11);
 printf("+--[好]\n");
 setColor(10);
}

void gameOver(char *str)
{
 setColor(12);
 system("cls");
 setCurPos(10, 0);
 int i = 0;

 do
 {
  //逐字輸出
  printf("%c", str[i]);
  Sleep(60);
 }
 while(str[i++]);
 setColor(15);
 system("pause");
 //隨意終止程序并返回給OS,0是正常的
 exit(0);
}

void delLine(int y)
{
 HANDLE hOutput;
 //窗口緩存信息
 CONSOLE_SCREEN_BUFFER_INFO sbi;
 DWORD len, nw;
 //用MSDN上的TCHAR類型跪了,換成char就好
 char fillchar = ' ';
 //定位光標(biāo)
 COORD startPosition = {0, y};
 //獲取輸出句柄
 hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
 //獲取窗口緩沖中的信息
 GetConsoleScreenBufferInfo(hOutput, &sbi);
 //窗口緩沖的位置,這里取得X值
 len = sbi.dwSize.X;
 //從特定的位置用特定的字符去填充窗口的緩沖特定次數(shù)
 //成功返回非0值,一般都成功,就不判斷了
 FillConsoleOutputCharacter(hOutput, fillchar, len, startPosition, &nw);
}

測試顏色:

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>

void setColor(unsigned short color)
{
 HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
 //對設(shè)置之后的輸出有效
 SetConsoleTextAttribute(hCon, color);
};

int main()
{
 //測試顏色啊~~
 for(int i = 0; i <= 255; i++)
 {
  setColor(i);
  printf("%d\n", i);
  system("pause");
 }
 return 0;
}

測試方向鍵:

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <conio.h>

int main()
{
 unsigned short int k;

 while(1)
 {
  _sleep(100);

  if(_kbhit())
  {
   k = _getch();

   if(0 == k)
    k = _getch() << 8;

   _cprintf("key:0x%04x pressed\r\n", k);
  }
 }
 system("pause");
 return 0;
}

運行截圖:圖片不會動啦,在自己機子跑起來就看得到動的效果了~~~

后話:

  雖然不是什么很厲害的事情,稍微懂點的都可以自己做出來,不過在實踐的過程中還是收獲蠻多的,在這分享也算個小小的記錄吧,繼續(xù)加油~

相關(guān)文章

  • C++符號優(yōu)先級(詳細(xì)整理)

    C++符號優(yōu)先級(詳細(xì)整理)

    C++符號優(yōu)先級,我詳細(xì)整理了一下。需要的朋友可以過來參考下。希望對大家有所幫助
    2013-10-10
  • Matlab實現(xiàn)鼠標(biāo)光標(biāo)變成愛心和瞄準(zhǔn)鏡形狀

    Matlab實現(xiàn)鼠標(biāo)光標(biāo)變成愛心和瞄準(zhǔn)鏡形狀

    這篇文章主要為大家詳細(xì)介紹了如何利用Matlab實現(xiàn)將鼠標(biāo)光標(biāo)變成愛心和瞄準(zhǔn)鏡等形狀,文中的示例代碼講解詳細(xì),感興趣的可以了解一下
    2022-08-08
  • c語言版本二叉樹基本操作示例(先序 遞歸 非遞歸)

    c語言版本二叉樹基本操作示例(先序 遞歸 非遞歸)

    這篇文章主要介紹了實現(xiàn)二叉樹的創(chuàng)建(先序)、遞歸及非遞歸的先、中、后序遍歷
    2013-11-11
  • C++之string類對象的容量操作詳解

    C++之string類對象的容量操作詳解

    通過在網(wǎng)站上的資料搜集,得到了很多關(guān)于string類對象的容量操作,通過對這些資料的整理和加入一些自己的代碼,希望能夠給你帶來幫助
    2021-08-08
  • Qt下調(diào)用vlc庫實現(xiàn)RTSP拉流播放和截圖過程詳解

    Qt下調(diào)用vlc庫實現(xiàn)RTSP拉流播放和截圖過程詳解

    這篇文章主要為大家介紹了Qt下調(diào)用vlc庫實現(xiàn)RTSP拉流播放和截圖過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-08-08
  • c語言中scanf的基本用法

    c語言中scanf的基本用法

    這篇文章主要給大家介紹了關(guān)于c語言中scanf的基本用法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • C++實現(xiàn)簡單的HTTP服務(wù)器

    C++實現(xiàn)簡單的HTTP服務(wù)器

    這篇文章主要為大家詳細(xì)介紹了C++實現(xiàn)簡單的HTTP服務(wù)器的相關(guān)資料,感興趣的朋友可以參考下
    2016-05-05
  • C++入門筆記之std::vector容器詳解

    C++入門筆記之std::vector容器詳解

    這篇文章主要給大家介紹了關(guān)于C++之std::vector容器的相關(guān)資料,vector,一種隨機訪問的數(shù)組類型,它提供了對數(shù)組元素的快速、隨機訪問,以及在序列尾部快速、隨機的插入和刪除操作,需要的朋友可以參考下
    2021-07-07
  • C語言實現(xiàn)按月顯示的日歷

    C語言實現(xiàn)按月顯示的日歷

    這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)按月顯示的日歷,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • C++ 情懷游戲掃雷的實現(xiàn)流程詳解

    C++ 情懷游戲掃雷的實現(xiàn)流程詳解

    掃雷是電腦上很經(jīng)典很經(jīng)典的傳統(tǒng)老游戲,從小編第一次摸到計算機開始就玩過掃雷,雖然當(dāng)時并不理解玩法原理,但終是第一次玩電腦游戲,下面來從掃雷的前世今生講起
    2021-11-11

最新評論