C# 五子棋小游戏源码(人机对战)

C#五子棋小游戏实现,包含人机对战功能,使用Windows Forms开发

源码

1. 主窗体代码 (FrmGobang.cs)

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Media;

namespace GobangGame
{
    public partial class FrmGobang : Form
    {
        // 游戏常量
        private const int BoardSize = 15; // 15x15棋盘
        private const int CellSize = 40;  // 每个格子大小
        private const int PieceRadius = 18; // 棋子半径
        private const int Margins = 30;   // 边距
        
        // 游戏状态
        private int[,] board; // 0:空, 1:黑棋, 2:白棋
        private bool isBlackTurn; // 是否黑棋回合
        private bool gameOver;   // 游戏是否结束
        private int winner;     // 0:无, 1:黑棋胜, 2:白棋胜
        
        // AI相关
        private bool aiMode;     // 是否AI模式
        private bool aiThinking;  // AI是否正在思考
        private Random random = new Random();
        
        // 音效
        private SoundPlayer placeSound;
        private SoundPlayer winSound;
        private SoundPlayer drawSound;
        
        // 绘图相关
        private Pen boardPen = new Pen(Color.FromArgb(150, 100, 50), 2);
        private Pen gridPen = new Pen(Color.FromArgb(180, 140, 60), 1);
        private SolidBrush blackBrush = new SolidBrush(Color.Black);
        private SolidBrush whiteBrush = new SolidBrush(Color.White);
        private SolidBrush highlightBrush = new SolidBrush(Color.FromArgb(255, 0, 0, 0));
        private Font statusFont = new Font("微软雅黑", 12, FontStyle.Bold);
        
        public FrmGobang()
        {
            InitializeComponent();
            InitializeGame();
            InitializeSounds();
        }
        
        private void InitializeGame()
        {
            // 初始化棋盘
            board = new int[BoardSize, BoardSize];
            isBlackTurn = true;
            gameOver = false;
            winner = 0;
            aiMode = true; // 默认AI模式
            aiThinking = false;
            
            // 设置窗体
            this.DoubleBuffered = true;
            this.ClientSize = new Size(BoardSize * CellSize + 2 * Margins, 
                                     BoardSize * CellSize + 2 * Margins + 50);
            this.Text = "五子棋 - 人机对战";
            this.BackColor = Color.FromArgb(220, 179, 92);
            this.Paint += FrmGobang_Paint;
            this.MouseClick += FrmGobang_MouseClick;
            this.FormClosing += FrmGobang_FormClosing;
            
            // 添加控制按钮
            AddControlButtons();
        }
        
        private void AddControlButtons()
        {
            // 重新开始按钮
            Button btnRestart = new Button
            {
                Text = "重新开始",
                Size = new Size(100, 35),
                Location = new Point(Margins, BoardSize * CellSize + Margins + 10),
                BackColor = Color.FromArgb(70, 130, 180),
                ForeColor = Color.White,
                FlatStyle = FlatStyle.Flat
            };
            btnRestart.Click += (s, e) => RestartGame();
            this.Controls.Add(btnRestart);
            
            // AI模式切换按钮
            Button btnToggleAI = new Button
            {
                Text = "切换双人模式",
                Size = new Size(120, 35),
                Location = new Point(Margins + 110, BoardSize * CellSize + Margins + 10),
                BackColor = Color.FromArgb(60, 179, 113),
                ForeColor = Color.White,
                FlatStyle = FlatStyle.Flat
            };
            btnToggleAI.Click += (s, e) => ToggleAIMode();
            this.Controls.Add(btnToggleAI);
            
            // 难度选择
            ComboBox cmbDifficulty = new ComboBox
            {
                DropDownStyle = ComboBoxStyle.DropDownList,
                Items = { "简单", "中等", "困难" },
                SelectedIndex = 1,
                Size = new Size(80, 30),
                Location = new Point(Margins + 240, BoardSize * CellSize + Margins + 12)
            };
            cmbDifficulty.SelectedIndexChanged += (s, e) => DifficultyChanged(cmbDifficulty.SelectedIndex);
            this.Controls.Add(cmbDifficulty);
            
            Label lblDifficulty = new Label
            {
                Text = "难度:",
                AutoSize = true,
                Location = new Point(Margins + 210, BoardSize * CellSize + Margins + 15),
                ForeColor = Color.Brown,
                Font = new Font("微软雅黑", 9)
            };
            this.Controls.Add(lblDifficulty);
        }
        
