C語言之圍棋(利用隊列實現)

来源:https://www.cnblogs.com/mdddd-yep/archive/2022/10/26/16830044.html
-Advertisement-
Play Games

圍棋要實現什麼功能呢? 首先是黑棋和白棋,下麵的代碼,黑棋占領的位置被賦值為1,白棋是2; 其次有幾個圍棋中的規則(不知道是不是這樣的,老師是這麼告訴我的,可以指正):1.塊:上下左右可以連起來的叫塊,一顆棋上下左右四個方向若有棋子,就可以稱作是一塊,一個棋子上下左右都沒有,也可以稱作一塊。2.氣: ...


圍棋要實現什麼功能呢?

首先是黑棋和白棋,下麵的代碼,黑棋占領的位置被賦值為1,白棋是2;

其次有幾個圍棋中的規則(不知道是不是這樣的,老師是這麼告訴我的,可以指正):1.塊:上下左右可以連起來的叫塊,一顆棋上下左右四個方向若有棋子,就可以稱作是一塊,一個棋子上下左右都沒有,也可以稱作一塊。2.氣:就是一個塊周圍(上下左右)都沒有棋的地方,那就是氣。

那麼要實現什麼呢?就是每下一次棋,返回一方所有的塊和每一塊有多少氣。如果沒氣了,就把圍住的棋都取走(數組裡就是清為0)。


 

先來看看主函數

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#define maxsize 10

#define null 0

typedef struct node{

       int x;

       int y;

       struct node*next;

} lqnode;

typedef struct{

       node *front,*rear;

}Queue;

 //定義了兩個結構體,一個是隊列,一個是節點

int main(){
int chess[10][10];
int savechess[10][10];//設置了一個數組保存之前下個棋盤
int i,j,type=1,a,b,flag=0;
for(i=0;i<10;i++){
  for(j=0;j<10;j++){
    chess[i][j]=0;
  }
}

for(i=0;i<10;i++){
  for(j=0;j<10;j++){
    printf(" %d",chess[i][j]);
  }
  printf("\n");
}

printf("黑手:");

//執黑子先手
while(scanf("%d %d",&a,&b)!=EOF){

  //輸入一方要下的位置
  if(flag==0){
    type=1;//黑方是1
    flag=1;
  }else{
    type=2;//白方是2
    flag=0;
  }

//利用以上實現黑方白方切換
  chess[a][b]=type;//下棋

//保存之前的棋盤
 for(int i=0;i<10;i++){
    for(int j=0;j<10;j++){
      savechess[i][j]=chess[i][j];
    }
  }

  lumpgas(chess,type);

//把所有七七八八的放在一個函數里,傳入的參數現在的棋盤,以及現在是哪一方下棋,因為傳入的數組會在函數里發生改變,所以上面的savechess就是為了保存。


//賦值,更新現在的棋盤
  for(int i=0;i<10;i++){
    for(int j=0;j<10;j++){
      if(chess[i][j]==9 ||chess[i][j]==6 ||chess[i][j]==3){//為什麼是這個條件,下麵看lumpgas再解釋
       chess[i][j]=savechess[i][j];

      }
    }
  }
//輸出下過之後的棋盤
  for(i=0;i<10;i++){
    for(j=0;j<10;j++){
      printf(" %d",chess[i][j]);
     }
    printf("\n");
  }

//如果上面是黑棋,那下一個就是白棋下辣!
  if(type==1){
    printf("白手\n");
  }else{
    printf("黑手\n");
  }
}
return 0;

}


現在就來看看lumpgas函數里實現的功能

void lumpgas(int chess[10][10],int type){

       int total=0;//這個是用來標記的,下麵看看怎麼退出迴圈

       int twtype=type*3;//這也是用來標記下麵是否迴圈過

       while(total==0){//為什麼是迴圈呢,就是說每一方可能不止只有一個塊

       Queue *q;

       lqnode *p;

       q=(Queue *)malloc(sizeof(Queue));

       p=(lqnode *)malloc(sizeof(lqnode));

       p->next=null;

       q->rear=p;

       q->front=p;

       int x=0,y=0,flag=1;

 //下麵就用黑方為例來講解吧,先找到黑方的第一個占領的位置

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

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

                     if(chess[i][j]==type && flag==1){

                            x=i;

                            y=j;

                            flag=0;//因為是二維,所以用這個方法來記錄下標

                     }

              }

       

             

       }

      

      chess[x][y]=type*3;//用來記錄這個點已經找過了,以便於下一次迴圈找其他的塊

 

        lqnode *r,*t;

        r=(lqnode *)malloc(sizeof(lqnode));

        r->x=x;

        r->y=y;

        q->rear->next=r;

        r->next=null;

        q->rear=r;

 //進隊列

        

       t=q->front->next;

       x=t->x;

       y=t->y;

      

int num=0;    

 

