專題-連連看-丙-丁-算法(一)-矩陣梳理(一)

本文介绍了一种基于连连看规则的算法实现过程。通过构建棋盘矩阵M,并使用C语言进行编程实现,文章详细讲解了如何扫描矩阵以寻找可消除元素,并将其存储为链表结构。此外,还介绍了如何构建和利用中间体矩阵来处理复杂的游戏逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

丙-算法(一)

前文我們得到了棋盤矩陣M,M中同種元素的消元遵循連連看的原則:相鄰或者連綫彎折小於等於兩処。我們可以從矩陣的第一列第一行的那個元素分析起,如果不等于0就考慮消元。

對於消元,其過程稍顯複雜。我們需要做以下判別工作:

一、元素非0;

二、四周非全遮擋(封閉);

三、存在非己同類元素;

四、非己同類元素四周非全遮擋(封閉);

五、連綫彎折処不大于2。

五個條件同時滿足及消元。

把矩陣M再寫一遍:

           1     2     3     0     1

   M = [ 0     0     0     0     0 ]

             0     1     0     3     1

             0     2     1     2     0

這個東西用C語言的二位數組來描述。聲明一個二位數組Array[行數][列數],即Array[4][5],行數就是縱坐標,用y表示,列數是橫坐標,用x表示。

遍歷數組Array,如果Array[y][x]不等于0(滿足條件一)就進入下一步。

 

for (y  =   0 ; y  <=   3 ; y ++ ) {
  
for(x = 0; x <= 4; x++){
    
if(Array[y][x] != 0){
          //元素不等于0的處理代碼
        }

      }

    }  

注意0~3是4行,0~4是5列。

 對於這樣一個複雜的問題我們需要對原始矩陣的每個元素掃描一道,得到它的相關訊息並將其存入一個重新構造的矩陣(二維數組)中,這些相關訊息包括:

1、牌面值(索引,無牌為“0”);

2、橫坐標;

3、縱坐標;

4、邊界狀況;

5、下一張同類牌指針。

於是定義結構card(中間體矩陣元素)

// 中間體矩陣元素
struct  card {
    
int posx;
    
int posy;
    
char index;
    
char directions;
    
struct card * next;
}
;
typedef 
struct  card CARD;

再聲明一個指針數組pCardArray:

CARD  *  pCardArray[ 4 ][ 5 ];

 其每個元素指向CARD結構。

 

我們再來梳理一下思路:

先對原始矩陣掃描一遍,得到非“0”每個元素的相關訊息,將其存入另一個“中間體矩陣”pCardArray中,當然這是一個指針矩陣。如果發現相同的牌(索引值相同)便將其掛至上一個相同元素的next指針上去,這便形成了一個相同元素比如1(紅球)元素的鏈表。對於每個員素之鏈表頭必須予以記錄,於是再聲明:

TYPE IndexArray[TYPENUM]  =   0} ;

 TYPE類型來源於聲明:

struct  type {
    
// 在矩陣中的列坐標
    int posx;
    
    
// 在矩陣中的行坐標
    int posy;
    
    
//狀態,0-已消元,1-仍存在
    char status;
}
;
typedef 
struct  type TYPE;

IndexArray數組0號元素置空,從1號元素起分別與牌的Index值相對應,比如IndexArray[1]元素存放的是中間體矩陣中index == 1 的元素組成的鏈表的表頭,IndexArray[2]元素存放的是中間體矩陣中index == 2 的元素組成的鏈表的表頭,以此類推。如果 IndexArray[n].status == 0 則表示牌面為n的牌已經全部消除了,如果 == 1即表示這種牌仍存在。 

以下是對原始矩陣處理的源程序,它了掃描原始矩陣Array由此生成中間體矩陣pCardArray及鏈表頭數組IndexArray並填充之。中間體矩陣中的directions相暫未填充,這個項目係標識牌四周相鄰位遮擋的情況,留作下一篇再講。

 矩陣梳理(一)

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

// 牌的種類
#define  TYPENUM 3

// 矩陣有5列
#define  XMAX 5

// 矩陣有4行
#define  YMAX 4

// 中間體矩陣元素
struct  card {
    
int posx;
    
int posy;
    
char index;
        char directions; 
    
struct card * next;
}
;
typedef 
struct  card CARD;

// 牌類別狀態、起始點數組元素
struct  type {
    
int posx;
    
int posy;
    
char status;
}
;
typedef 
struct  type TYPE;