        private void InitializeSounds()
        {
            try
            {
                // 在实际应用中,替换为实际的音效文件路径
                placeSound = new SoundPlayer(Properties.Resources.place);
                winSound = new SoundPlayer(Properties.Resources.win);
                drawSound = new SoundPlayer(Properties.Resources.draw);
            }
            catch
            {
                // 如果没有音效文件,忽略错误
            }
        }
        
        private void PlaySound(SoundPlayer player)
        {
            try
            {
                player?.Play();
            }
            catch
            {
                // 忽略播放错误
            }
        }
        
        private void FrmGobang_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            g.SmoothingMode = SmoothingMode.AntiAlias;
            
            // 绘制棋盘背景
            g.FillRectangle(new SolidBrush(Color.FromArgb(220, 179, 92)), 
                          0, 0, this.ClientSize.Width, this.ClientSize.Height);
            
            // 绘制棋盘网格
            DrawBoard(g);
            
            // 绘制棋子
            DrawPieces(g);
            
            // 绘制状态信息
            DrawStatus(g);
        }
        
        private void DrawBoard(Graphics g)
        {
            // 绘制外边框
            int boardWidth = BoardSize * CellSize;
            int boardHeight = BoardSize * CellSize;
            Rectangle boardRect = new Rectangle(Margins, Margins, boardWidth, boardHeight);
            g.DrawRectangle(boardPen, boardRect);
            
            // 绘制网格线
            for (int i = 0; i < BoardSize; i++)
            {
                // 横线
                g.DrawLine(gridPen, 
                          Margins, Margins + i * CellSize, 
                          Margins + boardWidth - CellSize, Margins + i * CellSize);
                
                // 竖线
                g.DrawLine(gridPen, 
                          Margins + i * CellSize, Margins, 
                          Margins + i * CellSize, Margins + boardHeight - CellSize);
            }
            
            // 绘制天元和星位
            int starRadius = 4;
            int[] starPositions = { 3, 7, 11 }; // 15x15棋盘的星位位置
            
            foreach (int x in starPositions)
            {
                foreach (int y in starPositions)
                {
                    int px = Margins + x * CellSize;
                    int py = Margins + y * CellSize;
                    g.FillEllipse(blackBrush, px - starRadius, py - starRadius, 
                                 starRadius * 2, starRadius * 2);
                }
            }
        }
        
        private void DrawPieces(Graphics g)
        {
            for (int row = 0; row < BoardSize; row++)
            {
                for (int col = 0; col < BoardSize; col++)
                {
                    if (board[row, col] != 0)
                    {
                        int x = Margins + col * CellSize;
                        int y = Margins + row * CellSize;
                        
                        // 绘制棋子阴影
                        g.FillEllipse(Brushes.Gray, x - PieceRadius + 2, y - PieceRadius + 2, 
                                     PieceRadius * 2, PieceRadius * 2);
                        
                        // 绘制棋子
                        Brush brush = board[row, col] == 1 ? blackBrush : whiteBrush;
                        g.FillEllipse(brush, x - PieceRadius, y - PieceRadius, 
                                     PieceRadius * 2, PieceRadius * 2);
                        
                        // 绘制棋子边框
                        g.DrawEllipse(Pens.Black, x - PieceRadius, y - PieceRadius, 
                                     PieceRadius * 2, PieceRadius * 2);
                        
                        // 如果是最后一步,绘制高亮标记
                        if (gameOver && (row == lastMoveRow && col == lastMoveCol))
                        {
                            g.FillEllipse(highlightBrush, x - 4, y - 4, 8, 8);
                        }
                    }
                }
            }
        }
        
        private int lastMoveRow = -1, lastMoveCol = -1;
        