while(num!=4){

         num=4;//這個是迴圈的條件,如果說這個節點上下左右都沒有可以進入隊列的節點了就退出

      //以下是廣度優先來找連在一起的點,找到就進隊列,上下左右都找

    if(chess[x-1][y]==type){

            

        r=(lqnode *)malloc(sizeof(lqnode));

        r->x=x;

        r->y=y+1;

        q->rear->next=r;

        r->next=null;

        q->rear=r;

        chess[x-1][y]=twtype;//標記一下這個地方已經找過了

        num--;

              }

             

             

                           

        if(chess[x+1][y]==type){

              r=(lqnode *)malloc(sizeof(lqnode));

        r->x=x+1;

        r->y=y;

        q->rear->next=r;

        r->next=null;

        q->rear=r;

        chess[x+1][y]=twtype;

        num--;

              }

             

        if(chess[x][y-1]==type){

             r=(lqnode *)malloc(sizeof(lqnode));

        r->x=x;

        r->y=y-1;

        q->rear->next=r;

        r->next=null;

        q->rear=r;

        chess[x][y-1]=twtype;

        num--;

              }

             

             

      

        if(chess[x][y+1]==type){

             r=(lqnode *)malloc(sizeof(lqnode));

        r->x=x;

        r->y=y+1;

        q->rear->next=r;

        r->next=null;

        q->rear=r;

        chess[x][y+1]=twtype;

        num--;

              }

       if(num==4){

              break;再判斷一遍,找不到就退出

       }

       t=t->next;

       x=t->x;

       y=t->y;

       printf("%d,%d\n",x,y);

}

 

t=q->front->next;//先記錄一下這個頭

       int count=0;

       printf("該塊有以下元素:\n");

    while(q->rear!=q->front){

             lqnode *s;

             s=q->front->next;

             x=s->x;

             y=s->y;

     //上下左右都找一遍,註意條件,有些在邊上,比如【0】【0】這個點x-1是找不到的

             if(chess[x+1][y]==0 && x+1>=0 && y>=0){

                     count++;

                            chess[x+1][y]=9;     //找過的標記一下,以防再找一遍                         

             }

                     if(chess[x][y+1]==0 && x>=0 && y+1>=0) {

                     count++;

                     chess[x][y+1]=9;

             }

                    if(chess[x][y-1]==0 && x>=0 && y-1>=0) {

                     count++;

                     chess[x][y-1]=9;

             }

                    if(chess[x-1][y]==0 && x-1>=0 && y>=0) {

                     count++;

                           chess[x-1][y]=9;

             }

            

             q->front->next=s->next;          

             printf("x=%d,y=%d\n",x,y);

            //出隊列嘍

             if(s->next==null){

                    q->rear=q->front;

             }

        }

 

printf("該塊有%d口氣\n",count);

 

if(count==0){//如果為0,就是被對方圍住啦,裡面所有的都要變為0,就是裡面的棋子都要被拿走

       while(t!=null){//這個就是上面那個t為什麼要被記錄下來的原因

              x=t->x;

              y=t->y;

              chess[x][y]=0;

              t=t->next;

       }

      

}

//以下就是再迴圈,找到沒有被記錄過並且還是黑放下的棋的點,

x=-1;

y=-1;

flag=1;

 

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

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

                     if(chess[i][j]==type && flag==1){//因為之前被找過的已經記錄過了

                            x=i;

                            y=j;

                            flag=0;

                     }

              }

}

       if(x==-1&&y==-1){

              total=1;//如果找不到就是退出迴圈辣

       }

       }

      

}

 最後再解釋一下

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

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

                     if(chess[i][j]==9 ||chess[i][j]==6 ||chess[i][j]==3)

                     {chess[i][j]=savechess[i][j];}

                    

              }

       }

      這一部分。

因為在lumpgas()函數里有記錄的痕跡,所以要把記錄的點都變成以前的,然後就是說一定要有記錄,因為當一方的棋被圍住了,所有被圍住的棋都是要清掉的,清掉這個功能也是在函數里實現的

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 一、開發環境 uni-app 官方文檔地址 原生開發者支持 1、Android Studio 下載地址:Android Studio官網 OR Android Studio中文社區 2、最新版的HBuilderX 3、App離線SDK下載 ...
  • 01、如何判斷⼀個變數是不是數組? let arr = [1,2,3,4] function fun(){ return arr instanceof Array } 02、如何使⽤class實現繼承? class fu {consructor(name,age)} class son extend ...
  • 01、<form>表單 <form> 表單是比較重要的HTML元素,塊元素,主要作用是向服務端提交數據。結合表單元素input使用,通過內部的button按鈕提交(type="submit")表單數據。 | 元素/屬性 | 描述 | 值/備註 | | | | | | <form> | 表單元素 | ...
  • 今天看到一篇文章中提到了一個好用的工具release-it。剛好可以用在我正在開發的vue3組件庫。紙上得來終覺淺,絕知此事要躬行,說乾就乾,下麵就介紹如何將release-it應用到實際項目中,讓組件庫可以自動化發佈、管理版本號、生成 changelog、tag等 項目調整 在使用這個工具之前先對 ...
  • 什麼是分散式鎖?對於這個問題,相信很多同學是既熟悉又陌生。隨著分散式系統的快速發展與廣泛應用,針對共用資源的互斥訪問也成為了很多業務必須要面對的需求,這個場景下人們通常會引入分散式鎖來解決問題。我們通常會使用怎麼樣的分佈鎖服務呢?有開源的 MySQL,Redis,ZooKeeper,Etcd 等三方... ...
  • 模板方法模式是一種行為設計模式,它在超類中定義了一個演算法的框架,允許子類在不修改結構的情況下重寫演算法的特定步驟。 ...
  • 您好,我是湘王,這是我的博客園,歡迎您來,歡迎您再來~ 為了提高CPU的利用率,工程師們創造了多線程。但是線程們說:要有光!(為了減少線程創建(T1啟動)和銷毀(T3切換)的時間),於是工程師們又接著創造了線程池ThreadPool。就這樣就可以了嗎?——不,工程師們並不滿足於此,他們不把自己創造出 ...
  • 之所以提這個坑,是因為,今天下午,通過監控系統,發現我們系統生產能力突然下降,頻繁報無法獲取資料庫連接。究其原因,竟然是因為mybatisplus的這個“坑”導致的。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...