int  main( void ) {
    printf(
"開始... ");

    
char x, y, m, n, i, j, k, forM = 0;
    
char Array[4][5= {{12301},
                        
{0},
                        
{21031},
                        
{00120}}
;

    
//中間體指針矩陣
    CARD * pCardArray[4][5];

    
//類別狀態數組
    
//0:未完成,1:完成
    TYPE IndexArray[TYPENUM] = {0};

    printf(
"原始矩陣: ");
    
for(y = 0; y <= (YMAX - 1); y++){
        
for(x = 0; x <= (XMAX -1); x++){
            printf(
"%d  ", Array[y][x]);
        }

        printf(
" ");
    }


    printf(
" 開始分析... ");
    
for(y = 0; y <= (YMAX - 1); y++){
        
for(x = 0; x <= (XMAX -1); x++){
            pCardArray[y][x] 
= (CARD *)malloc(sizeof(CARD));
            pCardArray[y][x] 
-> index = Array[y][x];
        }

    }


    printf(
"中間體矩陣: ");
    
for(y = 0; y <= (YMAX -1); y++){
        
for(x = 0; x <= (XMAX -1); x++){
            printf(
"%d  ", pCardArray[y][x] -> index);
        }

        printf(
" ");
    }


    printf(
" 開始查找... ");

    
//完整矩陣遍歷
    for(y = 0; y <= (YMAX -1); y++){
        
for(x = 0; x <= (XMAX -1); x++){

            
//牌種類依次分析
            for(k = 1; k <= TYPENUM; k++){

                
//如果此牌是當前要處理的排類別
                if(pCardArray[y][x] -> index == k){

                    
//如果此類牌未被處理過,則處理
                    if(IndexArray[k - 1].status == 0){

                        
//i,j係存放前一個元素坐標之變量
                        
//此時為某一類元素之第一個元素
                        pCardArray[y][x] -> posx = x;
                        pCardArray[y][x] 
-> posy = y;
                        
                        IndexArray[k 
- 1].posx = x;
                        IndexArray[k 
- 1].posy = y;
                        
                        i 
= x;
                        j 
= y;
                
                        
//設置查找起始點
                        
//如果還沒到最後一列
                        if(x < (XMAX - 1)){
                            m 
= x + 1;
                            n 
= y;
                        }

                        
//如果已處於最後一列,則進入下一行並從第一列開始
                        if(x == (XMAX -1)){
                            m 
= 0;
                            n 
= y + 1;
                        }

                        
//開始往後查找
                        for(n = n; n <= (YMAX - 1); n++){
                            
if(forM == 1){
                                m 
= 0;
                            }
//if閉合
                            
//從那個元素的後一個元素開始
                            for(m = m; m <= (XMAX - 1); m++){
                                forM 
= 1;
                                
//printf("[%d][%d] ", m, n);
                                
//如果發現下一個元素之index值與之相同
                                
//便追加至鏈表中
                                
//即修改當前元素之next
                                if(pCardArray[n][m] -> index == k){
                                    pCardArray[j][i] 
-> next = pCardArray[n][m];
                                    pCardArray[n][m] 
-> next = NULL;
                                    i 
= m;
                                    j 
= n;
                                    printf(
"Array[%d][%d] == %d ", m, n, k);
                                }
//if(pCardArray[n][m] -> index == k)閉合

                                
if(m == XMAX - 1 && n== YMAX - 1){
                                    IndexArray[k 
- 1].status = 1;
                                    
//printf("Status ");
                                }
//if(m&&n)閉合
                            
                            }
//for(m)閉合
                        }
//for(n)閉合

                    }
//if(IndexArray[k - 1] = 0)閉合
                }
//if(index == k)閉合
            }
//for(k)閉合

        }
//for(x)閉合
    }
//for(y)閉合
    printf("查找完畢! ");

    printf(
"相同牌: ");
    
    
/*for(k = 0; k <= TYPENUM; k++){
        while(pCurrent != NULL){
        }
    }
*/

    printf(
"pCardArray[][] = %p ", pCardArray[0][1-> next);
    printf(
"pCardArray[][] = %p "&pCardArray[2][0]);

    
for(k = 0; k <= TYPENUM - 1; k++){
        printf(
"索引%d:%d[][] ", k, IndexArray[k].status);
        printf(
"IndexArray[%d].posx = %d, posy = %d ", k,
            IndexArray[k].posx, IndexArray[k].posy);
    }

    printf(
"完成! ");
    
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值