        private void DrawStatus(Graphics g)
        {
            string status;
            if (gameOver)
            {
                if (winner == 1) status = "游戏结束: 黑棋胜利!";
                else if (winner == 2) status = "游戏结束: 白棋胜利!";
                else status = "游戏结束: 平局!";
            }
            else
            {
                if (aiMode && !isBlackTurn) status = "电脑思考中...";
                else status = $"当前回合: {(isBlackTurn ? "黑棋" : "白棋")}";
            }
            
            // 绘制状态背景
            int statusWidth = 300;
            int statusHeight = 40;
            int statusX = (this.ClientSize.Width - statusWidth) / 2;
            int statusY = Margins + BoardSize * CellSize + 5;
            
            g.FillRectangle(new SolidBrush(Color.FromArgb(240, 240, 200)), 
                          statusX, statusY, statusWidth, statusHeight);
            g.DrawRectangle(Pens.Brown, statusX, statusY, statusWidth, statusHeight);
            
            // 绘制状态文本
            g.DrawString(status, statusFont, Brushes.Brown, 
                        statusX + 10, statusY + 10);
        }
        
        private void FrmGobang_MouseClick(object sender, MouseEventArgs e)
        {
            if (gameOver || aiThinking) return;
            if (aiMode && !isBlackTurn) return; // AI模式下,电脑回合不响应点击
            
            // 计算点击的棋盘位置
            int col = (e.X - Margins + CellSize / 2) / CellSize;
            int row = (e.Y - Margins + CellSize / 2) / CellSize;
            
            // 检查点击是否在棋盘内
            if (row >= 0 && row < BoardSize && col >= 0 && col < BoardSize)
            {
                // 如果该位置为空,则放置棋子
                if (board[row, col] == 0)
                {
                    PlacePiece(row, col);
                }
            }
        }
        
        private void PlacePiece(int row, int col)
        {
            // 放置棋子
            board[row, col] = isBlackTurn ? 1 : 2;
            lastMoveRow = row;
            lastMoveCol = col;
            PlaySound(placeSound);
            
            // 检查是否获胜
            if (CheckWin(row, col))
            {
                gameOver = true;
                winner = isBlackTurn ? 1 : 2;
                PlaySound(winSound);
            }
            // 检查是否平局
            else if (IsBoardFull())
            {
                gameOver = true;
                winner = 0;
                PlaySound(drawSound);
            }
            else
            {
                // 切换玩家
                isBlackTurn = !isBlackTurn;
                
                // 如果是AI模式且轮到白棋(电脑)
                if (aiMode && !isBlackTurn && !gameOver)
                {
                    aiThinking = true;
                    this.Invalidate(); // 重绘以显示"思考中"状态
                    Application.DoEvents(); // 处理UI事件
                    
                    // 延迟一下,让玩家看到状态变化
                    System.Threading.Thread.Sleep(500);
                    
                    // 执行AI走棋
                    AIMove();
                    aiThinking = false;
                }
            }
            
            this.Invalidate(); // 重绘界面
        }
        
        private void AIMove()
        {
            // 根据难度选择AI算法
            int difficulty = 1; // 默认中等难度
            if (this.Controls[3] is ComboBox cmb) // 获取难度选择框
            {
                difficulty = cmb.SelectedIndex;
            }
            
            int[] move = null;
            
            switch (difficulty)
            {
                case 0: // 简单
                    move = GetRandomMove();
                    break;
                case 1: // 中等
                    move = GetMediumMove();
                    break;
                case 2: // 困难
                    move = GetHardMove();
                    break;
            }
            
            if (move != null)
            {
                PlacePiece(move[0], move[1]);
            }
        }
        
        private int[] GetRandomMove()
        {
            List<int[]> emptyCells = new List<int[]>();
            
            for (int row = 0; row < BoardSize; row++)
            {
                for (int col = 0; col < BoardSize; col++)
                {
                    if (board[row, col] == 0)
                    {
                        emptyCells.Add(new int[] { row, col });
                    }
                }
            }
            
            if (emptyCells.Count > 0)
            {
                return emptyCells[random.Next(emptyCells.Count)];
            }
            
            return null;
        }
        
        private int[] GetMediumMove()
        {
            // 80%概率使用中等AI,20%概率使用随机走法
            if (random.Next(100) < 80)
            {
                return GetDefensiveMove();
            }
            return GetRandomMove();
        }
        
