📄 form1.cs
字号:
private void makeRandomData()
{
Random rand = new Random(); //用于产生雷区分步
int i; //用于标记产生有雷区域的行下标
int j; //用于标记产生有雷区域的列下标
//产生BombNumber个地雷
for( int k = 0; k < BombNumber; k++ )
{
i = rand.Next( 1, 20 ); //产生有雷区域的行下标
j = rand.Next( 1, 20 ); //产生有雷区域的列下标
if( bombs[i,j] == 0xFF ) //表示该区域已经设置有雷,需要重新设置其他区域
k--;
else
bombs[i,j] = 0xFF;
}
//用于计算每个雷区bombs[i,j]附近的地雷数
for( i = 1; i < 21; i ++ )
for( j = 1; j < 21; j++ )
{
//对于每个无雷区域,对其周围8个区域进行监测
if( bombs[i,j] != 0xFF )
{
for( int m = -1; m < 2; m ++ )
for( int n = -1; n < 2; n++ )
{
//如果发现周围有雷区域,bombs[i,j]的值加1
if( bombs[ i + m, j +n ] == 0xFF )
bombs[i,j]++;
}
}
}
}
//对鼠标弹起事件的处理
private void Form1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
//如果游戏可以开始,则开始该游戏,并且开始用计时器计时
if( !timer.Enabled && gameReady && !gOver)
{
timer.Enabled = true;
}
//左键起
if( e.Button == MouseButtons.Left )
{
//触雷,游戏结束
if( this.bombs[arrayX,arrayY] == 0xFF )
{
gameOver();
}
//该雷区无雷,显示附近雷区雷数
else if( bombs[arrayX,arrayY] == 0 )
{
if( bombState[arrayX,arrayY] == 0 )
banging( arrayX, arrayY );
}
//该雷区附近无雷,显示附近所有无雷区
else
{
fillBombArea( eventX, eventY, arrayX, arrayY, 2 );
}
}
//其他键起并且游戏已经开始
else if( e.Button == MouseButtons.Right && gameReady && !gOver)
{
//如果该区域已经判定为有雷区,用户再次用鼠标单击,将状态修改为可能有雷区
if( bombState[arrayX,arrayY] == 0x02 )
{
//fillType为4,有雷区变为可能的有雷区
fillBombArea( eventX, eventY, arrayX, arrayY, 4 );
}
//该区域已标志为可能有雷区域,如果玩家再次用右键单击,将状态改为未判定状态
else if( bombState[arrayX,arrayY] == 0x03 )
{
//fillType为5,转变为未判定区
fillBombArea( eventX, eventY, arrayX, arrayY, 5 );
}
//该区域为未判定作态,如果玩家用右键单击,将作态改为用户判定的有雷区状态
else if( bombState[arrayX,arrayY] == 0 )
{
fillBombArea( eventX, eventY, arrayX, arrayY, 3 );
}
}
}
//游戏结束,向玩家显示所有有雷区域的位置
private void gameOver()
{
int i; //标志行坐标
int j; //标志列坐标
//对于每个有雷区域,用黑色标志
for( i = 1; i < 21; i++ )
for( j = 1; j < 21; j++ )
{
if( bombs[i,j] == 0xFF && bombState[i,j] == 0 )
{
this.fillBombArea( ( i - 1 ) * 20 + 2 , ( j - 1 ) * 20 + 2, i, j, 7 );
}
}
//停止计时器
timer.Enabled = false;
//游戏未开始
gameReady = false;
//游戏已经结束
gOver = true;
}
//玩家开始游戏
private void mnuBegin_Click(object sender, System.EventArgs e)
{
this.replay();
}
//玩家重新开始游戏,对游戏重新进行初始化
private void replay()
{
Refresh();
Pen pen = new Pen( Color.Goldenrod, 4 ); //用于绘制边界
//重新绘制雷区
for( int i = 0; i <= 400; i += 20 )
{
g.DrawLine( pen, 0, i, 400, i );
g.DrawLine( pen, i, 0, i, 400 );
}
//计时器重新置0
time = 0;
//向玩家显示当前时间
lbTime.Text = time.ToString();
//显示本次游戏的地雷个数
lbBombNum.Text = BombNumber.ToString();
//记忆实际剩余地雷个数
rightCheck = BombNumber;
//用户判定的剩余个数
userCheck = BombNumber;
this.btnReplay.Text = "重新开始";
//计时器尚未开始
timer.Enabled = false;
//将地雷数组重新初始化为0
Array.Clear( this.bombs, 0, this.bombs.Length );
//将雷区状态重新初始化为0
Array.Clear( this.bombState, 0, this.bombState.Length );
//产生雷区
makeRandomData();
//初始化完毕,可以开始游戏
gameReady = true;
//游戏尚未结束
gOver = false;
}
//用户点击附近无雷区域,显示所有周围为无雷的区域
private void banging( int x, int y )
{
fillBombArea( ( x - 1) * 20 + 2, ( y - 1 ) * 20 + 2, x, y, 1 );
//处理右方雷区情况
if( x + 1 < 21) //如果不是最右方
{
//如果该区域附近也无雷,则递规
if( bombs[ x + 1, y ] == 0 && bombState[ x + 1, y ] == 0 )
banging( x + 1, y );
//如果该区域附近有雷
else if( bombs[ x + 1, y] < 0xFF && bombState[ x + 1, y ] == 0 )
{
fillBombArea( x * 20 + 2, ( y - 1 ) * 20 + 2, x + 1, y, 2 );
}
}
//对左方雷区的处理
if( x - 1 > 0 ) //如果不是最左方
{
//如果该区域附近也无雷,则递规
if( bombs[ x - 1, y ] == 0 && bombState[ x - 1, y ] == 0 )
banging( x - 1, y );
//如果该区域附近有雷
else if( bombs[ x - 1, y ] < 0xFF && bombState[ x - 1, y ] == 0 )
{
fillBombArea( ( x - 2 ) * 20 + 2, ( y - 1 ) * 20 + 2, x - 1, y, 2 );
}
}
//对上方雷区的处理
if( y - 1 > 0 ) //如果不是最上方
{
//如果该区域附近也无雷,则递规
if( bombs[ x, y - 1] == 0 && bombState[ x, y - 1] == 0 )
banging( x, y -1 );
//如果该区域附近有雷
else if( bombs[ x, y - 1 ] < 0xFF && bombState[ x, y - 1] == 0 )
{
fillBombArea( ( x - 1) * 20 + 2, ( y - 2 ) * 20 + 2, x, y - 1, 2 );
}
}
//对下方雷区的处理
if( y + 1 < 21 ) //如果不是最下方
{
//如果该区域附近也无雷,则递规
if( bombs[ x, y + 1] == 0 && bombState[ x, y + 1] == 0 )
banging( x, y + 1 );
//如果该区域附近有雷
else if( bombs[ x, y + 1 ] < 0xFF && bombState[ x, y + 1] == 0)
{
fillBombArea( ( x - 1) * 20 + 2, y * 20 + 2, x, y + 1, 2 );
}
}
}
//用户选择中级难度
private void mmuMiddle_Click(object sender, System.EventArgs e)
{
BombNumber = 60; //地雷数为60
rightCheck = 60; //实际剩余的地雷数为60
userCheck =60; //用户判定的剩余地雷数为60
lbBombNum.Text = this.BombNumber.ToString(); //向用户显示判定的剩余地雷数
mnuBegenner.Checked = false; //未选定初级
mmuAdvanced.Checked = false; //未选定高级
mmuMiddle.Checked = true; //选定了中级
//重新开始游戏
this.replay();
}
private void mnuBegenner_Click(object sender, System.EventArgs e)
{
BombNumber = 40;
rightCheck = 40;
userCheck = 40;
lbBombNum.Text = this.BombNumber.ToString();
mnuBegenner.Checked = true;
mmuAdvanced.Checked = false;
mmuMiddle.Checked = false;
replay();
}
private void mmuAdvanced_Click(object sender, System.EventArgs e)
{
this.BombNumber = 80;
this.lbBombNum.Text = this.BombNumber.ToString();
this.mnuBegenner.Checked = false;
this.mmuAdvanced.Checked = true;
this.mmuMiddle.Checked = false;
this.rightCheck = 80;
this.userCheck = 80;
this.replay();
}
private void btnReplay_Click(object sender, System.EventArgs e)
{
this.replay();
}
private void timer_Tick(object sender, System.EventArgs e)
{
time++;
this.lbTime.Text = time.ToString();
}
private void menuItem6_Click(object sender, System.EventArgs e)
{
MessageBox.Show("左键点击你认为没有地雷的雷区\n右键点击你认为有雷的雷区\n右键点击标志有雷的雷区后,该区域显示“?”表示不能确定\n右键点击“?”雷区取消判定\n右键点击已经判定的无雷区,如果该雷区附近所有地雷都\n标志过,则自动翻开未判定雷区",
"玩法帮助",MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void menuItem7_Click(object sender, System.EventArgs e)
{
MessageBox.Show(" 游戏名称:飞天扫雷 \n 版本:V1.2 2005-4-11 \n 作者:冯东伟 ", "关于飞天",MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void mmuExit_Click(object sender, System.EventArgs e)
{
this.Close();
}
//雷区填充函数
//xCo表示要填充区域的左上X坐标
//yCo表示要填充区域的左上Y坐标
//xArr表示雷区对应的数组行下标
//yArr表示雷区对应的数组列下标
//fillType表示填充类型
private void fillBombArea( int xCo, int yCo, int xArr, int yArr, int fillType)
{
switch ( fillType )
{
case 1:
{
//附近无雷的无雷区,仅用绿色刷子填充该区域
SolidBrush greenBrush = new SolidBrush( Color.Green ); //绿刷子,用于标志玩家已打开的区域
g.FillRectangle( greenBrush, xCo, yCo, 16, 16 );
bombState[xArr,yArr] = 0x01;
break;
}
case 2: //附近有雷的无雷区,用绿色刷子填充该区域,并显示附近雷区地雷数
{
SolidBrush greenBrush = new SolidBrush( Color.Green ); //绿刷子,用于标志玩家已打开的区域
//用绿色刷子填充太雷区,表示无雷
g.FillRectangle( greenBrush, xCo, yCo, 16, 16 );
SolidBrush stringBrush = new SolidBrush( Color.Yellow ); //灰刷子,用于书写附近雷区地雷数
//显示附近雷区的地雷个数
g.DrawString( bombs[xArr,yArr].ToString(), new Font("Times New Roman",12), stringBrush, xCo, yCo );
//标志该状态已经正确判断为无雷区
bombState[xArr,yArr] = 0x01;
break;
}
case 3: //用户标志的有雷区,仅用蓝色刷子填充该区域
{
SolidBrush blueBrush = new SolidBrush( Color.Blue ); //蓝刷子,用于标志玩家判定有雷区
//用蓝色刷子标志该区域为有雷区
g.FillRectangle( blueBrush, xCo, yCo, 16, 16 );
//将作态改为用户判定的有雷区
bombState[xArr,yArr] = 0x02;
--userCheck;
lbBombNum.Text = userCheck.ToString();
if( bombs[xArr,yArr] == 0xFF )
rightCheck--;
if( rightCheck == 0 )
{
btnReplay.Text = "您赢了!";
gOver = true;
timer.Enabled = false;
}
break;
}
case 4: //用户判定的可能有雷区,用问号标志
{
//由已判定变为不能判定,实际剩余的雷区个数加1
rightCheck ++;
//由已判定变为不能判定,用户判定的雷区剩余个数加1
userCheck++;
//向玩家显示玩家判定的还剩余的地雷个数
lbBombNum.Text = userCheck.ToString();
//显示"?",提醒玩家
SolidBrush stringBrush = new SolidBrush( Color.Yellow ); //灰刷子,用于书写附近雷区地雷数
g.DrawString( "?",new Font("Times New Roman",12), stringBrush, xCo, yCo );
bombState[xArr,yArr] = 0x03;
break;
}
case 5: //用户将该区域设置为未判定区域
{
SolidBrush backBrush = new SolidBrush( Color.FromArgb(255,255,200) ); //背景刷子,用于恢复状态
//用背景刷子填充,回复为未判定状态
g.FillRectangle( backBrush, xCo, yCo, 16, 16 );
//除去显示的"?"
g.DrawString( "?",new Font("Times New Roman",12), backBrush, xCo, yCo );
//将该雷区状态该为未判定状态
bombState[xArr,yArr] = 0;
break;
}
case 6: //用户按下鼠标,用红色提示用户点击的雷区
{
SolidBrush redBrush = new SolidBrush( Color.Red ); //红刷子,用于显示玩家左键按下的雷区
g.FillRectangle( redBrush, xCo, yCo, 16, 16 );
break;
}
case 7: //玩家失败后,用黑色标识所有有雷区域
{
SolidBrush blackBrush = new SolidBrush( Color.Black ); //黑刷子,用于显示玩家左键按下的雷区
g.FillRectangle( blackBrush, xCo, yCo, 16, 16 );
break;
}
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -