五子棋是家喻户晓的游戏,想起那个没有网络游戏,没有只能手机的时代,我和几个差不多大的邻家孩子一起下棋的画面,不禁浮想万千。

记得大二的时候上“面向对象程序设计”课时我就写了个五子棋,但是那个是用VC6里头的MFC写的,个人现在很讨厌这个IDE,尤其是里面一堆的大写字母,真不知道当年我是怎么写出来的。今天,我用VS2008里的C#来重新写这个五子棋,VS2008是个好的IDE,C#是一种好的语言,从这次和以前写的代码量中可以清楚地看到。

时间有限,所以我先写了没有AI的五子棋,即只有人人对战,没有人机对战。

程序的主界面如下(我使用的是WinForm):

 

 

这个主界面是画出来的,主要使用到的库是System.Drawing中的Graphics类的DrawLine方法,关键代码如下:

Graphics g;                         //  画布对象,用于画格子,画棋子等

。。。。

 private void 开始新游戏ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            g = pictureBox1.CreateGraphics();
            for (int i = 0; i <= N; i++)           //画格子
            {
                g.DrawLine(System.Drawing.Pens.Black, 0, 24 * i, pictureBox1.Size.Width, 24 * i);
                g.DrawLine(System.Drawing.Pens.Black, 24 * i, 0, 24 * i, pictureBox1.Size.Height);
            }
            g.Dispose();
        }

其中pictureBox1是主界面里的图像控件,其大小设置为比24*16稍微大些。

接下来是落子的鼠标单击事件,每次落子需要判断是否有一方获得胜利,若是,那么弹出胜利信息,反之,将落子权交给对方。关键的代码如下:

private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
        {
            g = pictureBox1.CreateGraphics();
            int x1, y1, x2, y2;
            x2 = (int)((e.X + 12) / 24);
            y2 = (int)((e.Y + 12) / 24);
            x1 = (x2 * 24) - 12;
            y1 = (y2 * 24) - 12;
            player = new SoundPlayer(Resources.put);
            if (CStatus[x2, y2] != 0) return;
            if (bIsFirst > 0)
            {
                CStatus[x2, y2] = 1;
                g.FillEllipse(new SolidBrush(Color.Black), new Rectangle(x1, y1, 24, 24));
                player.Play();
                if (checks(x2, y2, 1))
                {
                    player = new SoundPlayer(Resources.win);
                    player.Play();
                    MessageBox.Show("黑方胜利!");
                    g.Clear(pictureBox1.BackColor);
                    CStatus = new int[N, N];    //  清空数组,恢复成未下棋的状态
                }
            }
            else
            {
                CStatus[x2, y2] = 2;
                g.FillEllipse(new SolidBrush(Color.Red), new Rectangle(x1, y1, 24, 24));
                player.Play();
                if (checks(x2, y2, 2))
                {
                    player = new SoundPlayer(Resources.win);
                    player.Play();
                    MessageBox.Show("红方胜利!");
                    g.Clear(pictureBox1.BackColor);
                    CStatus = new int[N, N];
                }
            }

            bIsFirst = -bIsFirst;   //  将控制权交给对方
        }

其中部分变量在类中的声明如下:

const int N = 16;                   //  棋盘的行列数
        Graphics g;                         //  画布对象,用于画格子,画棋子等
        int[,] CStatus = new int[N, N];     //  定义一个二维数组,1,2分别表示已下黑棋或白棋的区域,0为棋盘上未下子的区域
        int bIsFirst = 1;                   //  控制哪一方下棋,1为黑方
        SoundPlayer player;

此处需要引入System.Resources和System.Media,前者可以调用资源类中的wav声音文件,而后者是播放wav文件的类库。

落子声音调用语句为:player = new SoundPlayer(Resources.put);

                                        player.Play();

 

 

以下代码是判断哪一方胜利的函数:

        bool checks(int i, int j, int ss)   //  判断哪一方获胜
        {
            for (i = 0; i < N - 5; i++)
            {
                for (j = 0; j < N - 5; j++)
                {
                    //  水平方向5子同色
                    if (CStatus[i, j] == ss && CStatus[i, j + 1] == ss && CStatus[i, j + 2] == ss && CStatus[i, j + 3] == ss && CStatus[i, j + 4] == ss)
                    {
                        return true;
                    }
                    //  竖直方向5子同色
                    else if (CStatus[i, j] == ss && CStatus[i + 1, j] == ss && CStatus[i + 2, j] == ss && CStatus[i + 3, j] == ss && CStatus[i + 4, j] == ss)
                    {
                        return true;
                    }
                    //  对角线1
                    else if (CStatus[i, j] == ss && CStatus[i + 1, j + 1] == ss && CStatus[i + 2, j + 2] == ss && CStatus[i + 3, j + 3] == ss && CStatus[i + 4, j + 4] == ss)
                    {
                        return true;
                    }
                    //  对角线2
                    else if (CStatus[i, N - j - 1] == ss && CStatus[i + 1, N - j - 2] == ss && CStatus[i + 2, N - j - 3] == ss && CStatus[i + 3, N - j - 4] == ss && CStatus[i + 4, N - j - 5] == ss)
                    {
                        return true;
                    }
                    else
                        continue;
                }
            }
            return false;
        }
 

该方法从水平方向、竖直方向以及两个对角方向判断是否有5颗相同颜色的棋子。一种更有效的判断方法是仅仅判断落子处周围是否存在一种胜利棋子的组合(有兴趣的网友可以研究下)。

好了,就写到这,等我把电脑AI加进去之后再更新文章。