        private int[] GetHardMove()
        {
            // 优先使用中等AI
            int[] move = GetDefensiveMove();
            if (move != null) return move;
            
            // 其次使用随机走法
            return GetRandomMove();
        }
        
        private int[] GetDefensiveMove()
        {
            // 1. 检查电脑是否能立即获胜
            int[] winMove = FindWinningMove(2); // 2代表白棋(电脑)
            if (winMove != null) return winMove;
            
            // 2. 阻止玩家获胜
            int[] blockMove = FindWinningMove(1); // 1代表黑棋(玩家)
            if (blockMove != null) return blockMove;
            
            // 3. 尝试占据中心位置
            int center = BoardSize / 2;
            if (board[center, center] == 0)
            {
                return new int[] { center, center };
            }
            
            // 4. 尝试占据星位
            int[] starPositions = { 3, 7, 11 };
            foreach (int r in starPositions)
            {
                foreach (int c in starPositions)
                {
                    if (board[r, c] == 0)
                    {
                        return new int[] { r, c };
                    }
                }
            }
            
            // 5. 随机选择
            return GetRandomMove();
        }
        
        private int[] FindWinningMove(int player)
        {
            for (int row = 0; row < BoardSize; row++)
            {
                for (int col = 0; col < BoardSize; col++)
                {
                    if (board[row, col] == 0)
                    {
                        // 模拟落子
                        board[row, col] = player;
                        
                        // 检查是否获胜
                        bool win = CheckWin(row, col);
                        
                        // 撤销落子
                        board[row, col] = 0;
                        
                        if (win)
                        {
                            return new int[] { row, col };
                        }
                    }
                }
            }
            return null;
        }
        
        private bool CheckWin(int row, int col)
        {
            int player = board[row, col];
            int count;
            
            // 检查水平方向
            count = 1;
            // 向左检查
            for (int c = col - 1; c >= 0 && board[row, c] == player; c--) count++;
            // 向右检查
            for (int c = col + 1; c < BoardSize && board[row, c] == player; c++) count++;
            if (count >= 5) return true;
            
            // 检查垂直方向
            count = 1;
            // 向上检查
            for (int r = row - 1; r >= 0 && board[r, col] == player; r--) count++;
            // 向下检查
            for (int r = row + 1; r < BoardSize && board[r, col] == player; r++) count++;
            if (count >= 5) return true;
            
            // 检查左上-右下对角线
            count = 1;
            // 左上检查
            for (int r = row - 1, c = col - 1; r >= 0 && c >= 0 && board[r, c] == player; r--, c--) count++;
            // 右下检查
            for (int r = row + 1, c = col + 1; r < BoardSize && c < BoardSize && board[r, c] == player; r++, c++) count++;
            if (count >= 5) return true;
            
            // 检查右上-左下对角线
            count = 1;
            // 右上检查
            for (int r = row - 1, c = col + 1; r >= 0 && c < BoardSize && board[r, c] == player; r--, c++) count++;
            // 左下检查
            for (int r = row + 1, c = col - 1; r < BoardSize && c >= 0 && board[r, c] == player; r++, c--) count++;
            if (count >= 5) return true;
            
            return false;
        }
        
        private bool IsBoardFull()
        {
            for (int row = 0; row < BoardSize; row++)
            {
                for (int col = 0; col < BoardSize; col++)
                {
                    if (board[row, col] == 0)
                    {
                        return false;
                    }
                }
            }
            return true;
        }
        
        private void RestartGame()
        {
            board = new int[BoardSize, BoardSize];
            isBlackTurn = true;
            gameOver = false;
            winner = 0;
            lastMoveRow = -1;
            lastMoveCol = -1;
            aiThinking = false;
            this.Invalidate();
        }
        
        private void ToggleAIMode()
        {
            aiMode = !aiMode;
            Button btn = this.Controls[1] as Button;
            if (btn != null)
            {
                btn.Text = aiMode ? "切换双人模式" : "切换AI模式";
            }
            RestartGame();
        }
        
        private void DifficultyChanged(int index)
        {
            // 难度改变时重新开始游戏
            RestartGame();
        }
        
