欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言實現自定義掃雷游戲(遞歸版)

 更新時間:2022年03月29日 14:52:19   作者:caco9527  
這篇文章主要為大家詳細介紹了C語言實現自定義掃雷游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了C語言自定義掃雷游戲的具體代碼,供大家參考,具體內容如下

實現過程

對于用C語言實現掃雷游戲得實現,可將游戲過程分為兩個板塊。

  • 實現游戲關鍵功能得函數
  • 搭建合理得游戲過程

實現游戲關鍵功能

為了將游戲功能方便管理和鍵入,首先我們創(chuàng)建一個頭文件,mine.h對游戲功能進行聲明。
然后創(chuàng)建對應的源文件mine.c對這些函數進行定義。

對于游戲功能,我們首先想到的是構建一個目標規(guī)格的雷盤,也就是二維數組。
為了使游戲更具可玩性,所以雷盤的規(guī)格應可以自定義。所以在mine.h頭文件中,應先用define定義ROW(行)和列(列)的標識符便于自定義。

#define ROW 15 ?//先將他們的規(guī)格定義為15*15
#define COL 15
#define ROWS ROW+2
#define COLS COL+2

為什么要定義后面兩個宏?

對于雷盤的的核心功能實現,必然是能夠當玩家選擇坐標以后(若該位置不是雷)能夠精確的統(tǒng)計以該坐標為核心周圍九宮格雷的個數,那么處于邊界的地方該如何精準的判斷呢?

所以將真正的雷盤數組規(guī)格定義ROW+2,COL+2大小,在ROW,COL規(guī)格的雷盤中隨機置雷,使得游戲結果準確。

  • 定義雷盤和顯示盤的初始化

定義兩同規(guī)格的二維數組,前者是真正的雷區(qū),用‘1’和‘0’來表示雷和無雷,后者是顯示區(qū),用于玩家操作和結果顯示。

void init(char arr[ROWS][COLS], int rows, int cols, char type) //memset批量操作時傳入的是指針,即數組開始地址
{
? ? memset(arr, type, rows*cols * sizeof(mine[0][0]));
}
  • 在顯示區(qū)隨機放置雷
void setmine(char mine[ROWS][COLS], int count)
{
? ? srand((unsigned)time(NULL));
? ? int i = 0;
? ? int j = 0;
? ? while (count)
? ? {
? ? ? ? i = (rand() % ROW) + 1; ?//讓隨機值0-9變成1-10 實現操作區(qū)隨機放雷
? ? ? ? j = (rand() % COL) + 1;
? ? ? ? if (mine[i][j] == '0')
? ? ? ? {
? ? ? ? ? ? mine[i][j] = '1';
? ? ? ? ? ? count--;
? ? ? ? }
? ? }
}
  • 打印界面
void display(char board[ROWS][COLS])
{//從第一行一列開始打因元素
? ? int i = 0;
? ? int j = 0;


? ? printf("\n ? ? ?|");
? ? for (i = 1; i <= COL; i++)//打印操作區(qū)的列號
? ? {
? ? ? ? printf("%4d", i); ?//打印序號
? ? }
? ? printf("\n");
? ? printf("------|------------------------------------------\n");
? ? for (i = 1; i <= ROW; i++)
? ? {
? ? ? ? printf("%4d ?|", i);//打印序號
? ? ? ? for (j = 1; j <= COL; j++)
? ? ? ? {
? ? ? ? ? ? printf("%4c", board[i][j]);
? ? ? ? }
? ? ? ? printf("\n ? ? ?\n");
? ? }
}
  • 統(tǒng)計目標點周圍雷的個數
int cal_mine(char mine[ROWS][COLS], int x, int y)
{
? ? return (mine[x - 1][y - 1] + mine[x - 1][y]
? ? ? ? + mine[x - 1][y + 1] + mine[x][y - 1]
? ? ? ? + mine[x][y + 1] + mine[x + 1][y - 1]
? ? ? ? + mine[x + 1][y] + mine[x + 1][y + 1] - (7 * '0'));//這里減7而不是8。因為這樣直接可以表示出數字字符
? ? //此處的目的是統(tǒng)計周圍雷的個數,又因為是ASCII碼,'1'和'0'只相差1,然后進去'0'的ASCII值得到1的個數


}

如果目標點周圍無雷向外擴展

在掃雷游戲過程中必然會出來一點一大片凹陷的強烈快感,但自己實現的過程中這是如何做到的呢?
原則是如果該點周圍無雷,那么將用空格替代,然后向四周伸展將周圍的“周圍無雷點”繼續(xù)用空格替代,若四周存在“周圍有雷點”,那么停止向周圍延伸。

