大 作 业
(20 -20 学年第 学期)
课程名称: .net编程技术
学生姓名: 杨迁
专业班级: 计算机2班
学 院:信息与电气工程学院
学 号: 2016188056
学生成绩:
任课教师(签字):
一、项目介绍
十五子游戏开始界面,任意键进入十五子游戏,暂停按钮进入屏保。开始是十五个按钮按顺序,排成四排。点击开始按钮进入游戏,十五个按钮顺序被打乱,通过点击空白块周围的任意按钮,将该按钮移动到空白位置。以此来使十五个按钮按照正确的顺序重新排列,游戏获得胜利!
二、设计过程
游戏开始界面是老式windows电脑的屏保,通过Timer组件和五个Lable控件以及随机数对象Random来实现。设置timer的Interval属性,每0.1秒变换lable的BackColor,Left,Top属性,来达到lable背景颜色不断变换,位置移动的效果,当lable移动到窗体边缘就以相反的方向进行移动,从而实现类似屏保的开始界面。
游戏通过两个for循环创建了4*4的按钮数组,在for循环里设置了按钮的大小,坐标等相关属性,然后通过this.Controls.Add方法把按钮添加到窗体。当点击按钮时通过Button btn = sender as Button,来找到被点击的按钮,然后判断该按钮是否与空白按钮相邻,若相邻则把按钮上面的数字和可见性进行交换,从而实现将按钮移动到空白位置的视觉效果。每移动一次就判断按钮顺序是否正确,若正确则提示成功。为了防止玩家多次移动仍不能成功,右下角的按钮通过Controls.Remove方法删除所有按钮,然后重新创建来实现对所有按钮进行排序。
暂停功能也是通过timer组件,用g.DrawEllipse不停的在窗口绘制大小依次变大的圆来实现一个动态变换的效果。
三、源代码
开始界面(LBWNB.cs)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace MoveBlock
{
public partial class LBWNB : Form
{
public LBWNB()
{
InitializeComponent();
}
int deltX = 10;
int deltY = 8;
int deltX1 = -10;
int deltY1 = -7;
int deltX2 = -6;
int deltY2 = 11;
int deltX3 = -11;
int deltY3 = -9;
int deltX4 = 7;
int deltY4 = -13;
Random rnd = new Random();
private void timer1_Tick(object sender, EventArgs e)
{
this.label1.BackColor = Color.FromArgb(rnd.Next(255), rnd.Next(255), rnd.Next(255));
this.label1.Left += deltX;
this.label1.Top += deltY;
if (this.label1.Left < 0 || this.label1.Left + this.label1.Width > this.Width)
deltX = -deltX;
if (this.label1.Top < 0 || this.label1.Top + this.label1.Height > this.Height)
deltY = -deltY;
this.label2.BackColor = Color.FromArgb(rnd.Next(255), rnd.Next(255), rnd.Next(255));
this.label2.Left += deltX1;
this.label2.Top += deltY1;
if (this.label2.Left < 0 || this.label2.Left + this.label2.Width > this.Width)
deltX1 = -deltX1;
if (this.label2.Top < 0 || this.label2.Top + this.label2.Height > this.Height)
deltY1 = -deltY1;
this.label3.BackColor = Color.FromArgb(rnd.Next(255), rnd.Next(255), rnd.Next(255));
this.label3.Left += deltX2;
this.label3.Top += deltY2;
if (this.label3.Left < 0 || this.label3.Left + this.label3.Width > this.Width)
deltX2 = -deltX2;
if (this.label3.Top < 0 || this.label3.Top + this.label3.Height > this.Height)
deltY2 = -deltY2;
this.label4.BackColor = Color.FromArgb(rnd.Next(255), rnd.Next(255), rnd.Next(255));
this.label4.Left += deltX3;
this.label4.Top += deltY3;
if (this.label4.Left < 0 || this.label4.Left + this.label4.Width > this.Width)
deltX3 = -deltX3;
if (this.label4.Top < 0 || this.label4.Top + this.label4.Height > this.Height)
deltY3 = -deltY3;
this.label5.BackColor = Color.FromArgb(rnd.Next(255), rnd.Next(255), rnd.Next(255));
this.label5.Left += deltX4;
this.label5.Top += deltY4;
if (this.label5.Left < 0 || this.label5.Left + this.label5.Width > this.Width)
deltX4 = -deltX4;
if (this.label5.Top < 0 || this.label5.Top + this.label5.Height > this.Height)
deltY4 = -deltY4;
}
private void LBWNB_KeyDown(object sender, KeyEventArgs e)
{
this.Close();
}
private void label4_Click(object sender, EventArgs e)
{
}
private void label5_Click(object sender, EventArgs e)
{
}
private void label2_Click(object sender, EventArgs e)
{
}
private void label9_Click(object sender, EventArgs e)
{
}
}
}
游戏界面(Form1.cs)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace MoveBlock
{
public partial class Form1 : Form
{
public Form1()
{
LBWNB lBWNB = new LBWNB();
lBWNB.ShowDialog();
InitializeComponent();
}
const int N = 4; //按钮的行数和列数
Button[,]buttons= new Button[N,N]; //按钮的二维数组
bool moveOk = false; //是否点击了开始按钮
private void Form1_Load(object sender, EventArgs e)
{
//在窗体加载的时候产生所有按钮
GenerateAllButtons();
}
private void button1_Click(object sender, EventArgs e)
{
if (moveOk == true && MessageBox.Show("是否重新开始 ?", "Warning", MessageBoxButtons.YesNo)
== System.Windows.Forms.DialogResult.No)
goto end;
else
{
label1.Visible = false;
label2.Visible = false;
moveOk = true;
}
//点击按钮的时候打乱所有按钮
Shuffle();
end: ;
}
//打乱顺序
void Shuffle()
{
//多次随机交换两个按钮
Random rnd = new Random();
for (int i = 0; i < 100; i++)
{
//循环随机交换100次
int a = rnd.Next(N);
int b = rnd.Next(N);
int c = rnd.Next(N);
int d = rnd.Next(N);
Swap(buttons[a, b], buttons[c, d]);
}
}
void Swap(Button btna, Button btnb)
{
//把按钮上面的数字和可见性进行交换,从而实现视觉上的交换
string t = btna.Text;
btna.Text = btnb.Text;
btnb.Text = t;
bool v = btna.Visible;
btna.Visible = btnb.Visible;
btnb.Visible = v;
}
void GenerateAllButtons()
{
int x0 = 88, y0 = 38; //按钮相对于左上角的坐标
int w = 45, d = 50; //按钮的宽度(width)为45,两个按钮之间的距离(distance)为50
for(int r = 0; r < N; r++)
{
//行数(row)
for(int c = 0; c < N; c++)
{
//列数(column)
int num = r * N + c;
Button btn = new Button();
btn.Text = (num+1).ToString(); //加一是为了不从0开始
btn.Top = y0 + r * d; //设置按钮的坐标
btn.Left = x0 + c * d;
btn.Width = w; //设置按钮的大小
btn.Height = w;
btn.Visible = true; //每一个按钮刚出来时都是可见的
btn.Tag = r * N + c; //用来记录每个按钮所在行列位置
//注册事件
btn.Click += Btn_Click;
buttons[r, c] = btn; //放到数组中
this.Controls.Add(btn); //把按钮放到界面上
}
}
buttons[N - 1,N-1].Visible = false; //最后一个按钮不可见
}
//按钮块点击事件处理
private void Btn_Click(object sender, EventArgs e)
{
if (moveOk)//如果点击了开始按钮
{
Button btn = sender as Button; //当前点中的按钮
Button blank = FindHiddenButton(); //找到空白按钮
if (IsNeighbor(btn, blank))
{
//如果与空白块相邻则交换
Swap(btn, blank);
blank.Focus();
}
if (ResultIsOk())
{
MessageBox.Show("恭喜恭喜!");
}
}
}
//找到空白按钮
Button FindHiddenButton()
{
for (int r = 0; r < N; r++)
{
for(int c = 0; c < N; c++)
{
if (!buttons[r, c].Visible)
return buttons[r, c];
}
}
return null;
}
//检查是否相邻
bool IsNeighbor(Button btna,Button btnb)
{
int a = (int)btna.Tag; //Tag中记录的有行列位置
int b = (int)btnb.Tag;
int r1 = a / N, c1 = a % N;
int r2 = b / N, c2 = b % N; //r1表示按钮所在行数,r2表示按钮所在列数
if (r1 == r2 && (Math.Abs(c2 - c1) == 1) || //左右相邻
c1 == c2 && (Math.Abs(r1 - r2) == 1)) //上下相邻
return true;
return false;
}
//检查是否完成
bool ResultIsOk()
{
for(int r = 0; r < N; r++)
{
for(int c = 0; c < N; c++)
{
if (buttons[r, c].Text != (r * N + c+1).ToString())
//有一个不正确即未完成
return false;
}
}
return true;
}
void Attack()
{
for (int r = 0; r < N; r++)
{
for (int c = 0; c < N; c++)
{
buttons[r, c].Text = (r * N + c + 1).ToString();
}
}
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
//Point ms = MousePosition;
//this.label1.Text = string.Format("{0}:{1}", ms.X, ms.Y);
}
private void button2_Click(object sender, EventArgs e)
{
Suspend suspend = new Suspend();
suspend.ShowDialog();
}
private void btnAttack_Click(object sender, EventArgs e)
{
if (moveOk)
{
for (int r = 0; r < N; r++)
{
for (int c = 0; c < N; c++)
{
Controls.Remove(buttons[r, c]);
}
}
GenerateAllButtons();
MessageBox.Show("作弊成功! 任意移动按钮查看效果!");
}
}
}
}
暂停(Suspend.cs)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace MoveBlock
{
public partial class Suspend : Form
{
public Suspend()
{
InitializeComponent();
}
Random random = new Random();
Color getRandomColor()
{
return Color.FromArgb(random.Next(256), random.Next(256),
random.Next(256));
}
private void timer1_Tick(object sender, EventArgs e)
{
Graphics g = this.CreateGraphics();
int x0 = this.Width / 2;
int y0 = this.Height / 2;
for (int r = 0; r < this.Width / 2 + 85; r += 3)
{
g.DrawEllipse(new Pen(getRandomColor(), 20),
//椭圆左上角的x坐标
x0 - r, y0 - r, r * 2, r * 2);
}
}
private void Suspend_KeyDown(object sender, KeyEventArgs e)
{
this.Close();
}
}
}
四、使用说明
游戏开始界面
任意按键进入游戏
点击开始按钮,开始游戏
点击空白块周围的按钮进行移动,体验游戏
点击暂停按钮,暂停游戏
游戏成功!
五、总结
之前相同的控件一直都是从工具栏拖到窗体,非常费时和费力。通过上网查询发现在创建多个类似按钮的时候,可以通过循环函数创建按钮,然后通过this.Controls.Add方法把按钮添加到窗口,这样就可以避免拖多个相同的控件到界面上,这个感觉非常有用。还有就是通过Timer组件可以实现很多不断变化的效果,唯一的缺点就是很耗内存。通过十五子游戏,让我更加体会到了写代码时要细心,很可能一个细微的错误,因为刚开始的不注意,使后来找错误浪费了大量的时间。
教师评价:学习态度: 端正□ 一般□ 较差□学习纪律:好□ 较好□ 一般□ 较差□出勤情况: 好□ 一般□ 较差□实习任务完成情况: 优秀□ 好□ 一般□ 较差□报告完成情况: 优秀□ 好□ 一般□ 较差□动手能力: 强□ 较强□ 一般□ 较差□团队精神: 好□ 一般□ 较差□创新意识: 强□ 一般□ 无□其他:成绩:教师签字:年 月 日
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/m0_66999594/article/details/139582370