C#大作业源码及课程报告(十五子游戏)


 

大 作 业

(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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值