在苦思冥想后,想到了用遞歸的方法來實現這個一點一大片功能。

void expand(char mine[ROWS][COLS], char board[ROWS][COLS], int x, int y)
{
? ? if (x >= 1 && x <= ROW&&y >= 1 && y <= COL) // 遞歸防止越界
? ? {
? ? ? ? /*if (mine[x][y] == '0')*/
? ? ? ? {
? ? ? ? ? ? char count = cal_mine(mine, x, y);
? ? ? ? ? ? if (count == '0')
? ? ? ? ? ? {
? ? ? ? ? ? ? ? board[x][y] = ' ';
? ? ? ? ? ? ? ? if (board[x - 1][y - 1] == '*')
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? expand(mine, board, x - 1, y - 1);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? if (board[x - 1][y] == '*')
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? expand(mine, board, x - 1, y);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? if (board[x - 1][y + 1] == '*')
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? expand(mine, board, x - 1, y + 1);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? if (board[x][y - 1] == '*')
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? expand(mine, board, x, y - 1);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? if (board[x][y + 1] == '*')
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? expand(mine, board, x, y + 1);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? if (board[x + 1][y - 1] == '*')
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? expand(mine, board, x + 1, y - 1);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? if (board[x + 1][y] == '*')
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? expand(mine, board, x + 1, y);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? if (board[x + 1][y + 1] == '*')
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? expand(mine, board, x + 1, y + 1);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? else
? ? ? ? ? ? {
? ? ? ? ? ? ? ? board[x][y] = count;
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
  • 判斷勝利

若顯示區(qū)最終剩下的*等于雷數,那么玩家勝利

int is_win(char board[ROWS][COLS])
{
int count = 0;
int i = 0, j = 0;
for (i = 1; i <= ROW; i++)
{
? ? for (j = 1; j <= COL; j++)
? ? {
? ? ? ? if ('*' == board[i][j])
? ? ? ? {
? ? ? ? ? ? count++;
? ? ? ? }
? ? }
}
return count;
}
  • 玩家操作
int player(char mine[ROWS][COLS], char board[ROWS][COLS], int count)
{
? ? int x = 0, y = 0;
? ? while (1)//檢測輸入錯誤區(qū)
? ? {
? ? ? ? while (2 != scanf("%d %d", &x, &y))
? ? ? ? {
? ? ? ? ? ? while ((getchar() != '\n')) ?//如果玩家輸入了很多非法字符,那么將他們全部吸收
? ? ? ? ? ? {
? ? ? ? ? ? ? ? NULL;
? ? ? ? ? ? }
? ? ? ? ? ? printf("輸的是啥玩意?\n");
? ? ? ? }
? ? ? ? if (x < 1 || x > ROW || y < 1 || y > COL)
? ? ? ? {


? ? ? ? ? ? printf("輸入越界\n");
? ? ? ? }
? ? ? ? else if (board[x][y] != '*')
? ? ? ? {
? ? ? ? ? ? printf("你踩過了!\n");
? ? ? ? }
? ? ? ? else
? ? ? ? {
? ? ? ? ? ? if (count == 1 && (mine[x][y] == '1')) //!mine[x][y]=='1'這個條件特別重要!!如果玩家沒有踩到雷那么將會使這個位置變成雷!!
? ? ? ? //雖然這樣并不影響程序完整運行,因為檢驗雷點是通過存在的*來計數的,這個值附上去以后肯定恒為1占去了*,但是嚴謹的玩家肯定說你有BUG
? ? ? ? ? ? ? ? //所以我們還是盡量寫通俗易懂的邏輯程序 下面的while循環(huán)會讓人感覺是檢測,其實是賦值轉換
? ? ? ? ? ? {
? ? ? ? ? ? ? ? int i = 0, j = 0;
? ? ? ? ? ? ? ? while (mine[x][y] == '1')
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? i = (rand() % 10) + 1;
? ? ? ? ? ? ? ? ? ? j = (rand() % 10) + 1;
? ? ? ? ? ? ? ? ? ? mine[x][y] = mine[i][j];//將值為符號零的元素賦給操作數,
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? mine[i][j] = '1';//賦值如果成功那么便讓他成為1
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? break;
? ? }
? ? if (mine[x][y] == '1')//檢驗開始
? ? {
? ? ? ? printf("\n新時代的董存瑞!\n");
? ? ? ? return 1;

? ? }
? ? else
? ? {
? ? ? ? expand(mine, board, x, y);
? ? }
? ? return is_win(board);
}

最后將這些聲明和定義轉入到mine.hmine.c

搭建合理的游戲過程

將這些函數功能合理的整個在一起后,在mian函數存在的源文件中創(chuàng)建定義game()函數,將每一步連接在一起。創(chuàng)建menu()函數顯示菜單。

game()

void game()
{
? ? printf("歡\n"); Sleep(250);
? ? printf("迎\n"); Sleep(250);
? ? printf("來\n"); Sleep(250);
? ? printf("到\n"); Sleep(250);
? ? printf("caco\n"); Sleep(250);
? ? printf("的\n"); Sleep(250);
? ? printf("掃\n"); Sleep(250);
? ? printf("雷!\n"); Sleep(250);
? ? printf("村"); Sleep(250);
? ? printf("!"); Sleep(150);
? ? printf("!"); Sleep(150);
? ? char mine[ROWS][COLS] = { 0 };
? ? char board[ROWS][COLS] = { 0 };
? ? init(mine, ROWS, COLS, '0');
? ? init(board, ROWS, COLS, '*');
? ? int num = 0;
? ? printf("\n要幾個雷\n?");
? ? scanf("%d", &num);
? ? setmine(mine, num);
? ? display(mine);
? ? int count = 1;
? ? int ret = 0;

? ? while (1)
? ? {
? ? ? ? display(board);
? ? ? ? ret = player(mine, board, count);


? ? ? ? count++;
? ? ? ? if (ret == num) ?//和玩家輸入得雷數要保持一致
? ? ? ? {
? ? ? ? ? ? printf("炸不死得諾貝爾~!\n");
? ? ? ? ? ? break;
? ? ? ? }
? ? ? ? if (ret == 1)
? ? ? ? {
? ? ? ? ? ? break; ? //表示直接菜到雷退出
? ? ? ? }
? ? }

}

munu()

void menu()
{
? ? printf("*******************************************\n");
? ? printf("------ 我可以大口吞下炸彈而不傷身體--------\n"); ?//label 1. original test.
? ? printf("------1. ?進村 ? -------------------------\n-------------------------\n");
? ? printf("------0. ?撤退! -------------------------\n");
? ? printf("*******************************************\n");


}
int main()
{
? ? int a = 0;
? ? menu();


? ? do
? ? {

? ? ? ? scanf("%d", &a);
? ? ? ? switch (a)
? ? ? ? {
? ? ? ? case 1:
? ? ? ? ? ? game();
? ? ? ? ? ? menu();
? ? ? ? ? ? break;


? ? ? ? case 0:
? ? ? ? ? ? return 0;
? ? ? ? default:
? ? ? ? ? ? printf("\n進村還是不進?\n");
? ? ? ? }
? ? } while (a);

}

main()函數

int main()
{
? ? int a = 0;
? ? menu();


? ? do
? ? {
? ? ? ? scanf("%d", &a);
? ? ? ? switch (a)
? ? ? ? {
? ? ? ? case 1:
? ? ? ? ? ? game();
? ? ? ? ? ? menu();
? ? ? ? ? ? break;


? ? ? ? case 0:
? ? ? ? ? ? return 0;
? ? ? ? default:
? ? ? ? ? ? printf("\n進村還是不進?\n");
? ? ? ? }
? ? } while (a);

}

程序展示

mine.h

#pragma once
#define ROW 15
#define COL 15
#define ROWS ROW+2
#define COLS COL+2
void init(char mine[ROWS][COLS], int rows, int cols, char type);//初始化數組
void setmine(char mine[ROWS][COLS], int count);//放置隨機雷
void display(char board[ROWS][COLS]);//顯示界面
int cal_mine(char mine[ROWS][COLS], int x, int y);//統(tǒng)計周圍雷的個數
int player(char mine[ROWS][COLS], char board[ROWS][COLS],int count);//玩家操作
void expand(char mine[ROWS][COLS], char board[ROWS][COLS], int x, int y);//遞歸展開
int is_win(char board[ROWS][COLS]);//判斷勝利

mine.c

前文已展示定義

main.h

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<Windows.h>
#include"mine.h"
? ? void game()
? ? {
? ? ? ? printf("歡\n"); Sleep(250);
? ? ? ? printf("迎\n"); Sleep(250);
? ? ? ? printf("來\n"); Sleep(250);
? ? ? ? printf("到\n"); Sleep(250);
? ? ? ? printf("caco\n"); Sleep(250);
? ? ? ? printf("的\n"); Sleep(250);
? ? ? ? printf("掃\n"); Sleep(250);
? ? ? ? printf("雷!\n"); Sleep(250);
? ? ? ? printf("村"); Sleep(250);
? ? ? ? printf("!"); Sleep(150);
? ? ? ? printf("!"); Sleep(150);
? ? ? ? char mine[ROWS][COLS] = { 0 };
? ? ? ? char board[ROWS][COLS] = { 0 };
? ? ? ? init(mine, ROWS, COLS, '0');
? ? ? ? init(board, ROWS, COLS, '*');
? ? ? ? int num = 0;
? ? ? ? printf("\n要幾個雷\n?");
? ? ? ? scanf("%d", &num);
? ? ? ? setmine(mine, num);
? ? ? ? display(mine);
? ? ? ? int count = 1;
? ? ? ? int ret = 0;

? ? ? ? while (1)
? ? ? ? {
? ? ? ? ? ? display(board);
? ? ? ? ? ? ret = player(mine, board, count);


? ? ? ? ? ? count++;
? ? ? ? ? ? if (ret == num) ?//和玩家輸入得雷數要保持一致
? ? ? ? ? ? {
? ? ? ? ? ? ? ? printf("炸不死得諾貝爾~!\n");
? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? ? ? if (ret == 1)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? break; ? //表示直接菜到雷退出
? ? ? ? ? ? }
? ? ? ? }

? ? }
? ? void menu()
{
? ? printf("*******************************************\n");
? ? printf("------ 我可以大口吞下炸彈而不傷身體--------\n"); ?//label 1. original test.
? ? printf("------1. ?進村 ? -------------------------\n-------------------------\n");
? ? printf("------0. ?撤退! -------------------------\n");
? ? printf("*******************************************\n");


}
int main()
{
? ? int a = 0;
? ? menu();


? ? do
? ? {
? ? ? ? scanf("%d", &a);
? ? ? ? switch (a)
? ? ? ? {
? ? ? ? case 1:
? ? ? ? ? ? game();
? ? ? ? ? ? menu();
? ? ? ? ? ? break;


? ? ? ? case 0:
? ? ? ? ? ? return 0;
? ? ? ? default:
? ? ? ? ? ? printf("\n進村還是不進?\n");
? ? ? ? }
? ? } while (a);

}

程序運行

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • C++實現String與UF8互轉

    C++實現String與UF8互轉

    這篇文章介紹了C++實現String與UF8互轉的方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-05-05
  • 一篇文章帶你入門C語言數據結構:緒論

    一篇文章帶你入門C語言數據結構:緒論

    這篇文章主要介紹了C語言的數據解構基礎,希望對廣大的程序愛好者有所幫助,同時祝大家有一個好成績,需要的朋友可以參考下,希望能給你帶來幫助
    2021-08-08
  • 獲取當前系統(tǒng)本地時間,精確到毫秒的實例

    獲取當前系統(tǒng)本地時間,精確到毫秒的實例

    下面小編就為大家?guī)硪黄@取當前系統(tǒng)本地時間,精確到毫秒的實例。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-11-11
  • linux下使用g++編譯cpp工程的方法

    linux下使用g++編譯cpp工程的方法

    這篇文章主要介紹了linux下使用g++編譯cpp工程的相關知識,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-03-03
  • C語言單鏈表實現方法詳解

    C語言單鏈表實現方法詳解

    這篇文章主要介紹了C語言單鏈表實現方法,結合實例形式分析了基于C語言的單鏈表定義、創(chuàng)建、添加、刪除、排序、打印等操作技巧,并附帶了相關的優(yōu)化算法,需要的朋友可以參考下
    2018-04-04
  • C語言編程大小端問題示例詳解教程

    C語言編程大小端問題示例詳解教程

    這篇文章主要為大家介紹了C語言編程大小端問題解決的示例內容詳解教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2021-11-11
  • c語言在控制臺判定鼠標左鍵的小例子

    c語言在控制臺判定鼠標左鍵的小例子

    c語言在控制臺判定鼠標左鍵的小例子,需要的朋友可以參考一下
    2013-06-06
  • C/C++編譯器GCC下的常用編譯命令總結

    C/C++編譯器GCC下的常用編譯命令總結

    這篇文章主要介紹了C/C++編譯器GCC下的常用編譯命令總結,本文的示例環(huán)境為Linux系統(tǒng),需要的朋友可以參考下
    2015-08-08
  • C語言代碼實現俄羅斯方塊

    C語言代碼實現俄羅斯方塊

    這篇文章主要為大家詳細介紹了C語言代碼實現俄羅斯方塊,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-01-01
  • C語言初學者代碼中的常見錯誤與問題

    C語言初學者代碼中的常見錯誤與問題

    C語言初學者犯過的很多錯誤都非常典型,在初學者中非常普遍,于是整理了一下,應該對其他初學者有借鑒意義
    2013-11-11

最新評論