        private void FrmGobang_FormClosing(object sender, FormClosingEventArgs e)
        {
            // 释放资源
            boardPen.Dispose();
            gridPen.Dispose();
            blackBrush.Dispose();
            whiteBrush.Dispose();
            highlightBrush.Dispose();
            statusFont.Dispose();
            placeSound?.Dispose();
            winSound?.Dispose();
            drawSound?.Dispose();
        }
    }
}

2. 程序入口 (Program.cs)

using System;
using System.Windows.Forms;

namespace GobangGame
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new FrmGobang());
        }
    }
}

3. 资源文件 (Resources.resx)

在项目中添加资源文件,包含以下音效文件(可选):

  • place.wav - 落子音效
  • win.wav - 胜利音效
  • draw.wav - 平局音效

如果没有音效文件,可以删除相关代码。

参考代码 C# 五子棋小游戏源码(人机对战) www.youwenfan.com/contentcnt/39628.html

功能特点

1. 游戏功能

  • 15×15标准五子棋棋盘
  • 人机对战模式(默认)
  • 双人模式(可切换)
  • 三种AI难度级别(简单、中等、困难)
  • 胜负判定(五子连珠)
  • 平局判定(棋盘已满)
  • 重新开始功能

2. 智能AI

  • 简单模式:随机落子
  • 中等模式:80%概率使用防御策略,20%概率随机落子
  • 困难模式:优先使用防御策略,其次随机落子
  • 防御策略包括:
    • 尝试立即获胜
    • 阻止玩家获胜
    • 优先占据中心位置
    • 优先占据星位

3. 用户界面

  • 美观的木质纹理棋盘
  • 立体感棋子设计
  • 状态显示区域
  • 控制按钮(重新开始、模式切换、难度选择)
  • 最后落子位置高亮显示
  • 游戏状态提示(当前回合、思考中、胜负结果)

4. 其他特性

  • 落子音效
  • 胜利/平局音效
  • 双缓冲绘图(无闪烁)
  • 响应式设计
  • 资源自动释放

使用说明

1. 运行游戏

  1. 创建新的Windows Forms应用程序项目
  2. 将上述代码复制到相应文件中
  3. 添加资源文件(可选)
  4. 运行程序

2. 游戏操作

  • 落子:在棋盘上点击空白位置放置棋子
  • 重新开始:点击"重新开始"按钮
  • 切换模式:点击"切换双人模式"按钮
  • 选择难度:从下拉框中选择AI难度

3. 游戏规则

  • 黑棋先行,白棋后行
  • 在横、竖或斜方向先连成五子者获胜
  • 棋盘填满未分胜负则为平局

扩展功能建议

1. 添加悔棋功能

// 在类中添加
private Stack<Point> moveHistory = new Stack<Point>();

// 在PlacePiece方法中记录落子
moveHistory.Push(new Point(row, col));

// 添加悔棋按钮
Button btnUndo = new Button
{
    Text = "悔棋",
    Size = new Size(80, 35),
    Location = new Point(Margins + 360, BoardSize * CellSize + Margins + 10),
    BackColor = Color.FromArgb(205, 133, 63),
    ForeColor = Color.White,
    FlatStyle = FlatStyle.Flat
};
btnUndo.Click += (s, e) => UndoMove();
this.Controls.Add(btnUndo);

// 悔棋方法
private void UndoMove()
{
    if (gameOver || moveHistory.Count == 0) return;
    
    Point lastMove = moveHistory.Pop();
    board[lastMove.X, lastMove.Y] = 0;
    isBlackTurn = !isBlackTurn; // 回到上一步的玩家
    gameOver = false;
    winner = 0;
    
    this.Invalidate();
}

2. 添加计时器

// 在类中添加
private System.Windows.Forms.Timer gameTimer;
private int blackTime = 0;
private int whiteTime = 0;
private bool timerRunning = false;

// 在InitializeGame中初始化
gameTimer = new System.Windows.Forms.Timer();
gameTimer.Interval = 1000; // 1秒
gameTimer.Tick += GameTimer_Tick;

// 计时器方法
private void GameTimer_Tick(object sender, EventArgs e)
{
    if (isBlackTurn)
        blackTime++;
    else
        whiteTime++;
    this.Invalidate();
}

