用c#窗体做五子棋小游戏 :
首先是界面设计,控件一共有4个,1个PictureBox ;1个开始按钮,命名为btnStart;1个重置按钮,命名为btnReset;1个文本框Label,用于显示游戏状态;
2. 新建一个MainSize类用于存放界面上的可能用到的参数,主框体大小520*460,棋盘是一个PictureBox控件,大小401*401,棋盘20行20列,每个格子边长20,棋子直径16。
3. 新建一个ChessBoard类表示棋盘,有一个静态函数DrawBoard,函数代码如下:
class ChessBoard{static readonly Color color = Color.Black;static readonly float penWid = 1.0f;static readonly Pen pen = new Pen(color, penWid);public static void DrawCB(Graphics gra,PictureBox pic){//每排数量int horC = MainSize.CBWid / MainSize.CBGap;//间隔int gap = MainSize.CBGap;Image img = new Bitmap(MainSize.CBWid, MainSize.CBHei);gra = Graphics.FromImage(img);gra.Clear(Color.White);gra.DrawRectangle(pen, 0, 0, MainSize.CBWid, MainSize.CBHei);//画棋盘for (int i = 0; i < horC; i++){gra.DrawLine(pen, 0, i * gap, MainSize.CBWid, i * gap);gra.DrawLine(pen, i * gap, 0, i * gap, MainSize.CBHei);}gra.DrawLine(pen, 0, horC * gap, MainSize.CBWid, horC * gap - 1);gra.DrawLine(pen, horC * gap - 1, 0, horC * gap, MainSize.CBHei);pic.Image = img;}}
4. 新建一个基本类Chess,用来表示棋子,有一个静态函数DrawChess,代码如下:
class Chess{ public static void DrawChess(bool type,PictureBox pic,Graphics graphic,MouseEventArgs e)
//bool型变量用于表示下棋的双方
{graphic = pic.CreateGraphics();Pen pen1 = new Pen(Color.Red, 1);Brush bru1 = new SolidBrush(Color.Red);Pen pen2 = new Pen(Color.Blue, 1);Brush bru2 = new SolidBrush(Color.Blue);int newX = (int)((e.X + MainSize.CBGap / 2) / MainSize.CBGap) * MainSize.CBGap - MainSize.ChessRadious / 2;int newY = (int)((e.Y + MainSize.CBGap / 2) / MainSize.CBGap) * MainSize.CBGap - MainSize.ChessRadious / 2;
//pen1和pen2用于绘制双方的棋子,颜色设置为红蓝
if (type){ graphic.DrawEllipse(pen1, newX, newY, MainSize.ChessRadious, MainSize.ChessRadious);graphic.FillEllipse(bru1, newX, newY, MainSize.ChessRadious, MainSize.ChessRadious); }if (!type){ graphic.DrawEllipse(pen2, newX, newY, MainSize.ChessRadious, MainSize.ChessRadious);graphic.FillEllipse(bru2, newX, newY, MainSize.ChessRadious, MainSize.ChessRadious); }
//整型变量nexX和newY用于表示棋子在棋盘上的坐标,根据四舍五入就近原则落点 graphic.Dispose();
}
}
5. 主程序,一共设置了4个全局变量,Graphics graphic用于画图,bool type用于表示下棋双方,bool start表示游戏是否开始,二维数组ChessBack用于模拟下棋场景并进行计算。 主程序的构造函数对主框体和PictureBox的大小进行初始化,在Form1_Load函数中添加函数InitializeThis()对游戏进行初始化,包括将ChessBack数组全部置0,type设为true,start设为false,绘制棋盘,按键开始的Enabled属性设为true,按键重置设为false。 按键开始和重置的功能较为简单,代码如下:
private void btnStart_Click(object sender, EventArgs e){start = true;label1.Text = "游戏开始!";btnStart.Enabled = false;btnReset.Enabled = true;}
private void btnReset_Click(object sender, EventArgs e){ if (MessageBox.Show("确定要重新开始?", "提示", MessageBoxButtons.YesNo) == DialogResult.Yes){ InitializeThis();}}
6. picturebox的函数,先判断游戏是否开始,否则不会有反应。游戏开始后点击即可落子,并修改ChessBack矩阵,红色为1,蓝色为2,如果已经有棋子则返回,即落子失败。如果棋盘已满但没有分出胜负则弹出平局的提示框并给出提示。之后判断是否分出胜负,添加函数bool Victory(int bx,int by),分出胜负后提示胜利,如果没有则返回。最后换人,type=!type即可,然后修改label的文字表面到哪一方落子了。代码如下。
private void pictureBox1_MouseClick(object sender, MouseEventArgs e){if (start){//在计算矩阵中的位置int bX = (int)((e.X + MainSize.CBGap / 2) / MainSize.CBGap);int bY = (int)((e.Y + MainSize.CBGap / 2) / MainSize.CBGap);//防止在同一个位置落子if (ChessBack[bX, bY] != 0)return;Chess.DrawChess(type, pictureBox1, graphic, e);ChessBack[bX,bY] = type?1:2;//判断棋盘是否满了if (IsFull() && !Victory(bX,bY)){if (MessageBox.Show("游戏结束,平局") == DialogResult.OK)InitializeThis();return;}//判断胜利if (Victory(bX,bY)){string Vic = type ? "红" : "蓝";if (MessageBox.Show(Vic + "方胜利!") == DialogResult.OK)InitializeThis();return;}//换人type = !type;label1.Text = type ? "红方's trun!" : "蓝方's turn!";}elsereturn;}
7. 判断胜负的函数,先写了一个横向的进行测试,如果横向两端的值与当前值相同则变量count++,最后返回count的值,如果>4则表示胜利。但是这个函数运行出错,显示为stackoverflow,但我不知道错误在哪,只好换一种判断方法。后来才想明白两端的值都是0则会溢出,应该判断两端的值是否为1或2而不是当前值。此处借鉴了实验楼网站上的C语言版五子棋的判断胜负方式,从当前落子的矩阵中,横竖斜4个方向任意一个方向有连续5个数的值与当前的值相同则胜利,实现也不复杂,细分为三个函数实现。代码如下:
#region 判断胜利private bool Victory(int bx,int by){if (HorVic(bx, by))return true;if (VerVic(bx, by))return true;if (Vic45(bx, by))return true;elsereturn false;}private bool Vic45(int bx, int by) { int b1 = (bx - 4) > 0 ? bx - 4 : 0;int b2 = (by - 4) > 0 ? by - 4 : 0;//int buttom = b1 > b2 ? b2 : b1;int val = ChessBack[bx, by];for (int i = b1,j=b2; i < 16&&j<16; i++,j++){if (ChessBack[i, j] == val && ChessBack[i + 1, j + 1] == val &&ChessBack[i + 2, j + 2] == val && ChessBack[i + 3, j + 3] == val&& ChessBack[i + 4, j + 4] == val)return true;}for (int i = b1, j = b2; i < 16 && j < 16; i++, j++){if (ChessBack[i, j] == val && ChessBack[i + 1, j - 1] == val &&ChessBack[i + 2, j - 2] == val && ChessBack[i + 3, j - 3] == val&& ChessBack[i - 4, j - 4] == val)return true;}return false;}private bool VerVic(int bx, int by){int buttom = (by - 4) > 0 ? by - 4 : 0;int val = ChessBack[bx, by];for (int i = buttom; i < 16; i++){if (ChessBack[bx, i] == val && ChessBack[bx, i+1] == val &&ChessBack[bx, i+2] == val && ChessBack[bx ,i+3] == val&& ChessBack[bx, i+4] == val)return true;}return false;}private bool HorVic(int bx, int by){int left = (bx-4)>0?bx-4:0;int val = ChessBack[bx,by];for (int i = left; i < 16; i++){if (ChessBack[i, by] == val && ChessBack[i + 1, by] == val &&ChessBack[i + 2, by] == val && ChessBack[i + 3, by] == val&& ChessBack[i + 4, by] == val)return true;}return false;}#endregion
8 .经过测试,没有问题大功告成
楼主要及时采纳加分哦