文章目錄
- 1.前言
- 2.效果展示
- 3.地圖功能的構建
- 3.1地圖構建
- 3.2選擇功能的構建
- 3.3地圖的列印
- 4.回傳功能的實作
- 5.人物可以到達目標點的實作
- 6.箱子到達目的點后出來不會資料丟失
- 7.判斷函式
- 8.小人移動的實作
- 9.完整代碼
1.前言
前段時間寫了一個推箱子小游戲,只是實作了幾個基本的功能,這次在上次的基礎上添加了一些功能;
這次代碼的代碼量稍微大一點,可讀性沒有那么強,如果看起來比較難理解,可以先看一下上次我寫的比較簡單的推箱子博客鋪墊一下;較簡單推箱子博客鏈接: link.
2.效果展示
新添地圖選擇功能,回傳一步功能,人物可以進入目標點,修復箱子從目標點出來后目標點消失問題;

3.地圖功能的構建
3.1地圖構建
上次只有一個地圖,因此用一個二維陣列保存地圖就夠了,這次添加了地圖選擇功能,因此采用了三維陣列,這樣第一個下標就可以用來選擇地圖;


char map[2][10][10]={ //0位墻壁■,1位空白,2為箱子●,3為目的點¤,4為人♀,5為小人兒與目標點重合★,6為箱子進入了目標點☆
{
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 3, 1, 0, 0, 0, 1, 0, 0 },
{ 0, 0, 1, 1, 1, 1, 1, 3, 1, 0 },
{ 0, 1, 1, 1, 2, 1, 1, 1, 0, 0 },
{ 0, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
{ 0, 1, 2, 1, 0, 1, 2, 0, 0, 0 },
{ 0, 0, 0, 1, 1, 1, 1, 1, 0, 0 },
{ 0, 0, 0, 1, 1, 1, 1, 1, 3, 0 },
{ 0, 3, 1, 2, 1, 4, 1, 1, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
},//地圖1
{
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 3, 0, 0, 0, 0, 0, 1, 3, 0 },
{ 0, 3, 0, 1, 1, 1, 1, 3, 1, 0 },
{ 0, 1, 1, 1, 2, 1, 2, 1, 1, 0 },
{ 0, 1, 2, 1, 1, 1, 1, 0, 0, 0 },
{ 0, 1, 1, 2, 0, 1, 1, 0, 0, 0 },
{ 0, 1, 0, 1, 1, 1, 2, 1, 1, 0 },
{ 0, 3, 0, 2, 1, 0, 1, 1, 0, 0 },
{ 0, 3, 1, 1, 1, 4, 1, 1, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
},
};
3.2選擇功能的構建
我們依然可以將三維陣列的資料讀入到二維陣列之中完成地圖的選擇,同時每個地圖小人的起始位置都是一樣的,即可以直接設定,三維陣列的第一個下標就可以當做選擇地圖的標號;選定好地圖之后呼叫函式將三維陣列的資料拷貝至二維陣列內
char arr[ROW][LINE];
int select = 0;
int quit = 0;
while (!quit)
{
printf("請選擇你的關卡\n");
printf("###########################\n");
printf("1.第一關##########2.第二關###\n");
printf("###########################\n");
scanf("%d", &select);
switch (select)
{
case 1:
select = 0;//陣列下標從0開始
SlectMap(arr, map, select);
quit = 1;
break;
case 2:
select = 1;
SlectMap(arr, map, select);
quit = 1;
break;
default :
printf("輸入有誤,請從新輸入\n");
}
}
void SlectMap(char arr[][LINE], char map[][ROW][LINE],int select)//選擇地圖進行資料拷貝
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < LINE; j++)
{
arr[i][j] = map[select][i][j];
}
}
}
3.3地圖的列印
地圖列印直接構建一個回圈函式即可
void ShowMap(char arr[][LINE])//列印地圖
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < LINE; j++)
{
if (arr[i][j] == 0)
printf("■");//列印墻壁
else if (arr[i][j] == 1)//列印空白
printf(" ");
else if (arr[i][j] == 2)//列印箱子
printf("●");
else if (arr[i][j] == 3)//列印目的點
printf("¤");
else if (arr[i][j] == 4)//列印人物
printf("♀");
else if (arr[i][j] == 5)//列印人物和目標點重疊后的圖案
printf("★");
else if (arr[i][j] == 6)//箱子進入目標點后的圖案
printf("☆");
}
printf("\n");
}
}
4.回傳功能的實作
按照順序應該是先實作移動功能的,由于代碼量的增加,不先提回傳功能代碼的可讀性沒有那么好;當然我還是建議先看一下我先前的那篇只有基本功能的博客,比較清晰易懂;
回傳功能說白了就是保存上一步的資料,那么我們可以構建一個函式進行保存,即在移動后資料更新之前完成資料的存盤,在下次移動之前進行判斷是否需要退一步,這樣就完成了回傳的功能;需要注意的是我們不僅僅需要保存地圖的資料還需要保存小人的位置,因為我們按了回傳鍵呈現出來的地圖實際上是上一次展現的地圖,如果不將小人兒的位置重新回歸,那么實際上是對不上號的;
這里完成的是資料的存盤
void Retain(char retarr[][LINE],char arr[][LINE])//保存舊地圖
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < LINE; j++)
{
retarr[i][j] = arr[i][j];
}
}
}
void Save(char retarr[][LINE], char arr[][LINE], int *row, int *line, int *retrow, int *retline)//更新前內容保存
{
Retain(retarr, arr);//內容新前將其保存一份;
//小人坐標更新前保存一份
*retrow = *row;
*retline = *line;
}
完成了資料的存盤,當我們需要后退一步怎么辦呢,我們讀取到的資料為r時就將存盤的內容列印出來,結束這一次回圈;
if (move == 'r')//回傳
{
system("cls");
ShowMap(retarr);//列印舊地圖
Retain(arr, retarr);//地圖內容更換為上一步的內容
//將小人坐標替換為上一步的小人坐標
*row = *retrow;
*line = *retline;
break;
}
5.人物可以到達目標點的實作
剛開始我的代碼之中是禁止人物到達目標點的,在這里做出了修改,增加了人物可以進出目標點;
增加這個功能首先要進行考慮的是人物從目標點出來之后,目標點怎么恢復原樣,我將人物和目標點重疊設計為了另外一種圖案,那么當人物進行移動位置時,判斷人物的當前坐標的內容是否為重疊圖案,如果是移動后就替換成目標點,否則替換為空白,因為人物只可能處于空白處和目標點處,不可能處于墻壁和箱子之中;
下面這段代碼的后半部分可以封裝成函式,因為在其它的情況下也需要判定小人是不是從目標點出來,但是我為了代碼的可讀性就沒有將其封裝起來;
else if (arr[newrow][newline] == 3)//為目標點
{
arr[newrow][newline]=5;//小人兒和目標點重合的影像
if (arr[*row][*line] == 5)//此時小人與目標重合,
{
arr[*row][*line] = 3;//那么出來后就變成目標點了;
}
else//小人兒沒有在目標點中
{
arr[*row][*line] = 1;//小人的地方變為空白
}
//坐標更新
*row = newrow;
*line = newline;
6.箱子到達目的點后出來不會資料丟失
先前我們只進行了判定箱子是否可以移動到下一步,因此當箱子進入目標點再出來的時候,目標點的資料就丟失了;
這里同樣可以借用人物到達目標點的方法進行實作,我們將箱子和目標點設計為一種圖案,當人推箱子的時候,下一步小人兒肯定在箱子的位置,因此下一步小人兒的位置就變成了小人和目標點的結合圖案,而箱子下一步的情況要進行判定,箱子下一步的情況有可能是目標點有可能是空白;
else //箱子前面不是墻壁
{
if (arr[nextrow][nextline] == 3)//箱子前面是目標點
{
arr[nextrow][nextline] = 6;//箱子前挪,圖案變成箱子和目標點重合的圖案
}
else//箱子前面是空白
{
arr[nextrow][nextline] = 2;//空白處變成箱子
}
if (arr[newrow][newline] == 6)//原箱子位置是目標點
{
arr[newrow][newline] = 5;//變成目標點和小人兒的結合
}
else
{
arr[newrow][newline] = 4;//箱子位置變為人
}
if (arr[*row][*line] == 5)//此時小人與目標點重合,
{
arr[*row][*line] = 3;//那么出來后就變成目標點了;
}
else
{
arr[*row][*line] = 1;//小人的地方變為空白
}
//坐標更新
*row = newrow;
*line = newline;
}
7.判斷函式
我們可以通過統計目標點的當前剩余個數來實作這個功能,需要注意的是,小人進入目標點后目標點的個數也是減少的,因此還需要加上一個小人兒和目標點的重疊圖案個數;
void Judge(char arr[][LINE],int *boxs)
{
int temp = 0;
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < LINE; j++)
{
if (arr[i][j] == 3||arr[i][j]==5)//剩余目標點數以及人物進入了目標點
temp++;
}
}
*boxs = temp;
}
8.小人移動的實作