// 在开始游戏时启动计时器
private void StartTimer()
{
    blackTime = 0;
    whiteTime = 0;
    timerRunning = true;
    gameTimer.Start();
}

// 在DrawStatus中添加计时显示
string timeInfo = $"黑棋: {blackTime}s  白棋: {whiteTime}s";
g.DrawString(timeInfo, statusFont, Brushes.Blue, statusX + 10, statusY + 30);

3. 添加保存/加载功能

// 保存游戏
private void SaveGame(string fileName)
{
    using (System.IO.StreamWriter writer = new System.IO.StreamWriter(fileName))
    {
        // 保存棋盘状态
        for (int row = 0; row < BoardSize; row++)
        {
            for (int col = 0; col < BoardSize; col++)
            {
                writer.Write(board[row, col]);
            }
            writer.WriteLine();
        }
        
        // 保存游戏状态
        writer.WriteLine(isBlackTurn ? "1" : "2");
        writer.WriteLine(gameOver ? "1" : "0");
        writer.WriteLine(winner);
        writer.WriteLine(aiMode ? "1" : "0");
    }
}

// 加载游戏
private void LoadGame(string fileName)
{
    try
    {
        using (System.IO.StreamReader reader = new System.IO.StreamReader(fileName))
        {
            // 加载棋盘状态
            for (int row = 0; row < BoardSize; row++)
            {
                string line = reader.ReadLine();
                for (int col = 0; col < BoardSize; col++)
                {
                    board[row, col] = int.Parse(line[col].ToString());
                }
            }
            
            // 加载游戏状态
            isBlackTurn = reader.ReadLine() == "1";
            gameOver = reader.ReadLine() == "1";
            winner = int.Parse(reader.ReadLine());
            aiMode = reader.ReadLine() == "1";
            
            // 更新UI
            Button btn = this.Controls[1] as Button;
            if (btn != null) btn.Text = aiMode ? "切换双人模式" : "切换AI模式";
            
            this.Invalidate();
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show($"加载游戏失败: {ex.Message}");
    }
}

4. 添加更多AI算法

// 极小化极大算法(Minimax)
private int Minimax(int depth, bool isMaximizing, int alpha, int beta)
{
    // 检查终止条件
    if (depth == 0 || gameOver)
    {
        return EvaluateBoard();
    }
    
    if (isMaximizing)
    {
        int maxEval = int.MinValue;
        foreach (var move in GetPossibleMoves())
        {
            // 模拟落子
            board[move[0], move[1]] = 2; // 电脑执白
            
            // 递归评估
            int eval = Minimax(depth - 1, false, alpha, beta);
            
            // 撤销落子
            board[move[0], move[1]] = 0;
            
            maxEval = Math.Max(maxEval, eval);
            alpha = Math.Max(alpha, eval);
            if (beta <= alpha) break;
        }
        return maxEval;
    }
    else
    {
        int minEval = int.MaxValue;
        foreach (var move in GetPossibleMoves())
        {
            // 模拟落子
            board[move[0], move[1]] = 1; // 玩家执黑
            
            // 递归评估
            int eval = Minimax(depth - 1, true, alpha, beta);
            
            // 撤销落子
            board[move[0], move[1]] = 0;
            
            minEval = Math.Min(minEval, eval);
            beta = Math.Min(beta, eval);
            if (beta <= alpha) break;
        }
        return minEval;
    }
}

// 评估棋盘分数
private int EvaluateBoard()
{
    // 实现棋盘评估逻辑
    // 根据棋型(活四、冲四、活三等)计算分数
    return 0;
}

项目总结

这个五子棋游戏实现了以下功能:

  1. 完整的游戏逻辑

    • 棋盘绘制与管理
    • 落子与胜负判定
    • 游戏状态管理
  2. 智能AI对手

    • 三种难度级别
    • 防御策略(阻止玩家获胜)
    • 进攻策略(尝试获胜)
  3. 友好的用户界面

    • 美观的棋盘和棋子
    • 清晰的状态显示
    • 直观的控制按钮
  4. 额外的游戏特性

    • 音效反馈
    • 最后落子高亮
    • 双缓冲绘图(无闪烁)
posted @ 2026-04-11 16:32  小前端攻城狮  阅读(6)  评论(0)    收藏  举报