『壹』 如何用C++寫掃雷
用VC++編寫掃雷游戲
用VC++編寫掃雷游戲
王洪亞
本文從分析windows掃雷游戲的功能特點開始,應用面向對象的可視化編程語言visual c++給出了個功能模塊的具體實現方法,並提供了編寫小游戲程序的一般方法和visual c++的一些使用技巧。
首先分析掃雷的最基本功能。
點擊滑鼠左鍵於未知區域,如果未知區域有雷,游戲停止,顯示所有的地雷。如果沒雷,則顯示周圍雷數,如果周圍沒雷,則再查看周圍八個區域是否有雷直到有雷為止並顯示,這其實是一個遞歸過程。
點擊滑鼠右鍵於未知區域,則將其置為有雷而不管是否真的有雷。可選擇初、中、高三級並可自定義雷數和區域大小。
雷區上部左側顯示總雷數減被標明有雷區域的數目。
雷區上部中間位置顯示一按鈕用於開局和顯示滑鼠動作的結果。
雷區上部右側顯示掃雷的時間。
將雷全部掃清後,則顯示一對話框將你的姓名記入排行榜。以時間排序。
為完成上述功能,應用visual c++的具體技術細節如下:
1. 應用appwizard創建基於sdi的應用程序cbombapp,去除列印和狀態條支持,在資源編輯器中修改菜單和相應的加速鍵,使其與windows掃雷游戲一致。具體為開局(id-game-begin)、初級(id-game-junior)、中級(id-game-middle)、高級(id-game-senior)、自定義(id-game-custom)、顏色(id-game-color)、英雄榜(id-game-sort)、退出(id-game-exit)、幫助(id-help)。
2. 在資源編輯器中對應於雷區的每個小區域的13個屬性。用畫筆或其他繪圖工具繪制出相對應的13個10乘10的16色小點陣圖,三個對應於小人表情的20乘20的16色小點陣圖,供更換顏色時使用的一套與前16個對應的單色點陣圖,顯示時間和雷數的0~9十個數字點陣圖(底色為黑色)。
定製customer對話框,內含三個靜態文本控制項和三個編輯控制項,三個編輯控制項分別對應成員m_irownum,m_icolumnnum,m_ibombnum。該對話框用於定製雷數,行列數,其相應的mfc類為ccustomer。定製sort對話框,內含九個靜態文本控制項,其中六個顯示排行榜的姓名和時間,其對應的mfc類為csort。定製input對話框,內含一個靜態文本控制項和一個編輯控制項,編輯控制項用於在游戲成功結束時輸入姓名,其對應的mfc類為cinput。
3. 定義類bomb,封裝每顆雷的相關屬性。
class bomb
{
public:
int isbomb;//決定初始時是否是雷
bool issel; //判斷區域是否被處理過且周圍有雷
bool isdone;//判斷遞歸時是否被處理過
int num; //周圍雷數
bool findbomb; //排雷者認為是雷時置一(但是不一定真是雷)
} ;
4. 重載cmainframe中precreatewindow,並設置相應屬性,使其窗體大小固定,這樣就固定了顯示區域的大小為初始10乘10個雷和外加雷區上部的控制區域,部分代碼如下。
cs.style=ws_overlapped|ws_sysmenu| ws_border|ws_minimizebox;
cs.cy = 10*15+6;
cs.cx = 10*15+60; //6和60分別是橫縱的附加值,用於邊框、菜單、標題條、控制區域。
5. 游戲的主要工作就是呈現不斷變換的圖形或動畫,並按用戶的輸入交互進行顯示,而windows文檔-----視窗構架中的視窗的功能正是接受用戶輸入並負責顯示,因此由cview類來完成掃雷的大部分工作。在cbombview中定義下列成員變數記錄相關操作的結果或對象的狀態。
bomb m_bomb[30][30]; //最大的地雷區域
cstring m_currenttime; //用於記錄並顯示掃雷時間
ctime m_begintime;//記錄游戲開始時的時間
bool m_timerbegin;//定時器是否開啟
int m_ibomnum;//雷的數目
int m_irow;//雷的行數
int m_icolumn;//雷的列數
int m_ibombfound;//指示被認為是雷的數目
cbitmapbutton m_bitbutton;//控制區的點陣圖按鈕
int m_currentlevel;//指示當前游戲的級別
bool m_biscolor;//指示當前是彩色還是單色
cbitmap m_bmbomb[12];//用於存放12個小點陣圖
int m_igameover;//游戲未結束置0,已清除所有的雷置1,被炸死置2。
重載cbombview中oncreate函數創建點陣圖按鈕,該點陣圖按鈕的兩幅點陣圖對應了正常、排雷正確兩種狀態,當要顯示被炸死的狀態時應動態銷毀該按鈕,並重新創建一點陣圖對應正常和被炸死兩種狀態,將該點陣圖按鈕的id號定為id_game_begin,這樣一來當點擊按鈕時便可重新開始游戲,部分代碼如下。
crect rcclient;
getclientrect(&rcclient);
crect rect(rcclient.cx/2-8,10,rcclient.cx/2+8,20);
m_button.create("new",bs_defpushbutton|ws_visible|
bs_ownerdraw,rect,this,id_game_begin);
m_button.loadbitmaps(idb_face1, idb_face2);
顯示時間的功能相對比較簡單,在響應第一個wm_lbuttomdown消息時開啟定時器,並記錄游戲開始的時間,在wm_time消息響應函數ontimer中獲得當前時間,減去游戲開始時的時間,在顯示時間的客戶區域顯示得到的時間差(用數字點陣圖),當游戲結束時(排完全部雷或被炸死)關閉定時器,停止顯示。
wm_lbuttomdown消息響應函數onlbuttomdown是處理用戶輸入的主要執行者,函數首先判斷點中位置是否是雷,是則關閉定時器,銷毀原點陣圖按鈕,創建一對應正常和被炸死兩種狀態的新點陣圖按鈕,並調用setstate將其設置為pushdown(小人哭的狀態),將m_bgameover,置為true標志游戲結束,否則先調用setstate 設置點陣圖按鈕為pushdown (小人笑的狀態),並在onlbuttomup中設置點陣圖按鈕為正常狀態,然後調用caculate函數記下周圍雷的數目,最後調用invalidate使客戶區無效,迫使ondraw函數重繪客戶區域,在調用invalidate時不應重畫背景,避免閃爍,這樣就完成了在雷區按下左鍵的響應動作。
wm_rbuttomdown消息響應函數onlbuttomdown將被認為有雷位置的m_ibombnum.findbomb置一,減少左上角的雷記數,然後判斷是否真正全部排完了雷,是則結束游戲彈出input對話框,讓掃雷的人輸入姓名,在響應idok通知碼時將其寫入注冊表,沒有全部排完則使客戶區無效,迫使ondraw函數重繪客戶區域完成在雷區按下右鍵的動作。
ondraw函數在每次點擊左鍵或右鍵時都會被調用重雷區和控制區域,因為點擊情況的復雜性和雷屬性的多元化導致ondraw函數需要精心設計。
函數caculate計算某個雷周圍的雷數,根據前面的分析知道,計算某個雷周圍的雷數本身就是一個遞歸過程,在編制時應注意遞歸的邊界條件,稍不注意會陷入無窮遞歸而耗盡了系統的資源。
6. 菜單命令的響應是游戲交互的另一個重要方式,下面的九個命令響應函數分別與九個菜單項相對應,用以完成用戶的更新和設置命令。
ongamebegin完成初始時間清零,隨機布雷,依據顏色指示裝載12幅小點陣圖,使雷區無效調用ondraw重繪等工作。其中隨機布雷就是多次調用rand(),根據其返回值決定m_bomb[i][j].isbomb的值。
ongamecustom首先彈出ccustomer對話框,在用戶輸入設置後響應idok通知碼時將用戶輸入的雷數、行列數分別賦給cview的數據成員m_ibombnum、m_irow、m_icolumn,得到框架窗口的指針,用其調用movewindow將窗口調至所需大小,銷毀原位置的點陣圖按鈕,並在x軸坐標為新窗口寬1/2減8處,y軸坐標為新窗口頂部加30的位置創建一新按鈕。最後調用ongamebegin重新開始游戲。
ongamejunior、ongamemiddle、ongamesenior三個函數與ongamecustom類似,只不過將分別賦給cview的數據成員m_ibombnum、m_irow、m_icolumn以固定的值,其大小可由編程者自定,筆者定為junior(20,8,8,)、middle(40,13,13)、senior(99,20,25)。
ongamecolor函數銷毀原點陣圖按鈕,根據重新裝載點陣圖的標志m_iscolor來創建新的點陣圖按鈕,將裝載12幅單色點陣圖的標志取反,調用ongamebegin重新開始游戲。
ongamesort函數根據當前游戲級別從注冊表中讀出排名並彈出sort對話框顯示結果。到現在為止,一個自己編制的掃雷游戲就基本完成了,將數百行代碼編譯一下,找出小錯誤,最後build一遍,run一下,好了,可愛的掃雷游戲就出現在你的面前了。怎麼樣,自己的勞動成果並不比microsoft的差吧,而且你還可以把小點陣圖畫成各種樣子,當然你自己要認得出才行了。
『貳』 c程序編程掃雷
希望對你有幫助!
#include <graphics.h>
#include <stdlib.h>
#include <dos.h>
#define LEFTPRESS 0xff01
#define LEFTCLICK 0xff10
#define LEFTDRAG 0xff19
#define MOUSEMOVE 0xff08
int num[10][10];/*范圍*/
int p[10][10];/*統計雷的數組*/
int loop;/*重新來的標志*/
int again=0;/*是否重來的變數*/
int scorenum;/*一開始統計有幾個雷*/
char score[3];/*輸出一共有幾個地雷*/
int Keystate;
int MouseExist;
int MouseButton;
int MouseX;
int MouseY;
/*滑鼠游標形狀定義*/
typedef struct
{
unsigned int shape[32];
char hotx;
char hoty;
}SHAPE;
/*箭頭型*/
SHAPE ARROW={
{
0x3fff,0x1fff,0x0fff,0x07ff,
0x03ff,0x01ff,0x00ff,0x007f,
0x003f,0x00ff,0x01ff,0x10ff,
0x30ff,0xf87f,0xf87f,0xfc3f,
0x0000,0x7c00,0x6000,0x7000,
0x7800,0x7c00,0x7e00,0x7f00,
0x7f80,0x7e00,0x7c00,0x4600,
0x0600,0x0300,0x0300,0x0180
},
0,0,
};
/*滑鼠游標顯示*/
void MouseOn()
{
_AX=0x01;
geninterrupt(0x33);
}
/*滑鼠游標掩示*/
void MouseOff()/*滑鼠游標隱藏*/
{
_AX=0x02;
geninterrupt(0x33);
}
void MouseSetXY(int x,int y)/*設置當前位置*/
{
_CX=x;
_DX=y;
_AX=0x04;
geninterrupt(0x33);
}
int LeftPress()/*左鍵按下*/
{
_AX=0x03;
geninterrupt(0x33);
return(_BX&1);
}
void MouseGetXY()/*得到當前位置*/
{
_AX=0x03;
geninterrupt(0x33);
MouseX=_CX;
MouseY=_DX;
}
begain()/*游戲開始畫面*/
{
int i,j;
loop: cleardevice();
MouseOn();
MouseSetXY(180,30);
MouseX=180;
MouseY=30;
scorenum=0;
setfillstyle(SOLID_FILL,7);
bar(190,60,390,290);
setfillstyle(SOLID_FILL,8);
for(i=100;i<300;i+=20)/*畫格子*/
for(j=200;j<400;j+=20)
bar(j-8,i+8,j+8,i-8);
setcolor(7);
setfillstyle(SOLID_FILL,YELLOW);/*畫臉*/
fillellipse(290,75,10,10);
setcolor(YELLOW);
setfillstyle(SOLID_FILL,0);
fillellipse(285,75,2,2);
fillellipse(295,75,2,2);
setcolor(0);
bar(287,80,293,81);
randomize();
for(i=0;i<10;i++)
for(j=0;j<10;j++)
{
num[i][j]=random(7)+10;/*用10代表地雷算了*/
if(num[i][j]==10)
scorenum++;
}
sprintf(score,"%d",scorenum);
setcolor(1);
settextstyle(0,0,2);
outtextxy(210,70,score);
scorenum=100-scorenum;/*為了後面判斷勝利*/
}
gameove()/*游戲結束畫面*/
{
int i,j;
setcolor(0);
for(i=0;i<10;i++)
for(j=0;j<10;j++)
if(num[i][j]==10)/*是地雷的就顯示出來*/
{
setfillstyle(SOLID_FILL,RED);
bar(200+j*20-8,100+i*20-8,200+j*20+8,100+i*20+8);
setfillstyle(SOLID_FILL,0);
fillellipse(200+j*20,100+i*20,7,7);
}
}
int tongji(int i,int j)/*計算有幾個雷*/
{
int x=0;/*10代表地雷*/
if(i==0&&j==0)
{
if(num[0][1]==10)
x++;
if(num[1][0]==10)
x++;
if(num[1][1]==10)
x++;
}
else if(i==0&&j==9)
{
if(num[0][8]==10)
x++;
if(num[1][9]==10)
x++;
if(num[1][8]==10)
x++;
}
else if(i==9&&j==0)
{
if(num[8][0]==10)
x++;
if(num[9][1]==10)
x++;
if(num[8][1]==10)
x++;
}
else if(i==9&&j==9)
{
if(num[9][8]==10)
x++;
if(num[8][9]==10)
x++;
if(num[8][8]==10)
x++;
}
else if(j==0)
{
if(num[i][j+1]==10)
x++;
if(num[i+1][j]==10)
x++;
if(num[i-1][j]==10)
x++;
if(num[i-1][j+1]==10)
x++;
if(num[i+1][j+1]==10)
x++;
}
else if(j==9)
{
if(num[i][j-1]==10)
x++;
if(num[i+1][j]==10)
x++;
if(num[i-1][j]==10)
x++;
if(num[i-1][j-1]==10)
x++;
if(num[i+1][j-1]==10)
x++;
}
else if(i==0)
{
if(num[i+1][j]==10)
x++;
if(num[i][j-1]==10)
x++;
if(num[i][j+1]==10)
x++;
if(num[i+1][j-1]==10)
x++;
if(num[i+1][j+1]==10)
x++;
}
else if(i==9)
{
if(num[i-1][j]==10)
x++;
if(num[i][j-1]==10)
x++;
if(num[i][j+1]==10)
x++;
if(num[i-1][j-1]==10)
x++;
if(num[i-1][j+1]==10)
x++;
}
else
{
if(num[i-1][j]==10)
x++;
if(num[i-1][j+1]==10)
x++;
if(num[i][j+1]==10)
x++;
if(num[i+1][j+1]==10)
x++;
if(num[i+1][j]==10)
x++;
if(num[i+1][j-1]==10)
x++;
if(num[i][j-1]==10)
x++;
if(num[i-1][j-1]==10)
x++;
}
return(x);
}
funcheck(int i,int j)/*開始找無雷*/
{
scorenum--;
if(p[i][j]==0&&num[i][j]!=10)
{
setfillstyle(SOLID_FILL,7);/*顯示無雷區*/
bar(200+j*20-7,100+i*20-7,200+j*20+7,100+i*20+7);
num[i][j]=-1;
}
else if(p[i][j]!=0)
{
sprintf(score,"%d",p[i][j]);/*輸出雷數*/
setcolor(RED);
outtextxy(195+j*20,95+i*20,score);
num[i][j]=-1;
return ;
}
if(i!=0&&num[i-1][j]!=-1&&num[i-1][j]!=10)/*第歸開始*/
funcheck(i-1,j);
if(i!=0&&j!=9&&num[i-1][j+1]!=-1&&num[i-1][j+1]!=10)
funcheck(i-1,j+1);
if(j!=9&&num[i][j+1]!=-1&&num[i][j+1]!=10)
funcheck(i,j+1);
if(j!=9&&i!=9&&num[i+1][j+1]!=-1&&num[i+1][j+1]!=10)
funcheck(i+1,j+1);
if(i!=9&&num[i+1][j]!=-1&&num[i+1][j]!=10)
funcheck(i+1,j);
if(i!=9&&j!=0&&num[i+1][j-1]!=-1&&num[i+1][j-1]!=10)
funcheck(i+1,j-1);
if(j!=0&&num[i][j-1]!=-1&&num[i][j-1]!=10)
funcheck(i,j-1);
if(i!=0&&j!=0&&num[i-1][j-1]!=-1&&num[i-1][j-1]!=10)
funcheck(i-1,j-1);
}
playgame()/*游戲過程*/
{int i,j,numx;
for(i=0;i<10;i++)
for(j=0;j<10;j++)
p[i][j]=tongji(i,j);/*把標記有幾個雷的數字都存放起來*/
while(!kbhit())
{
if(LeftPress())/*左鍵盤按下*/
{
MouseGetXY();
if(MouseX>280&&MouseX<300&&MouseY>65&&MouseY<85)/*重新來*/
{
MouseOff();
again=1;
break;
}
if(MouseX>190&&MouseX<390&&MouseY>90&&MouseY<290)/*是否在游戲范圍內*/
{
j=(MouseX-190)/20;/*x坐標*/
i=(MouseY-90)/20;/*y坐標*/
if(num[i][j]!=-1)
{
if(num[i][j]==10)/*中雷*/
{
MouseOff();
gameove();/*失敗*/
break;
}
else/*非中雷*/
{
MouseOff();
numx=tongji(i,j);
if(numx==0)/*周圍沒地雷*/
funcheck(i,j);/*開始找無雷*/
else/*有地雷*/
{
sprintf(score,"%d",numx);/*輸出雷數*/
setcolor(RED);
outtextxy(195+j*20,95+i*20,score);
scorenum--;
}
MouseOn();
num[i][j]=-1;
if(scorenum<1)/*勝利了*/
{
setcolor(11);
settextstyle(0,0,2);
outtextxy(230,30,"YOU WIN!");
break;
}
}
}
}
}
}
}
main()
{int gd=DETECT,gr;
registerbgidriver(EGAVGA_driver);
initgraph(&gd,&gr,"c:\\tc");
loop: begain();
playgame();/*具體游戲*/
if(again)/*游戲中重新開始*/
{
again=0;
goto loop;
}
MouseOn();
while(!kbhit())/*重新來*/
{
if(LeftPress())
{
MouseGetXY();/*失敗後重新來*/
if(MouseX>280&&MouseX<300&&MouseY>65&&MouseY<85)
goto loop;
}
}
MouseOff();
closegraph();
}
本文來自: 中科軟體園(www.4oa.com) 詳細出處參考:http://www.4oa.com/Article/html/6/31/446/2005/15615.html
『叄』 畢業設計要做一個掃雷游戲,求完整代碼,最好是用java做的,沒有別的也行。但一定要運行得了啊。拜謝
【代碼1】: new LinkedList();
【代碼2】: list.add(block[i][j]) ;
【代碼3】: list.size();
【代碼4】: (Block)list.get(randomIndex);
【代碼5】: list.remove(randomIndex);
2.模板代碼
Block.java
public class Block
{ String name;
int number;
boolean boo=false;
public void setName(String name)
{ this.name=name;
}
public void setNumber(int n)
{ number=n;
}
public int getNumber()
{ return number;
}
public String getName()
{ return name;
}
boolean isMine()
{ return boo;
}
public void setIsMine(boolean boo)
{ this.boo=boo;
}
}
LayMines.java
import java.util.LinkedList;
public class LayMines
{ public void layMinesForBlock(Block block[][],int mineCount)
{ int row=block.length;
int column=block[0].length;
LinkedList list=【代碼1】 //創建空鏈表list
for(int i=0;i<row;i++)
{ for(int j=0;j<column;j++)
{ 【代碼2】 // list添加節點,其中的數據為block[i][j]
}
}
while(mineCount>0)
{ int size=【代碼3】 // list返回節點的個數
int randomIndex=(int)(Math.random()*size);
Block b=【代碼4】 // list返回索引為randomIndex的節點中的數據
b.setName(
『肆』 用VB編程實現掃雷的思路
'一個簡單掃雷游戲
Option Explicit
Dim Map() As Integer
Dim Row_Num, Col_Num As Integer '范圍,一個正方形的邊長
Dim Ant_Num As Long '白蟻數量
Const x0 = 30 '方框左上角坐標
Const y0 = 30
Const 小快寬度 = 9
Dim a As Integer '各個小塊的邊長
Private Sub Command1_Click()
'重設按鈕
Init_Form
End Sub
Private Sub Form_Load()
Init_Form
End Sub
Private Sub Form_MouseUp(Button As Integer, Shift As Integer, x As Single, y As Single)
Dim x1 As Integer, y1 As Integer
x1 = Fix((x - x0) / a): y1 = Fix((y - y0) / a)
If (x - x0) > ((Col_Num + 1) * a) Or (y - y0) > ((Col_Num + 1) * a) Then Exit Sub
If x < x0 Or y < y0 Then Exit Sub
If x < x0 + x1 * a + 2 Or _
x > x0 + x1 * a + a - 4 Or _
y < y0 + y1 * a + 2 Or _
y > y0 + y1 * a + a - 4 _
Then Exit Sub
If Button = 1 Then
If Map(x1, y1) = 0 Then
Call fan(x1, y1)
ElseIf Map(x1, y1) = 1 Then
Call lose
End If
ElseIf Button = 2 Then
Call draw_flg(x1, y1)
End If
Dim n As Integer
n = 0
Dim i As Integer, j As Integer
For i = 0 To Col_Num
For j = 0 To Row_Num
If Map(i, j) = -2 Then n = n + 1
Next j
Next i
If n = (Col_Num + 1) * (Row_Num + 1) - Ant_Num Then
Beep
CurrentX = (Col_Num / 2) * a + x0
CurrentY = (Row_Num / 2) * a + y0
Call sub1
a = Form1.FontSize
Form1.FontSize = 80
'Form1.ForeColor = vbBlack
Print "you win"
Form1.FontSize = a
End If
End Sub
Sub fan(x As Integer, y As Integer)
Dim i As Integer, j As Integer
Dim n As Integer
For i = -1 To 1
For j = -1 To 1
If j * i = 0 And Map(x + i, y + j) = 0 Then
Map(x + i, y + j) = -2
n = Counts(x + i, y + j)
Form1.Line (x0 + (i + x) * a + 2, y0 + (j + y) * a + 2)-Step(a - 4, a - 4), Form1.BackColor, BF
If n <> 0 Then
CurrentX = (x + i) * a + 2 + x0
CurrentY = (y + j) * a + 2 + y0
Select Case n
Case Is = 1
Form1.ForeColor = vbWhite
Case Is = 2
Form1.ForeColor = vbYellow
Case Is > 2
Form1.ForeColor = vbRed
End Select
Print n
ElseIf n = 0 Then
Call fan(x + i, y + j)
End If
End If
Next j
Next i
End Sub
Function Counts(x As Integer, y As Integer) As Integer
Dim i As Integer, j As Integer
For i = -1 To 1
For j = -1 To 1
If Map(x + i, y + j) = 1 Then Counts = Counts + 1
Next
Next
End Function
Sub lose()
Dim i As Integer, j As Integer
For i = 0 To Row_Num
For j = 0 To Col_Num
If Map(j, i) = 1 Then
Form1.FillColor = vbBlack
Form1.FillStyle = 0
Form1.Circle (x0 + j * a + a / 2, y0 + i * a + a / 2), a / 3, vbBlack, , , 0.8
Form1.Line (x0 + j * a, y0 + i * a)-Step(a, a), vbWhite
Form1.Line (x0 + j * a + a, y0 + i * a)-Step(-a, a), vbWhite
ElseIf Map(j, i) = 0 Then
Form1.Line (x0 + j * a + 2, y0 + i * a + 2)-Step(a - 4, a - 4), Form1.BackColor, BF
CurrentX = j * a + x0
CurrentY = i * a + y0
Print Counts(j, i)
End If
Next j
Next i
Beep
a = Form1.FontSize
Form1.FontSize = 80
'Form1.ForeColor = vbBlack
Print "you lose"
Form1.FontSize = a
End Sub
Sub draw_flg(x As Integer, y As Integer)
CurrentX = x * a + x0 + 2
CurrentY = y * a + y0 + 2
Print "?"
End Sub
Public Sub Init_Form()
Form1.Cls
Form1.ScaleMode = 3
Form1.Width = 8000
Form1.Height = 6000
Form1.BackColor = vbGreen
Form1.AutoRedraw = True
Form1.Caption = "一個簡單掃雷游戲 作者 zfc"
Col_Num = 10 '獲取列數
Row_Num = 10 '獲取行數
a = 20 '單元寬(高)度
Ant_Num = 40 '雷的數量
ReDim Map(-1 To Col_Num + 1, -1 To Row_Num + 1)
Dim i As Integer, j As Integer
For i = -1 To Row_Num + 1
For j = -1 To Col_Num + 1
Form1.Line (x0 + j * a, y0 + i * a)-Step(a, a), 0, B
Form1.Line (x0 + j * a + 2, y0 + i * a + 2)-Step(a - 4, a - 4), vbRed, BF
Map(j, i) = 0 '初始化位置標記為空格0
If i = -1 Or i = Row_Num + 1 Or j = -1 Or j = Row_Num + 1 Then
Form1.Line (x0 + j * a + 1, y0 + i * a + 1)-Step(a - 2, a - 2), RGB(100, 120, 100), BF '畫四周牆體
Map(j, i) = -1 '四周位置標記為牆體:-1
End If
Next j
Next i
Dim x As Integer, y As Integer
For i = 1 To Ant_Num
1000
Randomize
x = Rnd * Col_Num
y = Rnd * Row_Num
DoEvents
If Map(x, y) <> 0 Then GoTo 1000
Map(x, y) = 1
Next
End Sub
Sub sub1()
Dim i As Integer, j As Integer
For i = 0 To Row_Num
For j = 0 To Col_Num
If Map(j, i) = 1 Then
Form1.FillColor = vbBlack
Form1.FillStyle = 0
Form1.Circle (x0 + j * a + a / 2, y0 + i * a + a / 2), a / 3, vbBlack, , , 0.8
ElseIf Map(j, i) = 0 Then
Form1.Line (x0 + j * a + 2, y0 + i * a + 2)-Step(a - 4, a - 4), Form1.BackColor, BF
CurrentX = j * a + x0
CurrentY = i * a + y0
Print Counts(j, i)
End If
Next j
Next i
End Sub
『伍』 誰用VB6.0做一個掃雷,並且寫出代碼和解釋
'窗體1
OptionExplicit
PrivateConstvbGray=&H848284'灰色
PrivateConstMLeftAsLong=180'雷區距離左側(按Twips計算)
PrivateConstMTopAsLong=825'雷區距離上部
PrivateConstWAVE_DEFAULT=432'默認聲音
PrivateConstWAVE_VICTORY=433'失敗聲音
PrivateConstWAVE_LOST=434'勝利聲音
PrivateConstBMP_GRID_WIDTH=16'格子的寬
PrivateConstBMP_GRID_HEIGHT=16'格子的高
PrivateConstBMP_NUM_WIDTH=13'數字的寬
PrivateConstBMP_NUM_HEIGHT=23'數字的高
PrivateConstBMP_NUM_TOP=16'數字距離上邊(菜單底)
PrivateConstBMP_NUM_MINE_LEFT=17'計數器距離左側
PrivateConstBMP_NUM_TIME_RIGHT=BMP_NUM_WIDTH*3+20'計時器左側距離窗體右側
PrivateConstBMP_FACE_WIDTH=24'表情的寬
PrivateConstBMP_FACE_HEIGHT=24'表情的高
PrivateConstBMP_FACE_TOP=16'表情距離上邊(菜單底)
PrivateCanPeeperAsBoolean'作弊啊
'初級9/9/10
'中級16/16/40
'高級30/16/99
'PrivateNoMineAsBoolean
PrivateSubInithDC()
DimIAsLong
DimhBmpAsStdPicture
'從資源讀取游戲圖片
ForI=0To2
'不用PictureBox
SethBmp=LoadResPicture(IIf(MnuCheck(1).Checked,410,411)+I*10,vbResBitmap)
LethBmpDC(I)=CreateCompatibleDC(Me.hdc)
CallSelectObject(hBmpDC(I),hBmp.Handle)
SethBmp=Nothing
Next
EndSub
'開始
PublicSubGameStart()
'NoMine=False
LetMe.Width=MLeft+(MWidth*16+8+GetMePixelWidth-Me.ScaleWidth)*Screen.TwipsPerPixelX'調整窗體寬度
LetMe.Height=MTop+(MHeight*16+8+GetMePixelHeight-Me.ScaleHeight)*Screen.TwipsPerPixelY'調整窗體高度270OR390'19/26'495/510
LetIsFirstHit=False'沒有埋雷'沒有處理第一個雷
LetIsGameWin=False'沒有贏
LetIsGameOver=False'沒有輸
LetTimer1.Enabled=False'定時器,需要滑鼠激活
LetTime_Count=0'記時器清零
LetNowFace=4'CallCheckFace(4)
ReDimN(MWidth-1,MHeight-1)
LetShow_Count=MWidth*MHeight'倒計數字,剩餘未揭開的格子
LetMine_Count=Mines'剩餘未標記的地雷
CallForm_Paint
CallSetMines
EndSub
'Downloadbyhttp://www.codefans.net
PrivateSubSetMines()'OptionalByValXAsLong,OptionalByValYAsLong
'初始化地雷
DimIAsLong',JAsLong
DimAAsLong,BAsLong
DimKAsLong,LAsLong
CallMath.Randomize'初始化隨機數生成器。
ForI=0ToMines-1
LetA=Int(MWidth*Rnd)'Int((upperbound-lowerbound+1)*Rnd+lowerbound)
LetB=Int(MHeight*Rnd)
IfNotN(A,B).IsMineThen'不能重復,不能是按下的位置'Not(A=XAndb=Y)And
'IfI=1Then
'IfNoMine=FalseThen
'LetA=X:b=Y'第一個按下去總是雷--#
'EndIf
'EndIf
LetN(A,B).IsMine=True
'統計每個格子周圍的地雷數目
AddtionA,B,1
Else
LetI=I-1'再來
EndIf
NextI
'NoMine=False
'顯示每個格子'作弊1
'DimJAsLong
'作弊2
'ForI=0To8
'ForJ=0To8
'IfN(I,J).IsMineThen
'N(I,J).State=1
''SetImageI,J,15-N(I,J).Number
''N(I,J).IsShow=True
'EndIf
'Next
'Next
EndSub
PrivateSubAddtion(ByValXAsLong,ByValYAsLong,ByValOneAsLong)
DimIAsLong,JAsLong
ForI=-1To1
ForJ=-1To1
IfInRange(X+I,Y+J)AndNot(I=0AndJ=0)Then'在地圖的范圍內
LetN(X+I,Y+J).Number=N(X+I,Y+J).Number+One
EndIf
Next
Next
EndSub
'雷區
PrivateSubSetImage(ByValXAsLong,ByValYAsLong,OptionalByValImgIDAsLong)
'每個圖片寬16,高16,ImgID=0~15
CallBitBlt(Me.hdc,MLeft/Screen.TwipsPerPixelX+X*BMP_GRID_WIDTH,MTop/Screen.TwipsPerPixelY+Y*BMP_GRID_HEIGHT,BMP_GRID_WIDTH,BMP_GRID_HEIGHT,hBmpDC(0),0,ImgID*BMP_GRID_HEIGHT,vbSrcCopy)
EndSub
'剩餘地雷和時間
PrivateSubSetNumber(ByValXAsLong,ByValYAsLong,ByValNumIDAsLong,OptionalByValnWhatAsBoolean=True)
'每個數字寬13,高23,NumID=0~11
CallBitBlt(Me.hdc,X*BMP_NUM_WIDTH+IIf(nWhat,BMP_NUM_MINE_LEFT,GetMePixelWidth-BMP_NUM_TIME_RIGHT),Y*BMP_NUM_HEIGHT+BMP_NUM_TOP,BMP_NUM_WIDTH,BMP_NUM_HEIGHT,hBmpDC(1),0,BMP_NUM_HEIGHT*NumID,vbSrcCopy)
EndSub
'表情
PrivateSubSetFace(OptionalByValFaceIDAsLong=4)
'每個笑臉寬24,高24,NumID=0~4
CallBitBlt(Me.hdc,GetMePixelWidth/2-BMP_FACE_WIDTH/2-1,BMP_FACE_TOP,BMP_FACE_WIDTH,BMP_FACE_HEIGHT,hBmpDC(2),0,BMP_FACE_HEIGHT*FaceID,vbSrcCopy)
EndSub
這些只是主窗體部分代碼,還有幾個模塊和窗體、相關文檔,寫不下你自己看附件
『陸』 請教掃雷演算法
掃雷的演算法有兩種,一種是老手使用的(憑經驗操作),一種是新手使用的,我現在介紹一下老手使用的演算法:
1.點第一個空
2.若點開的是一個格,則繼續第1步
若點開的是一片(打開數大於等於9),則進行第3步
3.觀察一片格的邊角,
若有一個格數字與它周圍的空格數相等,在空格處標雷並在兩側格子上同時左右鍵雙擊
若沒有這種情況則觀察有無[經驗公式]
這樣做直到不能再找到為止(一般能完成初、中級或高級的50%了)進行第4步
4.檢查邊角,重復第1步
—————
註:
[經驗公式]:121組合,雷在2上
1221組合,兩個雷在2上
還有好多復雜的,得自己總結
至於掃雷圖形成的演算法,是根據你點開的第一個格在哪裡,總之第一個雷總不能在那裡。在點開後萬分之幾秒里形成雷圖,一切都是隨機的,不過有一點對於初級來說有十幾萬分之一的幾率打開3BV=1的圖,也就是說一下就開了。(3BV的意思是贏得這盤掃雷所需要的最少左鍵點擊數,比如一大片的3BV就是1,而一個沒在一大片的邊緣的格的3BV也是1,)也就是說,打開一大片所形成的那些邊緣的格都不算,3BV是目前評價難易程度的最好方法,這也是隨機,初級在1~71,中級大概25~180,高級100~250
『柒』 用LINUX編寫「掃雷」游戲,怎麼做
對於一個大一的學生來說,目測埋棗你的基礎已經不錯了,堅持努力下去應該會有不錯的成就。獨立游戲是個很大的話題,首先先明確想要自己一個人做還是找小團隊一起合作。自己一個人做的話,設計、程序、美術、音樂等等就都得會。如果組團隊做,可以重點攻堅其中1到2個方向。我主要說說技術方面。你在編程方面已經有所積累,至少演算法方面應該是吧,這對於編程來說是個不錯的開始。開發游戲的話,對基本的數據結構和演算法要求還是很高的,再有就是軟體結構的設計,這個需要較長時間的積累,最好多看看其他的游戲類工程是怎麼做的,游戲和那種業務流軟體的一個不同在於,游戲程序對實時性要求很高,會有一些為了性能而出現的不同的代碼模式。最基本的一個東西,編程語言,看你希望的開發平台,不同平台會使用不同的開發語言,這個要熟練掌握(不是能寫演算法、玩具例子那麼簡單就行,需要知道如何用這種語言開發大型工程)。關於開發平台,多說兩句。如果想要自己的程序便於大家在任何平台使用,推薦Web相關的技術,如HTML5/JavaScript(用canvas元素,如果需要GPU加速的底層3D API,canvas有WebGL繪制環境(OpenGL ES 2.0的瀏覽器版))。如果希望更方便開發,Unity3D是個很好的選擇,是個集游戲引擎與運行平台於一體的東西,而且這個東西牛逼的地方在於所有平台都支持(PC、Mobile、Web)。如果開發手機上的原生app,推薦學習cpp以及那個平台上官方語言,這樣可以用cpp開發,然後用官方語言做一個殼。如果是PC上的游戲,還是推薦cpp。另一個就是數學/物理,當然這個要看你要做什麼游戲。基本的東西是幾何相關的東西,基本上是個游戲都用得到。如果有不確定性(絕大部分游戲應該都需要)在裡面,基本的概率分布要深刻的理解。如果要自己做物理效果(碰撞,彈性,形變等),除了需要搞定相關的物理(剛體物理,柔體物理(這個通常很麻煩),流體物理(這個也很麻煩)等),還需要搞定數值計算方法,自己做物理這個水很深,不建議自己做,用現有的物理引擎最好。如果想要做到很好的3D畫面洞液鬧,還需要學習計算機圖形學,這里會有很多的光學,很多的立體幾何,一坨線性代數的東西還有各種形式的積分。而且實時圖形系統的開發對編程能力要求也非常高,除了普通程序的要求以外,還要能掌握高性能的數值密集型的代碼開發(這個對於物理相關的開發也一樣)。另外還需要掌握至少一個GPU加速的圖形介面的使用(OpenGL,Direct3D等)以及對應的shader代碼的編寫。同樣,如果想做到很好的畫面效果,建議用現有的渲染引擎,自己做水也太深。總體上來說,2D游戲和3D游戲所需的技能還有很大差別,2D游戲在技術上的要求相對簡單很多。還有就是,獨立游戲可能有伺服器端得比較少。如果真的需要,這方面的開發相對來說和通常的業務流軟體的服務端比較相似,所以不是太復雜。不過會有很多游戲邏輯需要在服務端處理,多客戶端的信息實時同步可能會成為一個比較有難度的問題。還有就是各種客戶端請求的驗證,反作弊用,這個一開始應該不會涉及到,不扯了。總的來說,游戲開發作為程序開發最難的一種形式之一,技術方面需要非常多的積累,這個需要時間去積累。可以先從那種非常小的小游戲(先是掃雷、貪食蛇這類休閑游戲,然後做塔防類游戲不錯)做起,練手用。基本功扎實了以後可以考慮進入3D。游戲美術方面呢,2D和3D也是很不一樣的。3D游戲的美術很復雜,各種模型網格的創建,各種貼圖紋理的繪制。如果有人物,還需要人物動畫,這又是一大塊。美術我不專業,不多說了,希望哪位專業的來補充一下。2D的相對好很多,只要能畫好畫,基本上就能做了。游戲音樂方面,主要是納罩作曲,用mid的話也不錯,但現在好像這么做的很少了。演奏要看作的曲子的復雜度了。除了音樂還有音效,這個我不懂,不說了。設計嘛,這個是製作游戲的核心。從你的表述來看,應該是玩過不少游戲了,那應該多少能體會到各種游戲的設計模式。把自己的想法,參考現有的一些模式,規劃好,做出來原型。設計這里有一個很重要的細節:開發工具要能盡可能提供高效的迭代方式,游戲的完成度是一點一點打磨出來的,而這個打磨過程的長短很大程度上取決於工具是否好用。
『捌』 能在dev-c++上運行通過的掃雷,貪吃蛇,等小游戲的c語言代碼
#include<bits/stdc++.h>
#include<stdlib.h>
#include<dos.h>
#define LEFT 0x4b00
#define RIGHT 0x4d00
#define DOWN 0x5000
#define UP 0x4800
#define ESC 0x011b
int i,key;
int score=0;
int gamespeed=32000;
struct Food /*食物的結構體*/
{
int x; /*食物的橫坐標*/
int y; /*食物的縱坐標*/
int yes; /*食物是否出現的變數*/
}food;
struct Snack /*蛇的結構體*/
{
int x[N];
int y[N];
int node; /*蛇的節數*/
int direction; /*蛇的方向*/
int life; /*蛇的生命,0活著,1死亡*/
}snake;
void Init(void); /*圖形驅動*/
void Close(void); /*關閉游戲函數*/
void DrawK(void); /*畫圖函數*/
void GameOver(void);/*輸出失敗函數*/
void GamePlay(); /*游戲控制函數 主要程序*/
void PrScore(void); /*分數輸出函數*/
DELAY(char ch)/*調節游戲速度*/
{
if(ch=='3')
{
delay(gamespeed); /*delay是延遲函數*/
}
else if(ch=='2')
{
delay(gamespeed);
}
}
Menu()/*游戲開始菜單*/
{
char ch;
printf("Please choose the gamespeed:\n");
printf("1-Fast 2-Normal 3-Slow\n");
printf("\nPlease Press The numbers..\n");
do
{ch=getch();}
while(ch!='1'&&ch!='2'&&ch!='3');
clrscr();
return(ch);
}
/*主函數*/
void main(void)
{
int ch;
ch=Menu();
Init();
DrawK();
GamePlay(ch);
Close();
}
void Init(void)
{
int gd=DETECT,gm;
initgraph(&gd,&gm,"c:\\tc");
cleardevice();
}
void DrawK(void)
{
setcolor(11);
setlinestyle(SOLID_LINE,0,THICK_WIDTH);
for(i=50;i<=600;i+=10)
{
rectangle(i,40,i+10,49); /*畫出上邊框*/
rectangle(i,451,i+10,460); /*畫出下邊框*/
}
for(i=40;i<=450;i+=10)
{
rectangle(50,i,59,i+10); /*畫出左邊框*/
rectangle(601,i,610,i+10); /*畫出右邊框*/
}
}
void GamePlay(char ch)
{
randomize(); /*隨機數發生器*/
food.yes=1; /*1代表要出現食物,0表示以存在食物*/
snake.life=0;
snake.direction=1;
snake.x[0]=100;snake.y[0]=100;
snake.x[1]=110;snake.y[1]=100;
snake.node=2;
PrScore();
while(1) /*可以重復游戲*/
{
while(!kbhit()) /*在沒有按鍵的情況下蛇自己移動*/
{
if(food.yes==1) /*需要食物*/
{
food.x=rand()%400+60;
food.y=rand()%350+60; /*使用rand函數隨機產生食物坐標*/
while(food.x%10!=0)
food.x++;
while(food.y%10!=0)
food.y++; /*判斷食物是否出現在整格里*/
food.yes=0; /*現在有食物了*/
}
if(food.yes==0) /*有食物了就要顯示出來*/
{
setcolor(GREEN);
rectangle(food.x,food.y,food.x+10,food.y-10);
}
for(i=snake.node-1;i>0;i--) /*貪吃蛇的移動演算法*/
{
snake.x[i]=snake.x[i-1];
snake.y[i]=snake.y[i-1]; /*貪吃蛇的身體移動演算法*/
}
switch(snake.direction) /*貪吃蛇的頭部移動演算法,以此來控制移動*/
{
case 1:snake.x[0]+=10;break;
case 2:snake.x[0]-=10;break;
case 3:snake.y[0]-=10;break;
case 4:snake.y[0]+=10;break;
}
for(i=3;i<snake.node;i++) /*判斷是否頭部與身體相撞*/
{
if(snake.x[i]==snake.x[0]&&snake.y[i]==snake.y[0])
{
GameOver();
snake.life=1;
break;
}
}
/*下面是判斷是否撞到牆壁*/
if(snake.x[0]<55||snake.x[0]>595||snake.y[0]<55||snake.y[0]>455)
{
GameOver();
snake.life=1;
}
if(snake.life==1) /*如果死亡就退出循環*/
break;
if(snake.x[0]==food.x&&snake.y[0]==food.y) /*判斷蛇是否吃到食物*/
{
setcolor(0);
rectangle(food.x,food.y,food.x+10,food.y-10); /*吃的食物後用黑色將食物擦去*/
snake.x[snake.node]=-20;snake.y[snake.node]=-20; /*現把增加的一節放到看不到的地方去*/
snake.node++;
food.yes=1;
score+=10;
PrScore();
}
setcolor(4); /*每次移動後將後面的身體擦去*/
for(i=0;i<snake.node;i++)
rectangle(snake.x[i],snake.y[i],snake.x[i]+10,snake.y[i]-10);
delay(gamespeed);
DELAY(ch);
setcolor(0);
rectangle(snake.x[snake.node-1],snake.y[snake.node-1],snake.x[snake.node-1]+10,snake.y[snake.node-1]-10);
}
if(snake.life==1)
break;
key=bioskey(0); /*接受按鍵*/
if(key==ESC)
break;
else
if(key==UP&&snake.direction!=4)/*判斷是否改變方向*/
snake.direction=3;
else
if(key==RIGHT&&snake.direction!=2)
snake.direction=1;
else
if(key==LEFT&&snake.direction!=1)
snake.direction=2;
else
if(key==DOWN&&snake.direction!=3)
snake.direction=4;
}
}
void GameOver(void)
{
cleardevice();
setcolor(RED);
settextstyle(0,0,4);
outtextxy(200,200,"GAME OVER");
getch();
}
void PrScore(void)
{
char str[10];
setfillstyle(SOLID_FILL,YELLOW);
bar(50,15,220,35);
setcolor(6);
settextstyle(0,0,2);
sprintf(str,"scord:%d",score);
outtextxy(55,20,str);
}
void Close(void)
{
getch();
closegraph();
}