小時候都玩過的推箱子,原來也可以用C語言來實現
想要完成推箱子,首先我們應該明白它的原理,或者說是對於這個遊戲有着一定的理解,這也是我從五子棋之後所學習到的一種全新的理念,想要編寫出一個東西就應該先了解它的具體內容,就像我們單片機老師所說道的程序的編寫,首先應該給自己畫一個流程圖,這樣才能夠根據流程圖將我們所需要的東西進行翻譯出來,具體化。
- 頭文件及具體宏定義
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <string.h>
#define MAX_ROW 8//定義地圖的行爲8
#define MAX_COL 8//定義地圖的列爲8
int Boxs;//統計其中所剩未完成箱子的個數
int x, y;//用此座標來定位小人的位置
int map[MAX_ROW][MAX_COL] = {//其實這說是地圖,也算是一個關卡 我自己做了三個關卡,大家也可以根據自己的需求來做
{ 0, 0, 1, 1, 1, 0, 0, 0 },
{ 0, 0, 1, 4, 1, 0, 0, 0 },
{ 0, 0, 1, 0, 1, 1, 1, 1 },
{ 1, 1, 1, 3, 0, 3, 4, 1 },
{ 1, 4, 0, 3, 2, 1, 1, 1 },
{ 1, 1, 1, 1, 3, 1, 0, 0 },
{ 0, 0, 0, 1, 4, 1, 0, 0 },
{ 0, 0, 0, 1, 1, 1, 0, 0 }
};
/**
* 0 表示空
* 1 表示牆
* 2 表示人
* 3 表示箱子
* 4 表示目的地(球)
* 5 表示已完成的箱子
*/
-
具體流程和主函數
- 打印菜單
- 選擇遊戲關卡
- 玩家開始移動
- 判斷遊戲是否成功
有了五子棋的經驗,我將主函數儘可能地寫的簡潔一些
int main(){
int i = 0;
int choice = 0;
MenuUi(1); //選擇界面
{
choice = ChoiceStart(i);
if (choice == 1){
Game();
}
}
system("pause");
return 0;
}
- 接下來就是每個函數的解析和具體的函數了
**菜單函數** 是一個小項目的主界面也是大家控制檯最開始顯示的所以對於這個界面一般還是設計的好一些
void MenuUi(){
printf("\t╔══════════════════════════════════════════════════════════════╗\n");
printf("\t║ ║\n");
printf("\t║ 歡迎使用推箱子游戲程序 祝您玩的愉快挑戰無極限 ║\n");
printf("\t║ ║\n");
printf("\t║ ._______________________. ║\n");
printf("\t║ | _____________________ | ║\n");
printf("\t║ | I I | ║\n");
printf("\t║ | I I | ║\n");
printf("\t║ | I 推 箱 子 I | ║\n");
printf("\t║ | I I | ║\n");
printf("\t║ | I___________________I | ║\n");
printf("\t║ !_______________________! ║\n");
printf("\t║ ._[__________]_. ║\n");
printf("\t║ .___|_______________|___. ║\n");
printf("\t║ |::: ____ | ║\n");
printf("\t║ | ~~~~ [CD-ROM] | ║\n");
printf("\t║ !_____________________! ║\n");
printf("\t║ ║\n");
printf("\t║ ║\n");
printf("\t║ 誰 怕 ? 一 蓑 煙 雨 任 平 生。 ║\n");
printf("\t║ ║\n");
printf("\t║ ║\n");
printf("\t║ 1.開始遊戲 0.離開遊戲 ║\n");
printf("\t║ ║\n");
printf("\t╚══════════════════════════════════════════════════════════════╝\n");
}
**選擇函數**
int ChoiceStart(int i){
printf("請輸入您的選擇:");
while (1){
scanf("%d", &i);
if (i == 1){
system("cls");/*清屏*/
return 1;
}
if (i == 0){
system("cls");/*清屏*/
printf("歡迎您的下次挑戰!\n");
break;
}
else {
printf("您的輸入有誤,請您重新輸入:\n");
continue;
}
}
return 0;
}
**搜圖函數** 記錄人所在的位置,並且計算地圖之中的箱子總數
void InitData(){
int i, j;
for (i = 0; i < MAX_ROW; i++){
for (j = 0; j < MAX_COL; j++){
//遍歷到2(人)時,記錄人的座標。x, y是前面定義的全局變量
if (map[i][j] == 2){
x = j;
y = i;
}
if (map[i][j] == 3){//計算地圖之中箱子的數目
Boxs++;
}
}
}
}
**打印地圖函數**
void drawMap(){
int i, j;
for (i = 0; i < MAX_ROW; i++){
for (j = 0; j < MAX_COL; j++){
switch (map[i][j]){
case 0://空白處
printf(" ");
break;
case 1://牆
printf("■");
break;
case 2:
printf("♀");
break;
case 3:
printf("◆");
break;
case 4:
printf("●");
break;
case 5:
printf("★");
break;
}
}
printf("\n");
}
}
**向上移動函數**
void MoveUp(){
if (y == 0){//當上方直接是牆的時候,直接進行返回
return;
}
int Ux = x;
int Uy = y - 1;
if (map[Uy][Ux] == 1||map[Uy][Ux]==5){//若上方是牆或者是已經完成的箱子,則不動
return;
}
if (map[Uy][Ux] == 3){//在上方是箱子的情況下
if (map[Uy - 1][Ux] == 1){//若再上方是牆的話,依然不動
return;
}
if (map[Uy - 1][Ux] == 4){//若上方是終點的話
map[Uy - 1][Ux] = 5;//將箱子向前移動,達到終點
Boxs--;
}
else{
map[Uy - 1][Ux] = 3;//若上方沒有任何東西,則箱子肯定會向上一步
}
}
map[y][x] = 0;//將人的位置置換爲0
map[Uy][Ux] = 2;//將原箱子的位置置換爲人
y = Uy;//將人的位置進行改變
}
**向下移動函數**
void MoveDown(){
int D = MAX_ROW - 1;
if (y == D){//下方是牆,則不移動;
return;
}
int Dx = x;
int Dy = y + 1;
if (map[Dy][Dx] == 1 || map[Dy][Dx] == 5){//若下方是牆或者是已經完成的箱子,則不動
return;
}
if (map[Dy][Dx] == 3){//在下方是箱子的情況下
if (map[Dy + 1][Dx] == 1){//若再下方是牆的話,依然不動
return;
}
if (map[Dy + 1][Dx] == 4){//若下方是終點的話
map[Dy + 1][Dx] = 5;//將箱子向下方移動,達到終點
Boxs--;
}
else{
map[Dy + 1][Dx] = 3;//若下方沒有任何東西,則箱子肯定會向下一步
}
}
map[y][x] = 0;//將人的位置置換爲0
map[Dy][Dx] = 2;//將原箱子的位置置換爲人
y = Dy;//將人的位置進行改變
}
**向左移動函數**
void MoveLeft(){
if (x == 0){
return;
}//左邊是牆的話,則不動;
int Lx = x - 1;
int Ly = y;
if (map[Ly][Lx] == 1 || map[Ly][Lx] == 5){//若左方是牆或者是已經完成的箱子,則不動
return;
}
if (map[Ly][Lx] == 3){//在左方是箱子的情況下
if (map[Ly][Lx - 1] == 1){//若再左方是牆的話,依然不動
return;
}
if (map[Ly][Lx - 1] == 4){//若左方是終點的話
map[Ly][Lx - 1] = 5;//將箱子向左方移動,達到終點
Boxs--;
}
else{
map[Ly][Lx - 1] = 3;//若左方沒有任何東西,則箱子肯定會向左方一步
}
}
map[y][x] = 0;//將人的位置置換爲0
map[Ly][Lx] = 2;//將原箱子的位置置換爲人
x = Lx;//將人的位置進行改變
}
**向右移動函數**
void MoveRight(){
int R = MAX_COL - 1;
if (x == R){
return;
}
int Rx = x + 1;
int Ry = y;
if (map[Ry][Rx] == 1 || map[Ry][Rx] == 5){//若右方是牆或者是已經完成的箱子,則不動
return;
}
if (map[Ry][Rx] == 3){//在右方是箱子的情況下
if (map[Ry][Rx + 1] == 1){//若再右方是牆的話,依然不動
return;
}
if (map[Ry][Rx + 1] == 4){//若右方是終點的話
map[Ry][Rx + 1] = 5;//將箱子向右方移動,達到終點
Boxs--;
}
else{
map[Ry][Rx + 1] = 3;//若右方沒有任何東西,則箱子肯定會向右一步
}
}
map[y][x] = 0;//將人的位置置換爲0
map[Ry][Rx] = 2;//將原箱子的位置置換爲人
x = Rx;//將人的位置進行改變
}
int Game(){
char direction; //定義方向鍵
InitData();
while (1){
system("cls");
drawMap();
printf("請輸入你所需要移動的方向(小寫字母):(W爲上,A爲左,S爲下,D爲右)\n");
if (!Boxs){
break;
}
direction = getch();
switch (direction){
case 'w':
MoveUp();
break;
case 'a':
MoveLeft();
break;
case 's':
MoveDown();
break;
case 'd':
MoveRight();
break;
}
}
printf("您已通關遊戲!\n");
return 0;
所有的程序到這裏也就完結了,其實對於這個推箱子游戲來說挺簡單的,只要我們能夠理解到在移動人的時候相對應的那些箱子的轉換就能夠很好的把握到相關的代碼,最爲主要的是一定要仔細,並且將自己所存在的思維漏洞或者說是死角記錄下來,總結成一些學習筆記,這樣也能夠更好的幫助我們應對之後所出現的更多的問題。
源代碼在這裏哦推箱子游戲程序Github鏈接