c语言拼图游戏-PicturePuzzle

vtor3478@qq.com,2023年6月22日

https://www.cnblogs.com/vtor3478/articles/17498545.html

 

​开发环境:使用vs2019,配合easyx图形库

 

 

 

 

基本设计:

注意,需要自行(寻找并)添加图片,在例子中,使用原神角色 甘雨进行游戏。

struct Block结构体:每个方块,都有坐标,以及对应的图片, 所以起码需要col,row,imgIdx。

init函数:然后使用easyx,初始化图片对象,,加载图片等。

paint函数:使用col得到y坐标,使用row得到x坐标,使用imgIdx得到确定图片,直接进行绘制图片,在程序中,增加了线,用于区分每个block。

userInput函数:使用easyx图形库,确定点击的坐标(x,y),

        左击时,,,根据y得到col,根据x得到row,判断四个方向是否有空缺(注意防止越界),如果有空缺,交换两者的imgIdx,从而完成图片交换。

        当完成游戏时,右击可重新开始游戏。

checkWin函数:检查block的imgidx是否有序即可。

 

拓展功能:

为了保证能完成拼图,打乱时,需要保证逆序数是偶数,两个循环比较一下即可。

 

以下是完整代码:

  1 #include <stdio.h>
  2 #include <time.h>
  3 #include <easyx.h>
  4 
  5 
  6 #define GAME_LEVEL    3
  7 
  8 #define WINDOW_WIDTH    800
  9 #define WINDOW_HEIGHT    800
 10 
 11 
 12 #define    X_OFFSET    0
 13 #define Y_OFFSET    0
 14 #define BLOCK_SIZE    (WINDOW_HEIGHT / GAME_LEVEL)
 15 
 16 #define GetXByCol(col)    (col * BLOCK_SIZE + X_OFFSET)
 17 #define GetYByRow(row)    (row * BLOCK_SIZE + Y_OFFSET)
 18 
 19 #define GetColByX(x)    ((x - X_OFFSET) / BLOCK_SIZE)
 20 #define GetRowByY(y)    ((y - Y_OFFSET) / BLOCK_SIZE)
 21 
 22 struct Block
 23 {
 24     int col, row;
 25     int imgIdx;
 26 };
 27 
 28 int colNum = GAME_LEVEL;
 29 int rowNum = GAME_LEVEL;
 30 
 31 int moveFlag = 0;
 32 
 33 
 34 struct Block blocks[GAME_LEVEL][GAME_LEVEL] = {0};
 35 
 36 const char* imgFileString = { "res//ganyu-1280.png" };
 37 //const char* imgFileString = { "res//unable.png" };
 38 IMAGE wholeImg;
 39 // https://wiki.biligame.com/ys/%E7%94%98%E9%9B%A8#/media/%E6%96%87%E4%BB%B6:%E7%94%98%E9%9B%A8%E7%AB%8B%E7%BB%98.png
 40 IMAGE img[GAME_LEVEL * GAME_LEVEL] = { 0 };
 41 
 42 
 43 int getReverseOrder()
 44 {
 45     int reverseOrderCnt = 0;
 46     for (int preOrder = 0; preOrder < colNum * rowNum - 1; preOrder++) {
 47         for (int nextOrder = preOrder + 1; nextOrder < colNum * rowNum; nextOrder++) {
 48             if (blocks[preOrder % colNum][preOrder / colNum].imgIdx != colNum * rowNum - 1
 49                 && blocks[nextOrder % colNum][nextOrder / colNum].imgIdx != colNum * rowNum - 1) {
 50                 if (blocks[preOrder % colNum][preOrder / colNum].imgIdx
 51                     > blocks[nextOrder % colNum][nextOrder / colNum].imgIdx)
 52                 {
 53                     reverseOrderCnt++;
 54                 }
 55             }
 56         }
 57     }
 58     return reverseOrderCnt;
 59 }
 60 
 61 bool checkWin()
 62 {
 63     bool winFlag = true;
 64     for (int imgIdx = 0; imgIdx < colNum * rowNum - 1; imgIdx++) {
 65         if (blocks[imgIdx % colNum][imgIdx / colNum].imgIdx != imgIdx) {
 66             winFlag = false;
 67             break;
 68         }
 69     }
 70     return winFlag;
 71 }
 72 
 73 
 74 void start()
 75 {
 76     int swapCnt = 3;
 77     while (1)
 78     {
 79         if ((swapCnt < 0) && (getReverseOrder() % 2 == 0))
 80         {
 81             break;
 82         }
 83         int swapIdx1 = rand() % (colNum * rowNum - 1);
 84         int swapIdx2 = rand() % (colNum * rowNum - 1);
 85         int tempImgIdx = blocks[swapIdx1 / colNum][swapIdx1 % colNum].imgIdx;
 86         blocks[swapIdx1 / colNum][swapIdx1 % colNum].imgIdx = blocks[swapIdx2 / colNum][swapIdx2 % colNum].imgIdx;
 87         blocks[swapIdx2 / colNum][swapIdx2 % colNum].imgIdx = tempImgIdx;
 88         swapCnt--;
 89     }
 90 
 91 }
 92 
 93 
 94 void init()
 95 {
 96     srand(time(NULL));
 97     initgraph(WINDOW_WIDTH, WINDOW_HEIGHT, EW_SHOWCONSOLE);
 98     // 加载到画面中,为下一步做准备
 99     loadimage(&wholeImg, imgFileString, WINDOW_WIDTH, WINDOW_WIDTH);
100     putimage(0, 0, &wholeImg);
101 
102 
103     for (int row = 0; row < rowNum; row++) {
104         for (int col = 0; col < colNum; col++) {
105             blocks[col][row].col = col;
106             blocks[col][row].row = row;
107             // 先有序,然后进行打乱
108             blocks[col][row].imgIdx = row * rowNum + col;
109 
110             if (row * colNum + col < colNum * rowNum - 1)
111             {
112                 getimage(&img[blocks[col][row].imgIdx],
113                     GetXByCol(col),
114                     GetYByRow(row),
115                     BLOCK_SIZE,
116                     BLOCK_SIZE);
117             }
118         }
119     }
120     // 针对最后一张图片额外处理
121     //loadimage(&img[colNum * rowNum - 1], imgFileString, BLOCK_SIZE, BLOCK_SIZE);
122     cleardevice();
123 }
124 
125 
126 void userInput()
127 {
128     MOUSEMSG msg;
129     if (PeekMouseMsg(&msg)) {
130         if (WM_LBUTTONDOWN == msg.uMsg) {
131             int clickCol, clickRow;
132             clickCol = GetColByX(msg.x);
133             clickRow = GetRowByY(msg.y);
134             printf("lbutton  %d %d\r\n", clickCol, clickRow);
135             for (int around = -3; around <= 3; around +=2)
136             {
137                 int aroundCol = clickCol + (around % 3);
138                 int aroundRow = clickRow + (around / 3);
139 
140                 printf("around %d %d\r\n", aroundCol, aroundRow);
141                 // 需要判断有效,防止越界访问
142                 if (0 <= aroundRow && aroundRow < rowNum
143                     && 0 <= aroundCol && aroundCol < colNum) {
144                     // 如果有一个方向是空块,那么将进行坐标置换
145                     if (blocks[aroundCol][aroundRow].imgIdx == rowNum * colNum - 1) {
146                         int tempImgIdx = blocks[clickCol][clickRow].imgIdx;
147                         blocks[clickCol][clickRow].imgIdx = blocks[aroundCol][aroundRow].imgIdx;
148                         blocks[aroundCol][aroundRow].imgIdx = tempImgIdx;
149                         break;
150                     }
151                 }
152             }
153         }
154         else if (WM_RBUTTONDOWN == msg.uMsg) {
155             // 游戏结束,右击,重新开始
156             if (checkWin())
157             {
158                 start();
159             }
160             for (int row = 0; row < rowNum; row++) {
161                 printf("     ");
162                 for (int col = 0; col < colNum; col++) {
163 
164                     printf("%d %d %d\t\t",
165                         blocks[col][row].col,
166                         blocks[col][row].row,
167                         blocks[col][row].imgIdx);
168                 }
169                 printf("\r\n");
170             }
171             printf("getReverseOrder = %d\r\n\r\n", getReverseOrder());
172         }
173 
174     }
175 }
176 
177 void paint()
178 {
179     BeginBatchDraw();
180     cleardevice();
181     for (int row = 0; row < rowNum; row++) {
182         for (int col = 0; col < colNum; col++) {
183             putimage(
184                 GetXByCol(blocks[col][row].col),
185                 GetYByRow(blocks[col][row].row),
186                 &img[blocks[col][row].imgIdx]);
187         }
188     }
189 
190     setlinestyle(0, 3);
191     setlinecolor(RGB(0, 0, 255));
192     for (int row = 1; row < rowNum; row++) {
193         line(0, row * BLOCK_SIZE, (colNum + 1) * BLOCK_SIZE, row * BLOCK_SIZE);
194     }
195     for (int col = 1; col < colNum; col++) {
196         line(col * BLOCK_SIZE, 0, col * BLOCK_SIZE, (rowNum + 1) * BLOCK_SIZE);
197     }
198     EndBatchDraw();
199 }
200 
201 
202 int main(void)
203 {
204     init();
205     start();
206     while (1) {
207         // 当逆序为0时,说明游戏成功
208         if (checkWin()) {
209             BeginBatchDraw();
210             putimage(0, 0, &wholeImg);
211             EndBatchDraw();
212         } else {
213             paint();
214         }
215         userInput();
216     }
217     system("pause");
218     return 0;
219 }

 

Posted on 2023-06-22 23:06  污钞vtor  阅读(69)  评论(0编辑  收藏  举报