9.完整代碼
#include "game.h"
void ShowMap(char arr[][LINE])//列印地圖
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < LINE; j++)
{
if (arr[i][j] == 0)
printf("■");//列印墻壁
else if (arr[i][j] == 1)//列印空白
printf(" ");
else if (arr[i][j] == 2)//列印箱子
printf("●");
else if (arr[i][j] == 3)//列印目的點
printf("¤");
else if (arr[i][j] == 4)//列印人物
printf("♀");
else if (arr[i][j] == 5)//列印人物和目標點重疊后的圖案
printf("★");
else if (arr[i][j] == 6)//箱子進入目標點后的圖案
printf("☆");
}
printf("\n");
}
}
void Move(char arr[][LINE], int *row, int *line, char retarr[][LINE],int *retrow, int *retline)//移動小人兒
{
while (1)
{
int newrow = *row;
int newline = *line;
int quit = 0;
printf("請通過w,s,a,d,控制上下左右,輸入r回傳\n");
int move=0;
int c = 0;
while (!quit)
{
move = getchar();//從標準輸入讀取字符
while((c=getchar())!='\n');//吃掉多余的字符以及空格
switch (move)
{
case 'w':
newrow--;//向上移動
quit = 1;
break;
case 's':
newrow++;//向下移動
quit = 1;
break;
case 'a':
newline--;//向左移動
quit = 1;
break;
case 'd':
newline++;//向右移動
quit = 1;
break;
case 'r':
quit = 1;
break;
default:
printf("輸入有誤,請從新輸入\n");
break;
}
}
if (move == 'r')//回傳
{
system("cls");
ShowMap(retarr);//列印舊地圖
Retain(arr, retarr);//地圖內容更換為上一步的內容
//將小人坐標替換為上一步的小人坐標
*row = *retrow;
*line = *retline;
break;
}
Save(retarr, arr, row, line, retrow, retline);//此時已經不需要回傳,坐標更新前保存一份
if (arr[newrow][newline] == 0 )//下一個坐標為墻壁
{
printf("禁止前行\n");
break;
}
else//前面為空白,箱子,或者目標點,或者箱子到目標點后的結合圖案(也是箱子)
{
if (arr[newrow][newline] == 1)//為空白
{
arr[newrow][newline]= 4;//將小人移動到坐標點
if (arr[*row][*line] == 5)//此時小人與目標重合,
{
arr[*row][*line] = 3;//那么出來后就變成目標點了;
}
else
{
arr[*row][*line] = 1;//小人的地方變為空白
}
//坐標更新
*row = newrow;
*line = newline;
}
else if (arr[newrow][newline] == 3)//為目標點
{
arr[newrow][newline]=5;//小人兒和目標點重合的影像
if (arr[*row][*line] == 5)//此時小人與目標重合,
{
arr[*row][*line] = 3;//那么出來后就變成目標點了;
}
else
{
arr[*row][*line] = 1;//小人的地方變為空白
}
//坐標更新
*row = newrow;
*line = newline;
}
else if (arr[newrow][newline] == 2||arr[newrow][newline]==6)//下一個點為箱子或者箱子和目標點的結合圖案
{
int nextrow = newrow;
int nextline = newline;
if (move == 'w')//上
nextrow = newrow - 1;
else if (move == 's')//下
nextrow = newrow + 1;
else if (move == 'a')//左
nextline = newline - 1;
else//右
nextline = newline + 1;
if (arr[nextrow][nextline] == 0 || arr[nextrow][nextline] == 2||arr[nextrow][nextline]==6)
//箱子前面是墻壁或者箱子或者箱子和目標點的結合
{
printf("移動不了,箱子前方有障礙\n");
break;
}
else //箱子前面不是墻壁
{
if (arr[nextrow][nextline] == 3)//箱子前面是目標點
{
arr[nextrow][nextline] = 6;//箱子前挪,圖案變成箱子和目標點重合的圖案
}
else//箱子前面是空白
{
arr[nextrow][nextline] = 2;//空白處變成箱子
}
if (arr[newrow][newline] == 6)//原箱子位置是目標點
{
arr[newrow][newline] = 5;//變成目標點和小人兒的結合
}
else
{
arr[newrow][newline] = 4;//箱子位置變為人
}
if (arr[*row][*line] == 5)//此時小人與目標點重合,
{
arr[*row][*line] = 3;//那么出來后就變成目標點了;
}
else
{
arr[*row][*line] = 1;//小人的地方變為空白
}
//坐標更新
*row = newrow;
*line = newline;
}
}
}
//進行移動之后的地圖列印;
system("cls");
ShowMap(arr);
break;
}
}
void Judge(char arr[][LINE],int *boxs)
{
int temp = 0;
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < LINE; j++)
{
if (arr[i][j] == 3||arr[i][j]==5)//剩余目標點數以及人物進入了目標點
temp++;
}
}
*boxs = temp;
}
void Retain(char retarr[][LINE],char arr[][LINE])//保存舊地圖
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < LINE; j++)
{
retarr[i][j] = arr[i][j];
}
}
}
void Save(char retarr[][LINE], char arr[][LINE], int *row, int *line, int *retrow, int *retline)//更新前內容保存
{
Retain(retarr, arr);//內容新前將其保存一份;
//小人坐標更新前保存一份
*retrow = *row;
*retline = *line;
}
void SlectMap(char arr[][LINE], char map[][ROW][LINE],int select)//選擇地圖
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < LINE; j++)
{
arr[i][j] = map[select][i][j];
}
}
}
char map[2][10][10]={ //0位墻壁■,1位空白,2為箱子●,3為目的點¤,4為人♀,5為小人兒與目標點重合★,6為箱子進入了目標點☆
{
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 3, 1, 0, 0, 0, 1, 0, 0 },
{ 0, 0, 1, 1, 1, 1, 1, 3, 1, 0 },
{ 0, 1, 1, 1, 2, 1, 1, 1, 0, 0 },
{ 0, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
{ 0, 1, 2, 1, 0, 1, 2, 0, 0, 0 },
{ 0, 0, 0, 1, 1, 1, 1, 1, 0, 0 },
{ 0, 0, 0, 1, 1, 1, 1, 1, 3, 0 },
{ 0, 3, 1, 2, 1, 4, 1, 1, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
},//地圖1
{
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 3, 0, 0, 0, 0, 0, 1, 3, 0 },
{ 0, 3, 0, 1, 1, 1, 1, 3, 1, 0 },
{ 0, 1, 1, 1, 2, 1, 2, 1, 1, 0 },
{ 0, 1, 2, 1, 1, 1, 1, 0, 0, 0 },
{ 0, 1, 1, 2, 0, 1, 1, 0, 0, 0 },
{ 0, 1, 0, 1, 1, 1, 2, 1, 1, 0 },
{ 0, 3, 0, 2, 1, 0, 1, 1, 0, 0 },
{ 0, 3, 1, 1, 1, 4, 1, 1, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
},
};
void Game()
{
char arr[ROW][LINE];
int select = 0;
int quit = 0;
while (!quit)
{
printf("請選擇你的關卡\n");
printf("###########################\n");
printf("1.第一關##########2.第二關###\n");
printf("###########################\n");
scanf("%d", &select);
switch (select)
{
case 1:
select = 0;//陣列下標從0開始
SlectMap(arr, map, select);
quit = 1;
break;
case 2:
select = 1;
SlectMap(arr, map, select);
quit = 1;
break;
default :
printf("輸入有誤,請從新輸入\n");
}
}
ShowMap(arr);
int row = 8, line = 5;//小人初始橫縱坐標
int boxs= 4;//還未到達目標點的盒子數
char retarr[ROW][LINE];
Retain(retarr, arr);//先保存一份,直接按回傳不會出錯
int retrow=row, retline=line;//舊的小人地址
while (boxs)
{
Move(arr, &row, &line,retarr,&retrow,&retline);//移動小人
Judge(arr, &boxs);//剩余目標點數
if (boxs == 0)
printf("恭喜你,通關成功\n");
}
}
#ifndef _GAME_H_
#define _GAME_H_
#include <stdio.h>
#include <windows.h>
#pragma warning (disable :4996)
#define ROW 10
#define LINE 10
void SlectMap(char arr[][LINE], char[][ROW][LINE],int select);
void Game();
void Retain(char retarr[][LINE], char arr[][LINE]);
void Save(char retarr[][LINE], char arr[][LINE], int *row, int *line, int *retrow, int *retline);
#endif
#include "game.h"
int main()
{
Game();
system("pause");
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/237537.html
標籤:其他
上一篇:原生JS實作貪吃蛇游戲
