前言:
先說說我寫推箱子小游戲的程序,
第一版:沒有圖形化界面,不能選關,只有推箱子的最基礎功能,
第二版:增加圖形化界面,但是不能選擇關卡,
最終版:增加選擇關卡功能、播放/關閉音樂功能、退出游戲功能,捕獲滑鼠功能,
首先看一下最終版效果圖

功能點分析:
打開/關閉音樂和退出游戲比較簡單,
打開音樂所需呼叫的頭檔案
#include <graphics.h> //呼叫easyx圖形庫時所需增加的頭檔案
#include <mmsystem.h>
#pragma comment(lib,"winmm.lib") //靜態庫資源
打開音樂呼叫的easyx內部函式
mciSendString("open 1.mp3", 0, 0, 0);//播放存放c代碼同一路徑的1.mp3音樂
mciSendString("play 1.mp3", 0, 0, 0);//回圈播放音樂資源
關閉音樂呼叫的easyx內部函式
mciSendString("close 1.mp3", 0, 0, 0);
退出游戲功能:直接找一個圖片,當滑鼠點擊退出游戲這個區域,那么就顯示該退出游戲的圖片,并退出控制臺,
選擇關卡可以用三維陣列:
三維陣列可以理解為多個二維陣列,例如map[3][10][10]表示有三個10x10的二維陣列,當我點擊關卡1,那么就列印map[1][10][10]這個區域的地圖,關卡二和關卡三類似,
捕獲滑鼠資訊:
easyx圖形庫給我們提供了滑鼠捕獲函式getmessage(EM_MOUSE),以及保存滑鼠訊息結構體:
// 滑鼠訊息的資料
struct
{
bool ctrl :1; // Ctrl 鍵是否按下
bool shift :1; // Shift 鍵是否按下
bool lbutton :1; // 滑鼠左鍵是否按下
bool mbutton :1; // 滑鼠中鍵是否按下
bool rbutton :1; // 滑鼠右鍵
short x; // 滑鼠的 x 坐標
short y; // 滑鼠的 y 坐標
short wheel; // 滑鼠滾輪滾動值,為 120 的倍數
};
整體代碼:
/*
問題:為什么通過一關后,再重新進入的話會進不去?也可以說閃退,
因為如果箱子已經到目的地了,那么就不會進入while(!gamePass())這個while回圈里面,
*/
#include <stdio.h>
#include <conio.h> //鍵盤輸入函式庫
#include <stdlib.h> //這個頭檔案包含了清屏函式system("cls");
#include <graphics.h> //呼叫easyx圖形庫時所需增加的頭檔案
#include <mmsystem.h>
#pragma comment(lib,"winmm.lib") //靜態庫資源
int flag;//0表示關卡1,1表示關卡2,2表示關卡3
EASYXMSG m; // 定義訊息變數
int map[3][10][10] =
{
1,1,1,1,1,1,1,1,1,1,
1,0,0,0,0,0,3,0,0,1,
1,0,0,5,4,0,0,0,0,1,
1,0,0,1,1,0,0,0,0,1,
1,0,1,0,0,0,1,0,0,1,
1,0,0,4,0,0,1,0,0,1,
1,0,0,0,0,0,0,0,0,1,
1,0,0,3,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,1,
1,1,1,1,1,1,1,1,1,1,
//關卡1
1,1,1,1,1,1,1,1,1,1,
1,0,0,1,0,0,0,0,0,1,
1,0,0,1,4,0,3,0,0,1,
1,0,0,0,0,0,0,0,0,1,
1,0,1,0,0,0,1,0,0,1,
1,0,1,4,0,0,1,0,0,1,
1,0,1,0,0,0,0,0,0,1,
1,3,0,0,0,0,5,0,0,1,
1,0,0,0,0,0,0,0,0,1,
1,1,1,1,1,1,1,1,1,1,//關卡2
1,1,1,1,1,1,1,1,1,1,
1,1,0,0,1,1,0,0,0,1,
1,1,0,4,0,0,0,0,0,1,
1,1,0,1,1,0,0,0,0,1,
1,0,0,0,0,0,1,0,3,1,
1,0,0,4,0,0,1,0,0,1,
1,0,0,0,0,0,0,4,1,1,
1,0,0,3,0,5,0,0,1,1,
1,0,0,0,0,0,0,3,0,1,
1,1,1,1,1,1,1,1,1,1,//關卡3
};
IMAGE img[9]; //9張圖片,9個名字
void loadResource()
{
loadimage(img + 0, "0.bmp", 50, 50);//50表示圖片長寬,可以自己調的
loadimage(img + 1, "1.bmp", 50, 50);
loadimage(img + 2, "3.bmp", 50, 50);
loadimage(img + 3, "4.bmp", 50, 50);
loadimage(img + 4, "5.bmp", 50, 50);
loadimage(img + 5, "7.bmp", 50, 50);
loadimage(img + 6, "8.jpeg", 500, 200);
loadimage(img + 7, "9.jfif", 500, 500);//退出游戲
loadimage(img + 8, "10.jfif", 500, 500);//恭喜過關
}
void Printmap()
{
int i,j;
for (i = 0; i < 10; i++)
{
for (j = 0; j < 10; j++)
{
int x,y;
x = j* 50;
y = i* 50;
switch (map[flag][i][j])
{
//0:空地 1:墻 3:箱子要放的位置 4:箱子 5:人 7:箱子到達目的地 8:人到達目的地
/*case 0: printf(" "); break;
case 1: printf("■"); break;
case 3: printf("☆"); break;
case 4: printf("□"); break;
case 5:
case 8:
printf("♀");
break;
case 7: printf("★"); break;
*/
case 0: putimage(x, y, img + 0); break; //把圖片列印在控制臺,從坐標點x,y開始顯示圖片
case 1: putimage(x, y, img + 1); break;
case 3: putimage(x, y, img + 2); break;
case 4: putimage(x, y, img + 3); break;
case 5:
case 8: putimage(x, y, img + 4); break;
case 7: putimage(x, y, img + 5); break;
default:
break;
}
}
printf("\n");
}
}
void PlayGame()
{
char temp;
//遍歷整個地圖,找到人所在的坐標,并把坐標值賦給i,j這兩個變數,
int x,y;
int i,j;
for(x=0;x<10;x++)
{
for(y=0;y<10;y++)
{
if(map[flag][x][y] == 5 || map[flag][x][y] == 8)
{
i=x;
j=y;
}
}
}
temp = _getch();//鍵盤輸入無回顯函式
switch (temp)
{
case 'W':
case 'w':
if (map[flag][i - 1][j] == 0 || map[flag][i - 1][j] == 3) //如果下一步是空地 或者是 箱子要放的位置
{
map[flag][i][j] -= 5;
map[flag][i - 1][j] += 5;
}
if (map[flag][i - 1][j] == 4 || map[flag][i - 1][j] == 7)//如果下一步是箱子 或者是 箱子到達目的地
{
if (map[flag][i - 2][j] == 0 || map[flag][i - 2][j] == 3)//如果繼續下一步是空地 或者是 箱子要放的位置
{
map[flag][i][j] -= 5;
map[flag][i - 1][j] += 1;
map[flag][i - 2][j] += 4;
}
}
break;
case 'S':
case 's':
if (map[flag][i + 1][j] == 0 || map[flag][i + 1][j] == 3)
{
map[flag][i][j] -= 5;
map[flag][i + 1][j] += 5;
}
if (map[flag][i + 1][j] == 4 || map[flag][i + 1][j] == 7)
{
if (map[flag][i + 2][j] == 0 || map[flag][i + 2][j] == 3)
{
map[flag][i][j] -= 5;
map[flag][i + 1][j] += 1;
map[flag][i + 2][j] += 4;
}
}
break;
case 'A':
case 'a':
if (map[flag][i][j - 1] == 0 || map[flag][i][j - 1] == 3)
{
map[flag][i][j] -= 5;
map[flag][i][j - 1] += 5;
}
if (map[flag][i][j - 1] == 4 || map[flag][i][j - 1] == 7)
{
if (map[flag][i][j - 2] == 0 || map[flag][i][j - 2] == 3)
{
map[flag][i][j] -= 5;
map[flag][i][j - 1] += 1;
map[flag][i][j - 2] += 4;
}
}
break;
case 'D':
case 'd':
if (map[flag][i][j + 1] == 0 || map[flag][i][j + 1] == 3)
{
map[flag][i][j] -= 5;
map[flag][i][j + 1] += 5;
}
if (map[flag][i][j + 1] == 4 || map[flag][i][j + 1] == 7)
{
if (map[flag][i][j + 2] == 0 || map[flag][i][j + 2] == 3)
{
map[flag][i][j] -= 5;
map[flag][i][j + 1] += 1;
map[flag][i][j + 2] += 4;
}
}
break;
default:
break;
}
}
int gamePass() //游戲通關
{
//地圖上沒有箱子就可以結束
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
if (map[flag][i][j] == 4)
{
return 0;
}
}
}
return 1;
}
void draw_initgraph()//游戲首頁界面
{
initgraph(500, 500);//創建一個大小為500 x 500 的視窗
loadResource();//加載資源函式
putimage(0, 0, &img[6]);//圖1的左上角的頂點為(0,0)
setbkmode(TRANSPARENT); //設定填制背景為透明,這樣填充文字時背景才是圖片的顏色
//在左上角坐標為(x,y)處輸出文字
//outtextxy(215, 50, "推箱子");
outtextxy(120, 250, "關卡1");
outtextxy(240, 250, "關卡2");
outtextxy(360, 250, "關卡3");
outtextxy(105, 300, "打開音樂");
outtextxy(105, 350, "關閉音樂");
outtextxy(345, 350, "退出游戲");
//在左上角(x1,y1)和右下角(x2,y2)范圍畫一個矩形,這個是設定的滑鼠點擊各按鍵時的范圍
rectangle(100, 245, 175, 270);//關卡1
rectangle(220, 245, 295, 270);//關卡2
rectangle(340, 245, 415, 270);//關卡3
rectangle(100, 295, 175, 320);//打開音樂
//rectangle(390, 295, 465, 320);
rectangle(100, 345, 175, 370);//關閉音樂
rectangle(340, 345, 415, 370);//退出游戲
}
int main()
{
level:
draw_initgraph();
while (1)
{
m = getmessage(EM_MOUSE);//獲取滑鼠資訊
if (m.x >= 100 && m.x <= 175 && m.y >= 295 && m.y <= 320)
{//如果游標在打開音樂
setlinecolor(RED);
rectangle(95, 290, 180, 325);
if (m.lbutton)
{ //如果按下滑鼠左鍵實作相應功能.
mciSendString("open 1.mp3", 0, 0, 0);//播放音樂
mciSendString("play 1.mp3", 0, 0, 0);//回圈播放音樂資源
}
}
else if(m.x >= 100 && m.x <= 175 && m.y >= 345 && m.y <= 370)
{//如果游標在關閉音樂
setlinecolor(RED);
rectangle(95, 340, 180, 375);
if (m.lbutton)
{ //如果按下滑鼠左鍵實作相應功能.
mciSendString("close 1.mp3", 0, 0, 0);//關閉音樂
}
}
else if(m.x >= 340 && m.x <= 415 && m.y >= 345 && m.y <= 370)
{//如果游標在退出游戲
setlinecolor(RED);
rectangle(335, 340, 420, 375);
if (m.lbutton)
{ //如果按下滑鼠左鍵實作相應功能.
putimage(0, 0, &img[7]);//圖3的左上角的頂點為(0,0)
Sleep(2000);
closegraph();
break;
}
}
else if(m.x >= 100 && m.x <= 175 && m.y >= 245 && m.y <= 270)
{//如果游標在關卡1
setlinecolor(RED);
rectangle(95, 240, 180, 275);
flag = 0;
if (m.lbutton)
{ //如果按下滑鼠左鍵實作相應功能.
while(!gamePass())
{
Printmap();
PlayGame();
system("cls");
}
putimage(0, 0, &img[8]);//圖3的左上角的頂點為(0,0)
Sleep(1500);
goto level;
}
}
else if(m.x >= 220 && m.x <= 295 && m.y >= 245 && m.y <= 270)
{//如果游標在關卡2
setlinecolor(RED);
rectangle(215, 240, 300, 275);
flag = 1;
if (m.lbutton)
{ //如果按下滑鼠左鍵實作相應功能.
while(!gamePass())
{
Printmap();
PlayGame();
system("cls");
}
putimage(0, 0, &img[8]);//圖3的左上角的頂點為(0,0)
Sleep(1500);
goto level;
}
}
else if(m.x >= 340 && m.x <= 415 && m.y >= 245 && m.y <= 270)
{//如果游標在關卡3
setlinecolor(RED);
rectangle(335, 240, 420, 275);
flag = 2;
if (m.lbutton)
{ //如果按下滑鼠左鍵實作相應功能.
while(!gamePass())
{
Printmap();
PlayGame();
system("cls");
}
putimage(0, 0, &img[8]);//圖3的左上角的頂點為(0,0)
Sleep(1500);
goto level;
}
}
else
{ //當滑鼠不在目標位置就用背景色覆寫之前的藍色邊框.
setlinecolor(BLACK);
rectangle(95, 290, 180, 325);
setlinecolor(BLACK);
rectangle(95, 340, 180, 375);
setlinecolor(BLACK);
rectangle(335, 340, 420, 375);
setlinecolor(BLACK);
rectangle(95, 240, 180, 275);
setlinecolor(BLACK);
rectangle(215, 240, 300, 275);
setlinecolor(BLACK);
rectangle(335, 240, 420, 275);
}
}
//closegraph();//關閉視窗
return 0;
}
ps:這里面需要用到的圖片和音樂素材可以自己尋找,也可以在評論區留下郵箱我看到了就發給你,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/293052.html
標籤:其他
上一篇:Python Pygame制作簡單五子棋游戲(詳細代碼+解釋)
下一篇:C語言實作掃雷(初階)
