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. 运行游戏
- 创建新的Windows Forms应用程序项目
- 将上述代码复制到相应文件中
- 添加资源文件(可选)
- 运行程序
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;
}
项目总结
这个五子棋游戏实现了以下功能:
-
完整的游戏逻辑:
- 棋盘绘制与管理
- 落子与胜负判定
- 游戏状态管理
-
智能AI对手:
- 三种难度级别
- 防御策略(阻止玩家获胜)
- 进攻策略(尝试获胜)
-
友好的用户界面:
- 美观的棋盘和棋子
- 清晰的状态显示
- 直观的控制按钮
-
额外的游戏特性:
- 音效反馈
- 最后落子高亮
- 双缓冲绘图(无闪烁)
浙公网安备 33010602011771号