前言
时间:2021.03.04
创作:欧阳地 围棋不仅能增强思维能力,提高智力,而且富含哲理,有助于修身养性。同时它起源于中国,古称“弈”,是我国传统技艺之一。本游戏软件提供了人机对弈,和棋手对弈(局域网对弈)两种模式,局域网模式可以保证多人同时进行游戏。本软件使用C#语言编写,在windows 7 x64系统下采用Visual Studio 2010开发和调试,附源码如下。
客户端程序:
//-------------------login.cs---------// using System;
using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text;
using System.Windows.Forms; namespace go {
public partial class Login : Form {
public Login() {
InitializeComponent(); }
//人机对弈
private void button1_Click(object sender, EventArgs e)
{
欧阳地创编
欧阳地创编
this.Hide();
Playing playing = new Playing(); playing.ShowDialog(); this.Show(); }
//局域网对弈 private sender,EventArgs e)
{
this.Hide();
FormRoom formroom = new FormRoom(); formroom.ShowDialog(); this.Show(); }
private void button3_Click(object sender, EventArgs e)
{
Application.Exit(); }
private void button3_MouseEnter(object sender, EventArgs e)
{
Button btn = (Button)sender; btn.ForeColor = Color.Black; btn.BackColor = Color.White; }
private void button3_MouseLeave(object sender, EventArgs e)
{
Button btn = (Button)sender;
欧阳地创编
void button2_Click(object
欧阳地创编
btn.ForeColor = Color.White; btn.BackColor = Color.Black; } } } }
//-------------------Playing.cs---------// using System;
using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text;
using System.Windows.Forms; namespace go {
public partial class Playing : Form {
delegate void SetTextCallback(string text);
private enum Status {
NotStarted = 0, InGame = 1, RemoveDead = 2, FillEmpty = 3, Ended = 4 }
private System.Threading.Thread pc_play;
欧阳地创编
欧阳地创编
private Board m_board = new Board(); private Chess.ChessType Chess.ChessType.Black;
m_turn
=
private int m_secondsBlack = 0; private int m_secondsWhite = 0; private Timer m_timer = new Timer(); private Status.NotStarted;
{
get {
return m_turn; } set {
m_turn = value;
this.SetTurn((m_turn.ToString() == \"Black\") ? \"黑方\" : \"白方\");
} }
public Playing() {
InitializeComponent();
float h = this.Size.Height - 10; float w = this.Size.Width - 140; m_board.ReSize(0, 0, w, h); m_timer.Interval = 1000; m_timer.Tick EventHandler(timer_Tick);
欧阳地创编
Status m_status =
public Chess.ChessType turn
+= new
欧阳地创编
TimeSpan tm = new TimeSpan(0, 0, 0); labelTimeBlack.Text = tm.ToString(); labelTimeWhite.Text = tm.ToString(); labelTurn.Text = \"黑方\"; }
private void SetTurn(string text) {
if (this.labelTurn.InvokeRequired) {
SetTextCallback SetTextCallback(SetTurn);
this.Invoke(d, { text });
} else {
this.labelTurn.Text = text; } } //计时功能
private void timer_Tick(object sender, EventArgs e)
{
if (turn == Chess.ChessType.Black) {
m_secondsBlack++;
TimeSpan tm = new TimeSpan(0, 0, m_secondsBlack);
labelTimeBlack.Text tm.ToString();
欧阳地创编
d new
= new
object[]
=
欧阳地创编
}
else Chess.ChessType.White)
{
m_secondsWhite++;
TimeSpan tm = new TimeSpan(0, 0, m_secondsWhite);
labelTimeWhite.Text tm.ToString();
} if && !pc_play.IsAlive)
{
pc_play.Abort(); pc_play.Join(); pc_play = null; } }
private void OnFormClicked(object sender, EventArgs e)
{
//棋局结束
if (m_board.isGameOver) {
this.buttonCalculate_Click(null, null);
m_board.isGameOver = false; return; }
//不是轮到黑子的时候禁止下棋
if (!m_board.single || turn ==
欧阳地创编
if (turn ==
=
(pc_play != null
欧阳地创编
Chess.ChessType.White)
{
return; }
//备份棋局
this.m_board.BackupChess();
MouseEventArgs args = e as MouseEventArgs;
if (args != null) {
if (args.Clicks args.Button == MouseButtons.Left)
{
// 计算鼠标点击的坐标位置 Chess.POS pos m_board.mapPointsToBoard(args.X, args.Y);
if (pos.isValid) {
// 游戏中
if (m_status == Status.NotStarted || m_status == Status.InGame)
{
if (m_board.addChess(pos, turn))
{
turn = (turn == Chess.ChessType.Black) ? Chess.ChessType.White : Chess.ChessType.Black;
if (m_status == Status.NotStarted)
{
欧阳地创编
== 1 &&
=
欧阳地创编
m_timer.Start();
m_status = Status.InGame;
}
Invalidate(); } } if Status.RemoveDead)
{ m_board.toggleDead(pos);
Invalidate(); }
if (m_board.single)//人机对弈模式
{
pc_play = System.Threading.Thread(new
System.Threading.ThreadStart(ComputerPlay));
}
} } } }
delegate void ButtonDelegate(Button btn, bool flag);
private void SetButton(Button btn, bool flag)
{
欧阳地创编
(m_status ==
new
pc_play.Start();
欧阳地创编
if (btn.InvokeRequired) {
ButtonDelegate buttonDelegate = new ButtonDelegate(SetButton);
this.Invoke(buttonDelegate, new object[] { btn, flag });
} else {
btn.Enabled = flag; } }
private void ComputerPlay() {
//计算下一步棋
Chess.POS pos = m_board.Play(2, turn);
if (m_board.addChess(pos, turn)) {
turn = (turn == Chess.ChessType.Black) ? Chess.ChessType.White : Chess.ChessType.Black; if Status.NotStarted)
{
m_timer.Start();
m_status = Status.InGame; }
Invalidate(); } else
欧阳地创编
(m_status ==
欧阳地创编
{
//计算棋局结果
m_status = Status.FillEmpty; m_board.fillBoardWithChess(); string m_board.caclulateResult();
strResult
=
m_board.removeFilledChess(); MessageBox.Show(strResult, \"结果\");
m_board.single = false; this.SetButton false);
this.SetButton (this.btnLetOtherGo, false);
this.SetButton (this.btnAgain, false);
this.m_timer.Stop(); Invalidate(); } }
//显示棋子序号
private void checkBoxShowNumber_CheckedChanged(object sender, EventArgs e)
{
m_board.showIndex checkBoxShowNumber.Checked;
Invalidate(); }
//让子功能
private void buttonLetOtherGo_Click(object sender, EventArgs e)
欧阳地创编
(this.btnCalc,
=
欧阳地创编
{
if
Chess.ChessType.Black)
{
turn = Chess.oppsiteType(turn); if (m_board.single) {
pc_play = System.Threading.Thread(new
System.Threading.ThreadStart(ComputerPlay));
pc_play.Start(); } } }
//求和功能
private void buttonCalculate_Click(object sender, EventArgs e)
{
m_status = Status.FillEmpty; m_board.fillBoardWithChess(); string
m_board.caclulateResult();
strResult
= new
(this.turn
==
m_board.removeFilledChess();
MessageBox.Show(strResult, \"结果\"); m_board.single = false;
this.btnCalc.Enabled = false;
this.btnLetOtherGo.Enabled = false; this.btnAgain.Enabled = false; this.m_timer.Stop(); Invalidate();
欧阳地创编
欧阳地创编
}
//开始游戏 private void sender, EventArgs e)
{
DialogResult result = MessageBox.Show(\"确定要开始新游戏吗?\新游戏\MessageBoxButtons.YesNo);
if (result == DialogResult.Yes) {
m_board.newGame();
m_board.single = true;//人机对弈 m_secondsBlack = 0; m_secondsWhite = 0;
TimeSpan tm = new TimeSpan(0, 0, 0);
labelTimeBlack.Text tm.ToString();
labelTimeWhite.Text tm.ToString();
turn = Chess.ChessType.Black; m_timer.Stop();
m_board.markAllChessAsLive(); m_status = Status.NotStarted; this.btnCalc.Enabled = true; this.btnLetOtherGo.Enabled true;
this.btnAgain.Enabled = true; Invalidate(); } }
欧阳地创编
btnStart_Click(object
= =
=
欧阳地创编
//退出功能
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
DialogResult result = MessageBox.Show(\"你确认要退出游戏吗?\\"提示\MessageBoxButtons.YesNo);
if (result == DialogResult.No) {
e.Cancel = true; } }
//主窗口大小
private void MainForm_SizeChanged(object sender, EventArgs e)
{
float h = this.Size.Height - 10; float w = this.Size.Width - 140; m_board.ReSize(0, 0, w, h); Invalidate(); }
//画棋盘
protected
OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics; m_board.draw(g); }
private void btnClose_Click(object sender, EventArgs e)
{
欧阳地创编
override void
欧阳地创编
this.Close(); }
//悔棋功能 private void sender, EventArgs e)
{
if (this.m_board.MoveAgain()) {
Invalidate(); } } } }
//------------------Board.cs---------// using System;
using System.Collections.Generic; using System.Text; using System.Drawing; using System.IO;
using ChessBlock = System.Collections.ArrayList; using System.Collections; namespace go {
/// ///
/// 欧阳地创编 btnAgain_Click(object 欧阳地创编 /// 单人模式 ///
public bool single = false; /// /// 距离上方边缘的单位长度 ///
private static float margin_top = 10; /// /// 距离左方边缘的单位长度 ///
private static float margin_left = 10; /// /// 棋盘每条线之间的单位长度 ///
private static float gap = 20; ///
private static float chessSize = 8; ///
private static float numberSize = 6; ///
private static float starSize = 3; /// 欧阳地创编 欧阳地创编 /// 棋盘的所有棋子 ///
private Chess[,] m_Board = new Chess[19, 19];
///
private Chess[19, 19];Chess[,] m_Board_backup
///
private BoardRecorder m_recorder; ///
private Chess m_LastChess; /// /// 最后一个棋子备份 ///
private Chess m_LastChess_backup; /// /// 最后一颗被吃的棋子 ///
private Chess m_LastEatten; /// /// 最后被吃棋子备份 ///
private Chess m_LastEatten_backup;欧阳地创编
= new
欧阳地创编
///
private int m_currentStep; /// /// 是否显示棋子的编号 ///
private bool m_bShowIndex = false; ///
private Chess[,] m_Sim_Board = new Chess[19, 19];
/// /// 模拟最后一颗棋子 ///
private Chess m_Sim_LastChess; /// /// 模拟最后一颗被吃的棋子 ///
private Chess m_Sim_LastEatten; ///
private int m_Sim_currentStep; /// /// 参数随机数,用于参数随机棋步 ///
private Random r = new Random();
欧阳地创编
欧阳地创编
///
public bool isGameOver = false; ///
Clear(); }
/// /// 获取最后一颗棋子 ///
public Chess lastChess { get { return m_LastChess; } } /// /// 获取或设置是否显示棋子的编号 ///
public bool showIndex {
get { return m_bShowIndex; } set { m_bShowIndex = value; } }
/// /// 调整棋子在棋盘中的位置,并返回棋子的位置 ///
///
欧阳地创编
欧阳地创编
/// ///
public Chess.POS mapPointsToBoard(float pointX, float pointY) {
int posX = Convert.ToInt32((pointX - margin_left + gap / 2) / gap - 0.5f);
int posY = Convert.ToInt32((pointY - margin_top + gap / 2) / gap - 0.5f);
Chess.POS pos = new Chess.POS(posX, posY);
if (!pos.isValid)
pos.setToInvalid(); return pos; }
///
/// public void draw(Graphics g) {
drawBorder(g); drawChess(g); }
///
/// /// ///
欧阳地创编
欧阳地创编
private void drawStar(Graphics g, float posX, float posY) {
Rectangle rect = new Rectangle(); rect.X = Convert.ToInt32 (margin_left + posX * gap - starSize);
rect.Y = Convert.ToInt32 (margin_top + posY * gap - starSize);
rect.Width = Convert.ToInt32 (starSize * 2);
rect.Height = Convert.ToInt32 (starSize * 2);
g.FillEllipse(Brushes.Black, rect); }
///
///
private void drawBorder(Graphics g) {
//绘制棋盘颜色
Pen backgroundPen Pen(Color.Goldenrod, 10);
=
new
g.FillRectangle(backgroundPen.Brush, margin_left - gap/2, margin_top - gap/2, gap * 19, gap * 19);
//绘制棋盘线
Pen borderPen = new Pen(Color.Black, 1); for (int i = 0; i < 19; i++) {
g.DrawLine(borderPen, margin_left, margin_top + i * gap, margin_left + 18 * gap,
欧阳地创编
欧阳地创编
margin_top + i * gap);
g.DrawLine(borderPen, margin_left + i * gap, margin_top, margin_left + i * gap, margin_top + 18 * gap); }
// 绘制9个星位 drawStar(g, 3, 3); drawStar(g, 3, 9); drawStar(g, 3, 15); drawStar(g, 9, 3); drawStar(g, 9, 9); drawStar(g, 9, 15); drawStar(g, 15, 3); drawStar(g, 15, 9); drawStar(g, 15, 15); }
///
///
private void drawChess(Graphics g) {
Rectangle rect = new Rectangle(); StringFormat StringFormat();
format.Alignment StringAlignment.Center;
format.LineAlignment StringAlignment.Center;
format
=
new = =
Font fontNumber = new Font(\"Arial Narrow\
欧阳地创编
欧阳地创编
for (int i = 0; i < 19; i++) {
for (int j = 0; j < 19; j++) {
switch (m_Board[i, j].type) {
case Chess.ChessType.Black:
rect.X = Convert.ToInt32 (margin_left + i * gap - chessSize); rect.Y = Convert.ToInt32 (margin_top + j * gap - chessSize); rect.Width Convert.ToInt32 (chessSize * 2);
rect.Height Convert.ToInt32 (chessSize * 2);
g.FillEllipse(Brushes.Black, rect);
if (m_bShowIndex && m_Board[i, j].step > 0)
{
g.DrawString(m_Board[i, j].step.ToString(), fontNumber, Brushes.White, rect, format); } break; case Chess.ChessType.DeadBlack:
rect.X = Convert.ToInt32 (margin_left + i * gap - chessSize); rect.Y = Convert.ToInt32 (margin_top + j * gap - chessSize); rect.Width Convert.ToInt32 (chessSize * 2);
欧阳地创编
= =
=
欧阳地创编
rect.Height Convert.ToInt32 (chessSize * 2);
int centerX Convert.ToInt32 (margin_left + i * gap); int centerY Convert.ToInt32 (margin_top + j * gap);
g.FillEllipse(Brushes.Black, rect);
= = =
g.DrawLine(new
Pen(Color.Red, 3), centerX - chessSize / 2, centerY - chessSize / 2, centerX + chessSize / 2, centerY + chessSize / 2);
if (m_bShowIndex && m_Board[i, j].step > 0)
{
g.DrawString(m_Board[i, j].step.ToString(), fontNumber, Brushes.White, rect, format); } break; case Chess.ChessType.White:
rect.X = Convert.ToInt32 (margin_left + i * gap - chessSize); rect.Y = Convert.ToInt32 (margin_top + j * gap - chessSize); rect.Width Convert.ToInt32 (chessSize * 2);
rect.Height Convert.ToInt32 (chessSize * 2);
g.FillEllipse(Brushes.White, rect);
if (m_bShowIndex && m_Board[i, j].step > 0)
{
欧阳地创编
= =
欧阳地创编
g.DrawString(m_Board[i, j].step.ToString(), fontNumber, Brushes.Black, rect, format); } break; case Chess.ChessType.DeadWhite:
rect.X = Convert.ToInt32 (margin_left + i * gap - chessSize); rect.Y = Convert.ToInt32 (margin_top + j * gap - chessSize); rect.Width Convert.ToInt32 (chessSize * 2);
rect.Height Convert.ToInt32 (chessSize * 2);
centerX
Convert.ToInt32 (margin_left + i * gap); centerY Convert.ToInt32 (margin_top + j * gap);
g.FillEllipse(Brushes.White, rect);
g.DrawLine(new
Pen(Color.Red, 3), centerX - chessSize / 2, centerY - chessSize / 2, centerX + chessSize / 2, centerY + chessSize / 2);
if (m_bShowIndex && m_Board[i, j].step > 0)
{
g.DrawString(m_Board[i, j].step.ToString(), fontNumber, Brushes.Black, rect, format); } break; case Chess.ChessType.MaybeBlack:
欧阳地创编
= = = =
欧阳地创编
rect.X = Convert.ToInt32 (margin_left + i * gap - chessSize / 2);
rect.Y = Convert.ToInt32 (margin_top + j * gap - chessSize / 2);
rect.Width Convert.ToInt32 (chessSize);
rect.Height Convert.ToInt32 (chessSize);
g.FillRectangle(Brushes.Black, rect); break; case Chess.ChessType.MaybeWhite:
rect.X = Convert.ToInt32 (margin_left + i * gap - chessSize / 2);
rect.Y = Convert.ToInt32 (margin_top + j * gap - chessSize / 2);
rect.Width Convert.ToInt32 (chessSize);
rect.Height Convert.ToInt32 (chessSize);
g.FillRectangle(Brushes.White, rect); break; case Chess.ChessType.MaybePending:
rect.X = Convert.ToInt32 (margin_left + i * gap - chessSize / 2);
rect.Y = Convert.ToInt32 (margin_top + j * gap - chessSize / 2);
欧阳地创编
= =
= =
欧阳地创编
rect.Width Convert.ToInt32 (chessSize);
rect.Height Convert.ToInt32 (chessSize);
g.FillRectangle(Brushes.Yellow, rect); break; } } } }
/// /// 增加一颗棋子在棋盘上 ///
/// /// ///
if (this.m_currentStep > 361) {
this.isGameOver = true; return false; }
//只允许放黑棋或白棋
addChess(Chess.POS
= =
pos,
if (type != Chess.ChessType.Black && type != Chess.ChessType.White) return false;
// 只允许在空位置上放棋子。
欧阳地创编
欧阳地创编
if (m_Board[pos.posX, pos.posY].type != Chess.ChessType.Empty)
return false;
// 设置当前位置的棋子的类型
m_Board[pos.posX, pos.posY].type = type;
#region 判断是否可以提子 bool bEat = false; bool bValidStep = true;
//当棋子的左方有空位,并且该位置棋子的棋子是对方的棋子时,执行以下代码
if (pos.hasLeft && m_Board[pos.posX - 1, pos.posY].type == Chess.oppsiteType(type)) { //
bEat = tryToEat(pos, new Chess.POS(pos.posX - 1, pos.posY), ref bValidStep) || bEat;
if (!bValidStep) return false; }
//当棋子的右方有空位,并且该位置棋子的棋子是对方的棋子时,执行以下代码
if (pos.hasRight && m_Board[pos.posX + 1, pos.posY].type == Chess.oppsiteType(type)) {
bEat = tryToEat(pos, new Chess.POS(pos.posX + 1, pos.posY), ref bValidStep) || bEat;
if (!bValidStep) return false; }
欧阳地创编
欧阳地创编
//当棋子的上方有空位,并且该位置棋子的棋子是对方的棋子时,执行以下代码
if (pos.hasUp && m_Board[pos.posX, pos.posY - 1].type == Chess.oppsiteType(type)) {
bEat = tryToEat(pos, new Chess.POS(pos.posX, pos.posY - 1), ref bValidStep) || bEat;
if (!bValidStep) return false; }
//当棋子的下方有空位,并且该位置棋子的棋子是对方的棋子时,执行以下代码
if (pos.hasDown && m_Board[pos.posX, pos.posY + 1].type == Chess.oppsiteType(type)) {
bEat = tryToEat(pos, new Chess.POS(pos.posX, pos.posY + 1), ref bValidStep) || bEat;
if (!bValidStep) return false; }
#endregion if (!bEat)
m_LastEatten.pos.setToInvalid(); // 判断相连的棋子是否还有气。 ArrayList chessBlock;
if (!isLive(pos, out chessBlock)) {
return false; }
欧阳地创编
欧阳地创编
m_LastChess.pos = pos; m_LastChess.type = type;
m_LastChess.step = m_currentStep;
m_recorder.addStep(new Chess(pos, type, m_currentStep));
m_Board[pos.posX, pos.posY].step = m_currentStep;
m_Board[pos.posX, pos.posY].pos = pos; m_currentStep++; return true; }
/// /// 加载文件中的棋局 ///
/// ///
if
(!Utils.isFileReadyForRead(strFile)) return false;
Chess.ChessType[,] newBoard = new Chess.ChessType[19, 19]; StreamReader StreamReader(strFile); {
string freader.ReadLine();
strLine
=
freader
=
new
bool
loadBoardFromFile(string
for (int i = 0; i < 19; i++)
if (strLine.Length != 19)
欧阳地创编
欧阳地创编
return false;
for (int j = 0; j < 19; j++) {
Chess.ChessType Chess.ChessType.Empty;
switch (strLine[j]) {
case '0': type Chess.ChessType.Empty;
break; case '1': type Chess.ChessType.Black;
break; case '2': type Chess.ChessType.White;
break; default:
return false; }
newBoard[j, i] = type; } }
for (int i = 0; i < 19; i++) {
for (int j = 0; j < 19; j++) {
m_Board[i, j].type = newBoard[i,
欧阳地创编
type =
=
=
=
欧阳地创编
j];
} }
return true; }
/// /// 保存棋局到文件中 ///
/// ///
public bool saveBoardToFile(string strFile) {
FileInfo fi = new FileInfo(strFile); if (fi.Exists) fi.Delete();
StreamWriter sw = fi.CreateText(); for (int i = 0; i < 19; i++) {
StringBuilder StringBuilder(20); {
char ch;
ch = (m_Board[j, i].type == Chess.ChessType.Empty) ? '0' : (m_Board[j, i].type == Chess.ChessType.Black) ? '1' : '2'; strLine.Append(ch); }
sw.WriteLine(strLine);
欧阳地创编
strLine = new
for (int j = 0; j < 19; j++)
欧阳地创编
}
sw.Close(); return true; }
/// ///
/// ///
public bool loadStepFile(string strFile) {
m_recorder.loadFromFile(strFile); int totalSteps = m_recorder.totalSteps; if (totalSteps > 0) {
clearBoard();
for (int i = 0; i < totalSteps; i++) {
Chess.POS m_recorder.getPosOfStep(i);
Chess.ChessType m_recorder.getTypeOfStep(i); }
return true; }
return false; }
/// 欧阳地创编 pos type = = addChess(pos, type); 欧阳地创编 /// ///
/// ///
public bool saveStepsToFile(string strFile) {
return m_recorder.saveToFile(strFile); }
///
public void newGame() {
clear(); }
/// /// 填充棋子用以计算得分 ///
public void fillBoardWithChess() {
for (int i = 0; i < 19; i++) {
for (int j = 0; j < 19; j++) {
if (m_Board[i, j].type == Chess.ChessType.Empty) {
ChessBlock block;
findBlock(new Chess.POS(i,
欧阳地创编
欧阳地创编
j), out block);
if (block.Count > 0) {
Chess.ChessType type = Chess.ChessType.Empty;
foreach (Chess.POS pos in block)
{
if (pos.hasLeft) {
Chess.ChessType newType = m_Board[pos.posX - 1, pos.posY].type;
if (type == Chess.ChessType.Empty &&
(newType == Chess.ChessType.Black || newType == Chess.ChessType.White))
{
type newType;
} else {
if (type != Chess.ChessType.Empty &&
type == Chess.oppsiteType(newType))
{
type = Chess.ChessType.MaybePending;
break;
欧阳地创编
=
欧阳地创编
} } }
if (pos.hasRight) {
Chess.ChessType newType = m_Board[pos.posX + 1, pos.posY].type;
if (type == Chess.ChessType.Empty && (newType == Chess.ChessType.Black || newType == Chess.ChessType.White))
{
type newType;
} else {
if
(type != Chess.ChessType.Empty && type == Chess.oppsiteType(newType))
{
type = Chess.ChessType.MaybePending;
break;
} } }
if (pos.hasUp) {
Chess.ChessType newType = m_Board[pos.posX,
欧阳地创编
=
欧阳地创编
pos.posY - 1].type;
if (type == Chess.ChessType.Empty && (newType == Chess.ChessType.Black || newType == Chess.ChessType.White))
{
type newType;
} else {
if
(type != Chess.ChessType.Empty && type == Chess.oppsiteType(newType))
{
type = Chess.ChessType.MaybePending;
break;
} } }
if (pos.hasDown) {
Chess.ChessType newType = m_Board[pos.posX, pos.posY + 1].type;
if (type == Chess.ChessType.Empty && (newType == Chess.ChessType.Black || newType == Chess.ChessType.White))
{
type newType;
欧阳地创编
=
=
欧阳地创编
} else {
if
(type != Chess.ChessType.Empty && type == Chess.oppsiteType(newType))
{
type = Chess.ChessType.MaybePending;
break;
} } } } if Chess.ChessType.Black)
(type
== =
type Chess.ChessType.MaybeBlack;
else if (type == Chess.ChessType.White)
type Chess.ChessType.MaybeWhite; else type Chess.ChessType.MaybePending;
foreach posToFill in block)
{
m_Board[posToFill.posX, posToFill.posY].type = type;
}
欧阳地创编
=
=
(Chess.POS
欧阳地创编
} } } } }
/// /// 向虚拟棋盘填充棋子用以计算得分 ///
public void fillBoardWithChessOnSim() {
for (int i = 0; i < 19; i++) {
for (int j = 0; j < 19; j++) {
if (this.m_Sim_Board[i, j].type == Chess.ChessType.Empty) {
ChessBlock block; findBlockOnSim(new Chess.POS(i, j), out block);
if (block.Count > 0) {
Chess.ChessType type = Chess.ChessType.Empty;
foreach (Chess.POS pos in block)
{
if (pos.hasLeft) {
欧阳地创编
欧阳地创编
Chess.ChessType newType = this.m_Sim_Board[pos.posX - 1, pos.posY].type;
if (type == Chess.ChessType.Empty &&
(newType == Chess.ChessType.Black ||
newType == Chess.ChessType.White))
{
type newType;
} else {
if (type != Chess.ChessType.Empty &&
type == Chess.oppsiteType(newType))
{
type = Chess.ChessType.MaybePending;
break;
} } }
if (pos.hasRight) {
Chess.ChessType newType = this.m_Sim_Board[pos.posX + 1, pos.posY].type;
if (type == Chess.ChessType.Empty && (newType == Chess.ChessType.Black || newType ==
欧阳地创编
=
欧阳地创编
Chess.ChessType.White))
{
type newType;
} else {
if
(type != Chess.ChessType.Empty && type == Chess.oppsiteType(newType))
{ type = Chess.ChessType.MaybePending;
break;
} } }
if (pos.hasUp) {
Chess.ChessType newType = this.m_Sim_Board[pos.posX, pos.posY - 1].type;
if (type == Chess.ChessType.Empty && (newType == Chess.ChessType.Black || newType == Chess.ChessType.White))
{
type newType;
} else {
欧阳地创编
=
=
欧阳地创编
if
(type != Chess.ChessType.Empty && type == Chess.oppsiteType(newType))
{ type = Chess.ChessType.MaybePending;
break;
} } }
if (pos.hasDown) {
Chess.ChessType newType = this.m_Sim_Board[pos.posX, pos.posY + 1].type;
if (type == Chess.ChessType.Empty && (newType == Chess.ChessType.Black || newType == Chess.ChessType.White))
{
type newType;
} else {
if
(type != Chess.ChessType.Empty && type == Chess.oppsiteType(newType))
{
type = Chess.ChessType.MaybePending;
break;
欧阳地创编
=
欧阳地创编
} } } } if (type
== Chess.ChessType.Black)
type Chess.ChessType.MaybeBlack;
else Chess.ChessType.White)if
type Chess.ChessType.MaybeWhite; else type Chess.ChessType.MaybePending;
foreach posToFill in block)
{ this.m_Sim_Board[posToFill.posX, posToFill.posY].type = type; } } } } } }
/// ///
public void removeFilledChess()欧阳地创编
=
== =
=
(type
(Chess.POS
欧阳地创编
{
for (int i = 0; i < 19; i++) {
for (int j = 0; j < 19; j++) {
if (m_Board[i, j].type == Chess.ChessType.MaybeBlack
|| m_Board[i, j].type == Chess.ChessType.MaybeWhite
|| m_Board[i, j].type == Chess.ChessType.MaybePending) {
m_Board[i, Chess.ChessType.Empty; } } } }
/// /// 暂停游戏,把棋子转换成死亡状态 ///
///
public void toggleDead(Chess.POS pos) {
Chess.ChessType type = m_Board[pos.posX, pos.posY].type;
if (type == Chess.ChessType.Black || type == Chess.ChessType.White ||
type == Chess.ChessType.DeadBlack || type == Chess.ChessType.DeadWhite) {
欧阳地创编
j].type =
欧阳地创编
ChessBlock block;
findBlock(pos, out block); if (block.Count > 0) {
Chess.ChessType typeResult = Chess.ChessType.Empty;
switch (type) {
case Chess.ChessType.Black:
typeResult Chess.ChessType.DeadBlack;
break; case Chess.ChessType.White:
typeResult Chess.ChessType.DeadWhite;
break; case Chess.ChessType.DeadBlack:
typeResult Chess.ChessType.Black;
break; case Chess.ChessType.DeadWhite:
typeResult Chess.ChessType.White;
break; }
foreach (Chess.POS posToToggle in block)
{
欧阳地创编
=
=
=
=
欧阳地创编
m_Board[posToToggle.posX, posToToggle.posY].type = typeResult; } } } }
/// /// 继续游戏,把棋子转换成存活状态 ///
public void markAllChessAsLive() {
for (int i = 0; i < 19; i++) {
for (int j = 0; j < 19; j++) {
if (m_Board[i, j].type == Chess.ChessType.DeadBlack) {
m_Board[i, Chess.ChessType.Black; }
else if (m_Board[i, j].type == Chess.ChessType.DeadWhite) {
m_Board[i, Chess.ChessType.White; } } } }
欧阳地创编
j].type =
j].type =
欧阳地创编
///
///
public string caclulateResult() {
int nBlack = 0; int nWhite = 0; int nPending = 0;
for (int i = 0; i < 19; i++) {
for (int j = 0; j < 19; j++) {
switch (m_Board[i, j].type) {
case Chess.ChessType.Black:
case Chess.ChessType.DeadWhite: case Chess.ChessType.MaybeBlack:
nBlack++; break; case Chess.ChessType.White:
case Chess.ChessType.DeadBlack: case Chess.ChessType.MaybeWhite:
nWhite++; break;
欧阳地创编
欧阳地创编
default:
nPending++; break; } } }
double fBlack (double)nPending / 2;
double fWhite (double)nPending / 2; StringBuilder StringBuilder();
= =
nBlack nWhite
=
+ + new
strResult
strResult.Append(\"黑子 : \" + fBlack.ToString() + \"\\n\");
strResult.Append(\"白子 : \" + fWhite.ToString() + \"\\n\\n\");
strResult.Append(\"结果 : \"); fWhite += 3.75; if (fBlack > fWhite) {
strResult.Append(\"黑子赢\" + (fBlack - fWhite).ToString()); }
else if (fWhite > fBlack) {
strResult.Append(\"白子赢\" + (fWhite - fBlack).ToString()); }
return strResult.ToString(); }
/// 欧阳地创编 欧阳地创编 /// 初始化棋盘并创建新记录 ///
private void clear() {
clearBoard();
m_recorder = new BoardRecorder(); }
///
private void clearBoard() {
for (int i = 0; i < 19; i++) {
for (int j = 0; j < 19; j++) {
m_Board[i, j] = new Chess(new Chess.POS(i, j), Chess.ChessType.Empty, 0);
m_Board_backup[i, j] = new Chess(new Chess.POS(i, j), Chess.ChessType.Empty, 0); } }
m_LastChess = new Chess(); m_LastEatten = new Chess(); m_LastChess.pos.setToInvalid(); m_LastEatten.pos.setToInvalid(); m_currentStep = 1; }
欧阳地创编
欧阳地创编
private void clearMoveList() {
for (int i = 0; i < 19; i++) {
for (int j = 0; j < 19; j++) {
this.m_Sim_Board[i, j] = new Chess(new Chess.POS(i, j), Chess.ChessType.Empty, 0);
} } }
///
///
/// private void findBlock(Chess.POS pos, out ChessBlock chessBlock) {
Queue posToProcceed = new Queue(); chessBlock = new ArrayList(); posToProcceed.Enqueue(pos); chessBlock.Add(pos);
Chess.ChessType type = m_Board[pos.posX, pos.posY].type;
while (posToProcceed.Count > 0) {
Chess.POS posCurrent (Chess.POS)posToProcceed.Dequeue();
欧阳地创编
=
欧阳地创编
// Left
if (posCurrent.hasLeft) {
Chess.POS pos1 = new Chess.POS(posCurrent.posX - 1, posCurrent.posY); if
(!posToProcceed.Contains(pos1)
&& !chessBlock.Contains(pos1) && m_Board[pos1.posX, pos1.posY].type == type) {
posToProcceed.Enqueue(pos1);
chessBlock.Add(pos1); } }
// Right
if (posCurrent.hasRight) {
Chess.POS pos1 = new Chess.POS(posCurrent.posX + 1, posCurrent.posY); if
(!posToProcceed.Contains(pos1)
&& !chessBlock.Contains(pos1) && m_Board[pos1.posX, pos1.posY].type == type) {
posToProcceed.Enqueue(pos1);
chessBlock.Add(pos1); } } // Up
if (posCurrent.hasUp)
欧阳地创编
欧阳地创编
{
Chess.POS pos1 = new Chess.POS(posCurrent.posX, posCurrent.posY - 1); if
(!posToProcceed.Contains(pos1)
&& !chessBlock.Contains(pos1) && m_Board[pos1.posX, pos1.posY].type == type) {
posToProcceed.Enqueue(pos1);
chessBlock.Add(pos1); } }
// Down
if (posCurrent.hasDown) {
Chess.POS pos1 = new Chess.POS(posCurrent.posX, posCurrent.posY + 1); if
(!posToProcceed.Contains(pos1)
&& !chessBlock.Contains(pos1) && m_Board[pos1.posX, pos1.posY].type == type) {
posToProcceed.Enqueue(pos1);
chessBlock.Add(pos1); } } } }
/// 欧阳地创编 欧阳地创编 ///
///
/// private void findBlockOnSim(Chess.POS pos, out ChessBlock chessBlock) {
Queue posToProcceed = new Queue(); chessBlock = new ArrayList(); posToProcceed.Enqueue(pos); chessBlock.Add(pos);
Chess.ChessType type this.m_Sim_Board[pos.posX, pos.posY].type; while (posToProcceed.Count > 0) {
Chess.POS posCurrent (Chess.POS)posToProcceed.Dequeue(); // Left
if (posCurrent.hasLeft) {
Chess.POS pos1 = new Chess.POS(posCurrent.posX - 1, posCurrent.posY); if
(!posToProcceed.Contains(pos1) && !chessBlock.Contains(pos1) &&
this.m_Sim_Board[pos1.posX, pos1.posY].type == type)
{
posToProcceed.Enqueue(pos1);
chessBlock.Add(pos1); }
欧阳地创编
=
=
欧阳地创编
}
// Right
if (posCurrent.hasRight) {
Chess.POS pos1 = new Chess.POS(posCurrent.posX + 1, posCurrent.posY); if
(!posToProcceed.Contains(pos1) && !chessBlock.Contains(pos1) &&
this.m_Sim_Board[pos1.posX, pos1.posY].type == type)
{
posToProcceed.Enqueue(pos1);
chessBlock.Add(pos1); } } // Up
if (posCurrent.hasUp) {
Chess.POS pos1 = new Chess.POS(posCurrent.posX, posCurrent.posY - 1); if
(!posToProcceed.Contains(pos1) && !chessBlock.Contains(pos1) &&
this.m_Sim_Board[pos1.posX, pos1.posY].type == type)
{
posToProcceed.Enqueue(pos1);
chessBlock.Add(pos1);
欧阳地创编
欧阳地创编
} }
// Down
if (posCurrent.hasDown) {
Chess.POS pos1 = new Chess.POS(posCurrent.posX, posCurrent.posY + 1); if
(!posToProcceed.Contains(pos1) && !chessBlock.Contains(pos1) &&
this.m_Sim_Board[pos1.posX, pos1.posY].type == type)
{
posToProcceed.Enqueue(pos1);
chessBlock.Add(pos1); } } } }
/// /// 判断棋子及相邻的棋子是否没气。 ///
///
/// ///
private bool isLive(Chess.POS pos, out ChessBlock chessBlock) {
// 1. 吃别人(包括劫持)
欧阳地创编
欧阳地创编
// 2. 被自己吃了
Queue posToProcceed = new Queue();//棋子位置队列
chessBlock = new ArrayList();//棋子位置块,用于记录最终所有相邻的同类的棋子位置
posToProcceed.Enqueue(pos);//把棋子位置添加到队列尾。
chessBlock.Add(pos);//把棋子位置添加到块里。
Chess.ChessType type = m_Board[pos.posX, pos.posY].type;//获取该位置棋子的类型
while (posToProcceed.Count > 0) {
Chess.POS posCurrent = (Chess.POS)posToProcceed.Dequeue();//获取队列的第一个棋子位置
//判断棋子与左边缘是否还有位置 if (posCurrent.hasLeft) {
Chess.POS pos1 = new Chess.POS(posCurrent.posX - 1, posCurrent.posY); //左边相邻的位置没有棋子时,该棋子有气。返回true。
if (m_Board[pos1.posX, pos1.posY].type == Chess.ChessType.Empty) return true;
if
(!posToProcceed.Contains(pos1) && //该位置不在队列里
!chessBlock.Contains(pos1) && //该位置不在块里
m_Board[pos1.posX,
pos1.posY].type == type) //该位置的棋子类型与原棋子一样
欧阳地创编
欧阳地创编
{
//把该棋子添加到队列和块中。
posToProcceed.Enqueue(pos1);
chessBlock.Add(pos1); } }
//判断棋子与右边缘是否还有位置 if (posCurrent.hasRight) {
Chess.POS pos1 = new Chess.POS(posCurrent.posX + 1, posCurrent.posY); //右边相邻的位置没有棋子时,该棋子有气。返回true。
if (m_Board[pos1.posX, pos1.posY].type == Chess.ChessType.Empty) return true;
if
(!posToProcceed.Contains(pos1) && //该位置不在队列里
!chessBlock.Contains(pos1) && //该位置不在块里
m_Board[pos1.posX,
pos1.posY].type == type) //该位置的棋子类型与原棋子一样
{
//把该棋子添加到队列和块中。
posToProcceed.Enqueue(pos1);
chessBlock.Add(pos1); }
欧阳地创编
欧阳地创编
}
//判断棋子与上边缘是否还有位置 if (posCurrent.hasUp) {
Chess.POS pos1 = new Chess.POS(posCurrent.posX, posCurrent.posY - 1); //上边相邻的位置没有棋子时,该棋子有气。返回true。
if (m_Board[pos1.posX, pos1.posY].type == Chess.ChessType.Empty) return true;
if
(!posToProcceed.Contains(pos1) && //该位置不在队列里
!chessBlock.Contains(pos1) && //该位置不在块里
m_Board[pos1.posX,
pos1.posY].type == type) //该位置的棋子类型与原棋子一样
{
//把该棋子添加到队列和块中。
posToProcceed.Enqueue(pos1);
chessBlock.Add(pos1); } }
//判断棋子与下边缘是否还有位置 if (posCurrent.hasDown) {
Chess.POS pos1 = new Chess.POS(posCurrent.posX, posCurrent.posY + 1) //下边相邻的位置没有棋子时,该
欧阳地创编
欧阳地创编
棋子有气。返回true。
if (m_Board[pos1.posX, pos1.posY].type == Chess.ChessType.Empty) return true;
if
(!posToProcceed.Contains(pos1) && //该位置不在队列里
!chessBlock.Contains(pos1) && //该位置不在块里
m_Board[pos1.posX,
pos1.posY].type == type) //该位置的棋子类型与原棋子一样
{
//把该棋子添加到队列和块中。
posToProcceed.Enqueue(pos1);
chessBlock.Add(pos1); } } }
return false; }
/// /// 判断该棋子是否可以被吃。 ///
/// 刚下的棋子
/// 被吃的棋子
/// ///
欧阳地创编
欧阳地创编
private bool tryToEat(Chess.POS posNewChess, Chess.POS posToEat, ref bool bValidStep) {
bValidStep = true;
System.Collections.ArrayList chessBlock;
if (!isLive(posToEat, out chessBlock))//如果被吃棋子没气了,执行以下代码 {
// 处理打劫问题
if (chessBlock.Count == 1) {
if (m_LastEatten.pos.isValid && posNewChess == m_LastEatten.pos) {
removeChess(posNewChess); bValidStep = false; return false; } else {
m_LastEatten.pos posToEat;
} } else {
m_LastEatten.pos.setToInvalid(); }
removeChessBlock(chessBlock);
欧阳地创编
=
欧阳地创编
return true; }
return false; }
/// /// 提子(移出一组指定的棋子) ///
/// private void removeChessBlock(ChessBlock chessBlock) {
foreach (Chess.POS pos in chessBlock) {
m_Board[pos.posX, pos.posY].type = Chess.ChessType.Empty; } }
/// /// 提子(移出一颗指定的棋子) ///
///
private void removeChess(Chess.POS pos) {
m_Board[pos.posX, pos.posY].type = Chess.ChessType.Empty; }
/// ///
欧阳地创编
欧阳地创编
public bool MoveAgain() {
if (this.m_currentStep > 1) {
//轮到自己下棋 if Chess.ChessType.White) {
for (int i = 0; i < 19; ++i) { for (int j = 0; j < 19; ++j) {
m_Board[i, j] = new Chess(m_Board_backup[i, j].pos, m_Board_backup[i, j].type, m_Board_backup[i, j].step); } }
this.m_LastChess this.m_LastChess_backup.Copy();
this.m_LastEatten this.m_LastEatten_backup.Copy();
this.m_currentStep -= 2; return true; }
//轮到电脑下棋 else {
//do nothing } }
欧阳地创编
(m_LastChess.type ==
= =
欧阳地创编
return false; }
public void BackupChess() {
for (int i = 0; i < 19; ++i) {
for (int j = 0; j < 19; ++j) {
m_Board_backup[i, j] = new Chess(m_Board[i, j].pos, m_Board[i, j].type, m_Board[i, j].step); } }
this.m_LastChess_backup this.m_LastChess.Copy();
this.m_LastEatten_backup this.m_LastEatten.Copy(); }
#region ==== 单人游戏时 ==== /// /// 电脑开始计算下一步棋子 ///
/// /// ///
#region 添加候选步
//Chess.POS pos = this.m_LastChess.pos;
欧阳地创编
= =
Play(int numsim,
欧阳地创编
List #region 一线点 move_Node = new //根据经验规则选择比较合适的着法 if (this.m_LastChess.step > 20) { #region 上边 for (int i = 0, j = 0; j < 19; ++j) { if (this.HaveChessDistantWithin(3, i, j)) { if (this.CanAddChess(new Chess.POS(i, j), Chess.oppsiteType(m_LastChess.type))) move_Node.Add(new Node(new Chess.POS(i, j))); } } #endregion #region 下边 for (int i = 18, j = 0; j < 19; ++j) { if (this.HaveChessDistantWithin(3, i, j)) { if (this.CanAddChess(new Chess.POS(i, j), Chess.oppsiteType(m_LastChess.type))) move_Node.Add(new Node(new Chess.POS(i, j))); } 欧阳地创编 欧阳地创编 } #endregion #region 左边 for (int i = 1, j = 0; i < 18; ++i) { if (this.HaveChessDistantWithin(3, i, j)) { if (this.CanAddChess(new Chess.POS(i, j), Chess.oppsiteType(m_LastChess.type))) move_Node.Add(new Node(new Chess.POS(i, j))); } } #endregion #region 右边 for (int i = 1, j = 18; i < 18; ++i) { if (this.HaveChessDistantWithin(3, i, j)) { if (this.CanAddChess(new Chess.POS(i, j), Chess.oppsiteType(m_LastChess.type))) move_Node.Add(new Node(new Chess.POS(i, j))); } } #endregion } 欧阳地创编 欧阳地创编 #endregion #region 二线点 if (this.m_LastChess.step > 15) { #region 上边 for (int i = 1, j = 1; j < 18; ++j) { if (this.HaveChessDistantWithin(4, i, j)) { if (this.CanAddChess(new Chess.POS(i, j), Chess.oppsiteType(m_LastChess.type))) move_Node.Add(new Node(new Chess.POS(i, j))); } } #endregion #region 下边 for (int i = 17, j = 1; j < 18; ++j) { if (this.HaveChessDistantWithin(4, i, j)) { if (this.CanAddChess(new Chess.POS(i, j), Chess.oppsiteType(m_LastChess.type))) move_Node.Add(new Node(new Chess.POS(i, j))); } } 欧阳地创编 欧阳地创编 #endregion #region 左边 for (int i = 2, j = 1; i < 17; ++i) { if (this.HaveChessDistantWithin(4, i, j)) { if (this.CanAddChess(new Chess.POS(i, j), Chess.oppsiteType(m_LastChess.type))) move_Node.Add(new Node(new Chess.POS(i, j))); } } #endregion #region 右边 for (int i = 2, j = 17; i < 17; ++i) { if (this.HaveChessDistantWithin(4, i, j)) { if (this.CanAddChess(new Chess.POS(i, j), Chess.oppsiteType(m_LastChess.type))) move_Node.Add(new Node(new Chess.POS(i, j))); } } #endregion } #endregion 欧阳地创编 欧阳地创编 #region 三线点 if (this.m_LastChess.step > 10) { #region 上边 for (int i = 2, j = 2; j < 17; ++j) { if (this.HaveChessDistantWithin(4, i, j)) { if (this.CanAddChess(new Chess.POS(i, j), Chess.oppsiteType(m_LastChess.type))) move_Node.Add(new Node(new Chess.POS(i, j))); } } #endregion #region 下边 for (int i = 16, j = 2; j < 17; ++j) { if (this.HaveChessDistantWithin(4, i, j)) { if (this.CanAddChess(new Chess.POS(i, j), Chess.oppsiteType(m_LastChess.type))) move_Node.Add(new Node(new Chess.POS(i, j))); } } #endregion 欧阳地创编 欧阳地创编 #region 左边 for (int i = 3, j = 2; i < 16; ++i) { if (this.HaveChessDistantWithin(4, i, j)) { if (this.CanAddChess(new Chess.POS(i, j), Chess.oppsiteType(m_LastChess.type))) move_Node.Add(new Node(new Chess.POS(i, j))); } } #endregion #region 右边 for (int i = 3, j = 16; i < 16; ++i) { if (this.HaveChessDistantWithin(4, i, j)) { if (this.CanAddChess(new Chess.POS(i, j), Chess.oppsiteType(m_LastChess.type))) move_Node.Add(new Node(new Chess.POS(i, j))); } } #endregion } #endregion for (int i = 3; i < 16; ++i) 欧阳地创编 欧阳地创编 { for (int j = 3; j < 16; ++j) { if (this.m_Board[i, j].type == Chess.ChessType.Empty && this.m_Board[i, j].step == 0) { if (this.CanAddChess(new Chess.POS(i, j), Chess.oppsiteType(m_LastChess.type))) move_Node.Add(new Node(new Chess.POS(i, j))); } } } if (move_Node.Count <= 0) { this.isGameOver = true; } #endregion #region 每个节点都进行若干回合的模拟棋局 foreach (Node root in move_Node) { for (int i = 0; i < numsim; ++i) { CopyState(root); /* 复制棋局信息 */ play_simulation(root); /* 进行模拟 */ 欧阳地创编 欧阳地创编 } } #endregion Node n = GetBestChild(move_Node); /* 获得根节点的访问次数最多的子节点 */ return n.pos; /* 返回节点着手 */ } private bool CanAddChess(Chess.POS pos, Chess.ChessType type) { //只允许放黑棋或白棋 if (type != Chess.ChessType.Black && type != Chess.ChessType.White) return false; // 只允许在空位置上放棋子。 if (m_Board[pos.posX, pos.posY].type != Chess.ChessType.Empty) return false; // 设置当前位置的棋子的类型 m_Board[pos.posX, pos.posY].type = type; #region 判断是否可以提子 bool bEat = false; bool bValidStep = true; bool result = true; //当棋子的左方有空位,并且该位置棋子的棋子是对方的棋子时,执行以下代码 if (pos.hasLeft && m_Board[pos.posX - 1, pos.posY].type == Chess.oppsiteType(type)) { // 欧阳地创编 欧阳地创编 bEat = ChecktryToEat(pos, new Chess.POS(pos.posX - 1, pos.posY), ref bValidStep) || bEat; if (!bValidStep) result = false; } //当棋子的右方有空位,并且该位置棋子的棋子是对方的棋子时,执行以下代码 else if (pos.hasRight m_Board[pos.posX + 1, pos.posY].type Chess.oppsiteType(type)) { bEat = ChecktryToEat(pos, new Chess.POS(pos.posX + 1, pos.posY), ref bValidStep) || bEat; if (!bValidStep) result = false; } //当棋子的上方有空位,并且该位置棋子的棋子是对方的棋子时,执行以下代码 else if (pos.hasUp && m_Board[pos.posX, pos.posY - 1].type == Chess.oppsiteType(type)) { bEat = ChecktryToEat(pos, new Chess.POS(pos.posX, pos.posY - 1), ref bValidStep) || bEat; if (!bValidStep) result = false; } //当棋子的下方有空位,并且该位置棋子的棋子是对方的棋子时,执行以下代码 else if (pos.hasDown m_Board[pos.posX, pos.posY + 1].type Chess.oppsiteType(type)) 欧阳地创编 && == && == 欧阳地创编 { bEat = ChecktryToEat(pos, new Chess.POS(pos.posX, pos.posY + 1), ref bValidStep) || bEat; if (!bValidStep) result = false; } #endregion // 判断相连的棋子是否还有气。 ArrayList chessBlock; if (!isLive(pos, out chessBlock)) { result= false; } m_Board[pos.posX, pos.posY].type = Chess.ChessType.Empty; return result; } private bool ChecktryToEat(Chess.POS posNewChess, Chess.POS posToEat, ref bool bValidStep) { bValidStep = true; System.Collections.ArrayList chessBlock; if (!isLive(posToEat, out chessBlock))//如果被吃棋子没气了,执行以下代码 { // 处理打劫问题 if (chessBlock.Count == 1) { 欧阳地创编 欧阳地创编 if (m_LastEatten.pos.isValid && posNewChess == m_LastEatten.pos) { bValidStep = false; return false; } } return true; } return false; } /// /// 小于某距离范围内是否有棋子 /// /// /// /// private bool HaveChessDistantWithin(int distant, int X, int Y) { int x = 0, mx = 19; if (X- distant + 1 > 0) { x = X - distant + 1; } if (X + distant < 19) { mx = X + distant; } 欧阳地创编 欧阳地创编 for (; x < mx; ++x) { int y = 0, my = 19; if (Y - distant + 1 > 0) { y = Y - distant + 1; } if (Y + distant < 19) { my = Y + distant; } for (; y < my; ++y) { if (Math.Abs(x - X) + Math.Abs(y - Y) >= distant) continue; if (this.m_Board[x, y].type != Chess.ChessType.Empty) { return true; } } } return false; } private void CopyState(Node n) { for (int i = 0; i < 19; ++i) { 欧阳地创编 欧阳地创编 for (int j = 0; j < 19; ++j) { this.m_Sim_Board[i, j] = new Chess(this.m_Board[i, j].pos, this.m_Board[i, j].type, this.m_Board[i, j].step); } } this.m_Sim_LastChess this.m_LastChess.Copy(); this.m_Sim_LastEatten this.m_LastEatten.Copy(); this.m_Sim_currentStep this.m_currentStep; this.addChessOnSim(n.pos, Chess.oppsiteType(this.m_Sim_LastChess.type)); } /// /// private void play_simulation(Node n) { Chess chs; do { //随机创建棋步 chs = CreatePos(); //棋局结束 if (chs == null) break; this.addChessOnSim(chs.pos, 欧阳地创编 = = = 欧阳地创编 chs.type); } while (true); #region 填子 this.fillBoardWithChessOnSim(); #endregion #region 计算分数 int nBlack = 0; int nWhite = 0; int nPending = 0; for (int i = 0; i < 19; i++) { for (int j = 0; j < 19; j++) { switch j].type) { case Chess.ChessType.Black: case Chess.ChessType.DeadWhite: case Chess.ChessType.MaybeBlack: nBlack++; break; case Chess.ChessType.White: case Chess.ChessType.DeadBlack: case Chess.ChessType.MaybeWhite: nWhite++; 欧阳地创编 (this.m_Sim_Board[i, 欧阳地创编 break; default: nPending++; break; } } } double fBlack (double)nPending / 2; double fWhite (double)nPending / 2; fWhite += 3.75; if ((fBlack > fWhite && this.m_LastChess.type==Chess .ChessType .White)|| (fBlack < fWhite && this.m_LastChess.type == Chess.ChessType.Black)) { //是轮到黑方下棋,切此步黑方占优 //是轮到白方下棋,切此步白方占优 n.update_node(1); /* 更新节点信息 */ } #endregion } /// /// 随机生成下一步合法的棋子 /// /// 欧阳地创编 = = nBlack nWhite + + 欧阳地创编 //获取棋盘所以可以下棋的空点 ArrayList emptyList = new ArrayList(); foreach (Chess c in this.m_Sim_Board) { if (c.type == Chess.ChessType.Empty && c.step == 0) { emptyList.Add(c); } } if (emptyList.Count <= 0) return null; Chess.ChessType type Chess.oppsiteType(this.m_Sim_LastChess.type); Chess.POS pos ((Chess)emptyList[this.r.Next(0, emptyList.Count)]).pos; = = Chess chs = new Chess(pos, type, this.m_Sim_currentStep); return chs; } /// /// 增加一颗棋子在模拟棋盘上 /// /// /// /// public bool addChessOnSim(Chess.POS pos, Chess.ChessType type) { //只允许放黑棋或白棋 欧阳地创编 欧阳地创编 if (type != Chess.ChessType.Black && type != Chess.ChessType.White) return false; // 只允许在空位置上放棋子。 if (this.m_Sim_Board[pos.posX, pos.posY].type != Chess.ChessType.Empty) return false; // 设置当前位置的棋子的类型 this.m_Sim_Board[pos.posX, pos.posY].type = type; #region 判断是否可以提子 bool bEat = false; bool bValidStep = true; //当棋子的左方有空位,并且该位置棋子的棋子是对方的棋子时,执行以下代码 if (pos.hasLeft && this.m_Sim_Board[pos.posX - 1, pos.posY].type == Chess.oppsiteType(type)) { bEat = tryToEatOnSim(pos, new Chess.POS(pos.posX - 1, pos.posY), ref bValidStep) || bEat; if (!bValidStep) return false; } //当棋子的右方有空位,并且该位置棋子的棋子是对方的棋子时,执行以下代码 if (pos.hasRight && this.m_Sim_Board[pos.posX + 1, pos.posY].type == Chess.oppsiteType(type)) { bEat = tryToEatOnSim(pos, new Chess.POS(pos.posX + 1, pos.posY), ref bValidStep) || bEat; 欧阳地创编 欧阳地创编 if (!bValidStep) return false; } //当棋子的上方有空位,并且该位置棋子的棋子是对方的棋子时,执行以下代码 if (pos.hasUp && this.m_Sim_Board[pos.posX, pos.posY - 1].type == Chess.oppsiteType(type)) { bEat = tryToEatOnSim(pos, new Chess.POS(pos.posX, pos.posY - 1), ref bValidStep) || bEat; if (!bValidStep) return false; } //当棋子的下方有空位,并且该位置棋子的棋子是对方的棋子时,执行以下代码 if (pos.hasDown && this.m_Sim_Board[pos.posX, pos.posY + 1].type == Chess.oppsiteType(type)) { bEat = tryToEatOnSim(pos, new Chess.POS(pos.posX, pos.posY + 1), ref bValidStep) || bEat; if (!bValidStep) return false; } #endregion if (!bEat)//把棋子移出棋盘 this.m_Sim_LastEatten.pos.setToInvalid(); // 判断相连的棋子是否还有气。 ArrayList chessBlock; 欧阳地创编 欧阳地创编 if (!isLiveOnSim(pos, out chessBlock)) { if (type == Chess.ChessType.Black) this.m_Sim_Board[pos.posX, pos.posY].type = Chess.ChessType.DeadBlack; else Chess.ChessType.White) if (type == this.m_Sim_Board[pos.posX, pos.posY].type = Chess.ChessType.DeadWhite; return false; //removeChessBlock(chessBlock); } this.m_Sim_LastChess.pos = pos; this.m_Sim_LastChess.type = type; this.m_Sim_LastChess.step this.m_Sim_currentStep; //m_recorder.addStep(new type, this.m_Sim_currentStep)); = Chess(pos, this.m_Sim_Board[pos.posX, pos.posY].step = this.m_Sim_currentStep; ++this.m_Sim_currentStep; return true; } /// /// 判断该棋子是否可以被吃。 /// /// 刚下的棋子 /// 被吃的棋子 /// 欧阳地创编 欧阳地创编 /// private bool tryToEatOnSim(Chess.POS posNewChess, Chess.POS posToEat, ref bool bValidStep) { bValidStep = true; ChessBlock chessBlock; if (!isLiveOnSim(posToEat, out chessBlock))//如果被吃棋子没气了,执行以下代码 { // deal with \"ko(dajie)\" if (chessBlock.Count == 1) { if (this.m_Sim_LastEatten.pos.isValid && posNewChess m_LastEatten.pos) { removeChessOnSim(posNewChess); bValidStep = false; return false; } else { m_Sim_LastEatten.pos posToEat; } } else { 欧阳地创编 == = 欧阳地创编 m_Sim_LastEatten.pos.setToInvalid(); } removeChessBlockOnSim(chessBlock); return true; } return false; } /// /// 判断棋子及相邻的棋子是否有气。 /// /// /// /// private bool isLiveOnSim(Chess.POS pos, out ChessBlock chessBlock) { // two cases need to be handled // 1. Eat others (Include \"jie\") // 2. Be eaten yourself Queue posToProcceed = new Queue();//棋子位置队列 chessBlock = new ArrayList();//棋子位置块,用于记录最终所有相邻的同类的棋子位置 posToProcceed.Enqueue(pos);//把棋子位置添加到队列尾。 chessBlock.Add(pos);//把棋子位置添加到块里。 Chess.ChessType type = this.m_Sim_Board[pos.posX, pos.posY].type;//获取该位置棋子的类型 欧阳地创编 欧阳地创编 while (posToProcceed.Count > 0) { Chess.POS posCurrent = (Chess.POS)posToProcceed.Dequeue();//获取队列的第一个棋子位置 //判断棋子与左边缘是否还有位置 if (posCurrent.hasLeft) { Chess.POS pos1 = new Chess.POS(posCurrent.posX - 1, posCurrent.posY); //左边相邻的位置没有棋子时,该棋子有气。返回true。 if (this.m_Sim_Board[pos1.posX, pos1.posY].type == Chess.ChessType.Empty) return true; if (!posToProcceed.Contains(pos1) && //该位置不在队列里 !chessBlock.Contains(pos1) && //该位置不在块里 this.m_Sim_Board[pos1.posX, pos1.posY].type == type) //该位置的棋子类型与原棋子一样 { //把该棋子添加到队列和块中。 posToProcceed.Enqueue(pos1); chessBlock.Add(pos1); } } //判断棋子与右边缘是否还有位置 if (posCurrent.hasRight) 欧阳地创编 欧阳地创编 { Chess.POS pos1 = new Chess.POS(posCurrent.posX + 1, posCurrent.posY); //右边相邻的位置没有棋子时,该棋子有气。返回true。 if (this.m_Sim_Board[pos1.posX, pos1.posY].type == Chess.ChessType.Empty) return true; if (!posToProcceed.Contains(pos1) && //该位置不在队列里 !chessBlock.Contains(pos1) && //该位置不在块里 this.m_Sim_Board[pos1.posX, pos1.posY].type == type) //该位置的棋子类型与原棋子一样 { //把该棋子添加到队列和块中。 posToProcceed.Enqueue(pos1); chessBlock.Add(pos1); } } //判断棋子与上边缘是否还有位置 if (posCurrent.hasUp) { Chess.POS pos1 = new Chess.POS(posCurrent.posX, posCurrent.posY - 1); //上边相邻的位置没有棋子时,该棋子有气。返回true。 if (this.m_Sim_Board[pos1.posX, pos1.posY].type == Chess.ChessType.Empty) return true; 欧阳地创编 欧阳地创编 if (!posToProcceed.Contains(pos1) && //该位置不在队列里 !chessBlock.Contains(pos1) && //该位置不在块里 this.m_Sim_Board[pos1.posX, pos1.posY].type == type) //该位置的棋子类型与原棋子一样 { //把该棋子添加到队列和块中。 posToProcceed.Enqueue(pos1); chessBlock.Add(pos1); } } //判断棋子与下边缘是否还有位置 if (posCurrent.hasDown) { Chess.POS pos1 = new Chess.POS(posCurrent.posX, posCurrent.posY + 1); //下边相邻的位置没有棋子时,该棋子有气。返回true。 if (this.m_Sim_Board[pos1.posX, pos1.posY].type == Chess.ChessType.Empty) return true; if (!posToProcceed.Contains(pos1) && //该位置不在队列里 !chessBlock.Contains(pos1) && //该位置不在块里 this.m_Sim_Board[pos1.posX, pos1.posY].type == type) //该位置的棋子类型与原棋子一样 欧阳地创编 欧阳地创编 { //把该棋子添加到队列和块中。 posToProcceed.Enqueue(pos1); chessBlock.Add(pos1); } } } return false; } /// /// 模拟提子(移出一组指定的棋子) /// /// private void removeChessBlockOnSim(ChessBlock chessBlock) { foreach (Chess.POS pos in chessBlock) { //this.m_Sim_Board[pos.posX, pos.posY].type = Chess.ChessType.Empty; //上一步是黑子,当前是白子下棋,所以吃掉的棋子是黑子。 if (this.m_Sim_LastChess.type == Chess.ChessType.Black) this.m_Sim_Board[pos.posX, pos.posY].type = Chess.ChessType.DeadBlack; else this.m_Sim_Board[pos.posX, pos.posY].type = Chess.ChessType.DeadWhite; 欧阳地创编 欧阳地创编 } } /// /// 模拟提子(移出一颗指定的棋子) /// /// private void removeChessOnSim(Chess.POS pos) { Chess.ChessType type this.m_Sim_Board[pos.posX, pos.posY].type; if (type == Chess.ChessType.Black) this.m_Sim_Board[pos.posX, pos.posY].type = Chess.ChessType.DeadBlack; else if (type == Chess.ChessType.White) this.m_Sim_Board[pos.posX, pos.posY].type = Chess.ChessType.DeadWhite; } /// /// 获取得分最高的候选棋步 /// /// /// if (move_Node.Count <= 0) { return null; } 欧阳地创编 = Node GetBestChild(List 欧阳地创编 List if (temp1.Count == 0) { temp1.Add(node); } else if (node.wins > temp1[0].wins) { temp1.Clear(); temp1.Add(node); } else temp1[0].wins) { temp1.Add(node); } } List Chess.POS pos = node.pos; if (Math.Abs(this.m_LastChess.pos.posX - pos.posX) <= 1 || Math.Abs(this.m_LastChess.pos.posY - pos.posY) <= 1) { temp2.Add(node); 欧阳地创编 if (node.wins == 欧阳地创编 continue; } if (this.HaveChessDistantWithin(3, pos.posX, pos.posY)) { temp2.Add(node); } } Node result ; if (temp2.Count > 0) result 1)]; else result 1)]; return result; } #endregion ==== /// = temp2[r.Next(temp2.Count - = temp1[r.Next(temp1.Count - 单人游戏时 ==== 重新计算棋盘大小,以适应窗体的大小变化 开始位置横坐标 开始位置纵坐标 长度 高度 void ReSize(float x,float y,float 欧阳地创编 欧阳地创编 float v = height / 21; margin_top = y + v ; margin_left = x + v + (width - height) / 2; gap = v; chessSize = 3 * v / 7; numberSize = 2 * v / 5; starSize = v / 5; } else { float v = width / 21; margin_top = y + v + (height - width) / 2; margin_left = x + v; gap = v; chessSize = 3 * v / 7; numberSize = 2 * v / 5; starSize = v / 5; } } } } / 服务端程序: //-------------User.cs----------------// using System.Net.Sockets; using System.IO; namespace GameServer 欧阳地创编 欧阳地创编 { class User { public TcpClient client; public StreamReader sr; public StreamWriter sw; public string userName; public User(TcpClient client) { this.client = client; this.userName = \"\"; NetworkStream client.GetStream(); netStream = sr = new StreamReader(netStream, System.Text.Encoding.UTF8); sw = new StreamWriter(netStream, System.Text.Encoding.UTF8); } } } //-------------FormServer.cs------------------// using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; //添加的命名空间 欧阳地创编 欧阳地创编 using System.Net; using System.Net.Sockets; using System.Threading; using System.IO; namespace GameServer { public partial class FormServer : Form { //游戏室允许进入的最多人数 private int maxUsers; //连接的用户 System.Collections.Generic.List private GameTable[] gameTable; //使用的本机IP地址 IPAddress localAddress; //监听端口 private int port = 51888; private TcpListener myListener; private Service service; public FormServer() { InitializeComponent(); service = new Service(listBox1); } //加载窗体时触发的事件 private void FormServer_Load(object sender, 欧阳地创编 欧阳地创编 EventArgs e) { listBox1.HorizontalScrollbar = true; IPAddress[] addrIP Dns.GetHostAddresses(Dns.GetHostName()); localAddress = addrIP[0]; buttonStop.Enabled = false; } //【开始服务】按钮的Click事件 private void sender, EventArgs e) { if (int.TryParse(textBoxMaxTables.Text, out maxTables) == false || int.TryParse(textBoxMaxUsers.Text, out maxUsers) == false) { MessageBox.Show(\"请输入在规定范围内的正整数\"); return; } if (maxUsers < 1 || maxUsers > 300) { MessageBox.Show(\"允许进入的人数只能在1-300之间\"); return; } if (maxTables < 1 || maxTables > 100) { MessageBox.Show(\"允许的桌数只能在 欧阳地创编 = buttonStart_Click(object 欧阳地创编 1-100之间\"); return; } textBoxMaxUsers.Enabled = false; textBoxMaxTables.Enabled = false; //初始化数组 gameTable = new GameTable[maxTables]; for (int i = 0; i < maxTables; i++) { gameTable[i] GameTable(listBox1); } myListener = TcpListener(localAddress, port); myListener.Start(); service.SetListBox(string.Format(\"开始在{0}:{1}监听客户连接\ //创建一个线程监听客户端连接请求 ThreadStart ts ThreadStart(ListenClientConnect); myThread.Start(); buttonStart.Enabled = false; buttonStop.Enabled = true; } //【停止服务】按钮的Click事件 private void buttonStop_Click(object sender, EventArgs e) { //停止向游戏桌发送棋子 欧阳地创编 = new new = new Thread myThread = new Thread(ts); 欧阳地创编 service.SetListBox(string.Format(\"目前连接用户数:{0}\ service.SetListBox(\"开始停止服务,并依次使用户退出!\"); for (int i = 0; i < userList.Count; i++) { //关闭后,客户端接收字符串为null, //使接收该客户的线程ReceiveData接收的字符串也为null, //从而达到结束线程的目的 userList[i].client.Close(); } //通过停止监听让myListener.AcceptTcpClient()产生异常退出监听线程 myListener.Stop(); buttonStart.Enabled = true; buttonStop.Enabled = false; textBoxMaxUsers.Enabled = true; textBoxMaxTables.Enabled = true; } //接收客户端连接 private void ListenClientConnect() { while (true) { TcpClient newClient = null; try { //等待用户进入 newClient 欧阳地创编 = 欧阳地创编 myListener.AcceptTcpClient(); } catch { //当单击“停止监听”或者退出此窗体时AcceptTcpClient()会产生异常 //因此可以利用此异常退出循环 break; } //每接受一个客户端连接,就创建一个对应的线程循环接收该客户端发来的信息 ParameterizedThreadStart pts = new ParameterizedThreadStart(ReceiveData); Thread Thread(pts); threadReceive = new User user = new User(newClient); threadReceive.Start(user); userList.Add(user); service.SetListBox(string.Format(\"{0}newClient.Client.RemoteEndPoint)); 进 入 \ service.SetListBox(string.Format(\"当前连接用户数:{0}\ } } //接收、处理客户端信息,每客户1个线程,参数用于区分是哪个客户 private void ReceiveData(object obj) { User user = (User)obj; TcpClient client = user.client; 欧阳地创编 欧阳地创编 //是否正常退出接收线程 bool normalExit = false; //用于控制是否退出循环 bool exitWhile = false; while (exitWhile == false) { string receiveString = null; try { receiveString user.sr.ReadLine(); } catch { //该客户底层套接字不存在时会出现异常 service.SetListBox(\"接收数据失败\"); } //TcpClient对象将套接字进行了封装,如果TcpClient对象关闭了, //但是底层套接字未关闭,并不产生异常,但是读取的结果为null if (receiveString == null) { if (normalExit == false) { //如果停止了监听,Connected为false if (client.Connected == true) 欧阳地创编 = 欧阳地创编 { service.SetListBox(string.Format( \"与{0}失去联系,已终止接收该用户信息\ client.Client.RemoteEndPoint)); } //如果该用户正在游戏桌上,则退出游戏桌 RemoveClientfromPlayer(user); } //退出循环 break; } service.SetListBox(string.Format(\"来自{0}:{1}\user.userName, receiveString)); string[] receiveString.Split(','); splitString = int tableIndex = -1; //桌号 int side = -1; //座位号 int anotherSide = -1; //对方座位号 string sendString = \"\"; switch (splitString[0]) { case \"Login\": //格式:Login,昵称 //该用户刚刚登录 if 欧阳地创编 (userList.Count > 欧阳地创编 maxUsers) { sendString = \"Sorry\"; service.SendToOne(user, sendString); service.SetListBox(\"人数已满,拒绝\" + splitString[1] + \"进入游戏室\"); exitWhile = true; } else //将用户昵称保存到用户列表中 //由于是引用类型,因此直接给user赋值也就是给userList中对应的user赋值 //用户名中包含其IP和端口的目的是为了帮助理解,实际游戏 //中一般不会显示IP的 user.userName string.Format(\"[{0}--{1}]\ client.Client.RemoteEndPoint); //允许该用户进入游戏室,即将各桌是否有人情况发送给该用户 sendString = \"Tables,\" + this.GetOnlineString(); service.SendToOne(user, sendString); } break; case \"Logout\": //格式:Logout 欧阳地创编 = 欧阳地创编 //用户退出游戏室 service.SetListBox(string.Format(\"{0}退出游戏室\user.userName)); normalExit = true; exitWhile = true; break; case \"SitDown\": //格式:SitDown,桌号,座位号 //该用户坐到某座位上 tableIndex int.Parse(splitString[1]); side int.Parse(splitString[2]); gameTable[tableIndex].gamePlayer[side].user user; = = = gameTable[tableIndex].gamePlayer[side].someone = true; service.SetListBox(string.Format( \"{0}在第{1}桌第{2}座入座\ user.userName, tableIndex + 1, side + 1)); //得到对家座位号 anotherSide = (side + 1) % 2; //判断对方是否有人 if (gameTable[tableIndex].gamePlayer[anotherSide].someone == true) 欧阳地创编 欧阳地创编 { //先告诉该用户对家已经入座 //发送格式:SitDown,座位号,用户名 sendString string.Format(\"SitDown,{0},{1}\ = gameTable[tableIndex].gamePlayer[anotherSide].user.userName); service.SendToOne(user, sendString); } //同时告诉两个用户该用户入座(也可能对方无人) //发送格式:SitDown,座位号,用户名 sendString string.Format(\"SitDown,{0},{1}\user.userName); service.SendToBoth(gameTable[tableIndex], sendString); //重新将游戏室各桌情况发送给所有用户 service.SendToAll(userList, this.GetOnlineString()); break; case \"GetUp\": //格式:GetUp,桌号,座位号 //用户离开座位,回到游戏室 tableIndex int.Parse(splitString[1]); side 欧阳地创编 = side, \"Tables,\" + = = 欧阳地创编 int.Parse(splitString[2]); service.SetListBox( string.Format(\"{0}离座,返回游戏室\ //将离座信息同时发送给两个用户,以便客户端作离座处理 //发送格式:GetUp,座位号,用户名 service.SendToBoth(gameTable[tableIndex], string.Format(\"GetUp,{0},{1}\user.userName)); //服务器进行离座处理 gameTable[tableIndex].gamePlayer[side].someone = false; gameTable[tableIndex].gamePlayer[side].started = false; gameTable[tableIndex].gamePlayer[side].grade = 0; anotherSide = (side + 1) % 2; if (gameTable[tableIndex].gamePlayer[anotherSide].someone == true) { gameTable[tableIndex].gamePlayer[anotherSide].started = false; gameTable[tableIndex].gamePlayer[anotherSide].grade = 0; } //重新将游戏室各桌情况发 欧阳地创编 side, 欧阳地创编 送给所有用户 service.SendToAll(userList, this.GetOnlineString()); break; case \"Level\": //格式:Time,桌号,难度级别 //设置难度级别 break; case \"Talk\": //格式:Talk,桌号,对话内容 tableIndex int.Parse(splitString[1]); = \"Tables,\" + //由于说话内容可能包含逗号,所以需要特殊处理 sendString string.Format(\"Talk,{0},{1}\ receiveString.Substring(splitString[0].Length + splitString[1].Length)); service.SendToBoth(gameTable[tableIndex], sendString); break; case \"Ready\": //格式:Start,桌号,座位号 //该用户单击了开始按钮 tableIndex int.Parse(splitString[1]); side int.Parse(splitString[2]); 欧阳地创编 = = = 欧阳地创编 gameTable[tableIndex].gamePlayer[side].started = true; if (side == 0) { anotherSide = 1; sendString = \"Message,黑方已准备。\"; } else { anotherSide = 0; sendString = \"Message,白方已准备。\"; } service.SendToBoth(gameTable[tableIndex], sendString); if (gameTable[tableIndex].gamePlayer[anotherSide].started == true) { service.SendToBoth(gameTable[tableIndex], \"Start,游戏开始。\"); } break; case \"NotReady\": tableIndex int.Parse(splitString[1]); side int.Parse(splitString[2]); = = gameTable[tableIndex].gamePlayer[side].started = false; 欧阳地创编 欧阳地创编 if (side == 0) { sendString = \"Message,黑方取消准备。\"; } else { sendString = \"Message,白方取消准备。\"; } service.SendToBoth(gameTable[tableIndex], sendString); //gameTable[tableIndex].StartTimer(); break; case \"UnsetDot\": //格式:UnsetDot,桌号,座位号,行,列,颜色 //消去客户单击的棋子 tableIndex int.Parse(splitString[1]); side int.Parse(splitString[2]); int int.Parse(splitString[3]); int int.Parse(splitString[4]); int int.Parse(splitString[5]); xi xj color = = = = = gameTable[tableIndex].UnsetDot(xi, xj, color); break; 欧阳地创编 欧阳地创编 case \"SetDot\": //格式:SetDot,桌号,座位号,行,列 //消去客户单击的棋子 tableIndex int.Parse(splitString[1]); side int.Parse(splitString[2]); = = anotherSide = (side + 1) % 2; service.SendToOne(gameTable[tableIndex].gamePlayer[anotherSide].user, receiveString); gameTable[tableIndex].gamePlayer[anotherSide].pass = false; break; case \"Pass\": //格式:Pass,桌号,座位号 tableIndex int.Parse(splitString[1]); side int.Parse(splitString[2]); = = anotherSide = (side + 1) % 2; gameTable[tableIndex].gamePlayer[side].pass true; = if (gameTable[tableIndex].gamePlayer[anotherSide].pass) { //双方都pass,棋局结束 service.SendToBoth(gameTable[tableIndex], 欧阳地创编 欧阳地创编 \"GameOver\"); gameTable[tableIndex].gamePlayer[side].pass false; = gameTable[tableIndex].gamePlayer[anotherSide].pass = false; gameTable[tableIndex].gamePlayer[side].started = false; gameTable[tableIndex].gamePlayer[anotherSide].started = false; } else { service.SendToOne(gameTable[tableIndex].gamePlayer[anotherSide].user, receiveString); } break; case \"Lose\": //格式:Lose,桌号,座位号 tableIndex int.Parse(splitString[1]); side int.Parse(splitString[2]); = = anotherSide = (side + 1) % 2; service.SendToOne(gameTable[tableIndex].gamePlayer[anotherSide].user, receiveString); gameTable[tableIndex].gamePlayer[side].pass false; 欧阳地创编 = 欧阳地创编 gameTable[tableIndex].gamePlayer[anotherSide].pass = false; gameTable[tableIndex].gamePlayer[side].started = false; gameTable[tableIndex].gamePlayer[anotherSide].started = false; break; default: service.SendToAll(userList, \"什么意思啊:\" + receiveString); break; } } userList.Remove(user); client.Close(); service.SetListBox(string.Format(\"有一个退出,剩余连接用户数:{0}\ } // 循环检测该用户是否坐到某游戏桌上,如果是,将其从游戏桌上移除,并终止该桌游戏 private void RemoveClientfromPlayer(User user) { for (int i = 0; i < gameTable.Length; i++) { for (int j = 0; j < 2; j++) { if (gameTable[i].gamePlayer[j].user != null) 欧阳地创编 欧阳地创编 { //判断是否同一个对象 if (gameTable[i].gamePlayer[j].user == user) { StopPlayer(i, j); return; } } } } } //停止第i桌游戏 private void StopPlayer(int i, int j) { gameTable[i].gamePlayer[j].someone = false; gameTable[i].gamePlayer[j].started = false; gameTable[i].gamePlayer[j].grade = 0; int otherSide = (j + 1) % 2; if (gameTable[i].gamePlayer[otherSide].someone true) { gameTable[i].gamePlayer[otherSide].started false; gameTable[i].gamePlayer[otherSide].grade = 0; if (gameTable[i].gamePlayer[otherSide].user.client.C 欧阳地创编 == = 欧阳地创编 onnected == true) { //发送格式:Lost,座位号,用户名 service.SendToOne(gameTable[i].gamePlayer[otherSide].user, string.Format(\"Lost,{0},{1}\ j, gameTable[i].gamePlayer[j].user.userName)); } } } //获取每桌是否有人的字符串,每座用一位表示,0表示无人,1表示有人 private string GetOnlineString() { string str = \"\"; for (int i = 0; i < gameTable.Length; i++) { for (int j = 0; j < 2; j++) { str += gameTable[i].gamePlayer[j].someone == true ? \"1\" : \"0\"; } } return str; } //关闭窗体前触发的事件 欧阳地创编 欧阳地创编 private FormDDServer_FormClosing(object FormClosingEventArgs e) { void sender, //未单击开始服务就直接退出时,myListener为null if (myListener != null) { buttonStop_Click(null, null); } } } } //---------------Service.cs-------------------// using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms; using System.Net.Sockets; using System.IO; namespace GameServer { class Service { private ListBox listbox; //用于线程间互操作 private delegate SetListBoxCallback(string str); private setListBoxCallback; 欧阳地创编 void SetListBoxCallback 欧阳地创编 public Service(ListBox listbox) { this.listbox = listbox; setListBoxCallback SetListBoxCallback(SetListBox); } public void SetListBox(string str) { //比较调用SetListBox方法的线程和创建listBox1的线程是否同一个线程 //如果不是,则listBox1的InvokeRequired为true if (listbox.InvokeRequired) { //结果为true,则通过代理执行else中的代码,并传入需要的参数 listbox.Invoke(setListBoxCallback, str); } else { //结果为false,直接执行 listbox.Items.Add(str); listbox.SelectedIndex listbox.Items.Count - 1; listbox.ClearSelected(); } } public void SendToOne(User user, string str) { try 欧阳地创编 = new = 欧阳地创编 { user.sw.WriteLine(str); user.sw.Flush(); SetListBox(string.Format(\"向{0}发送{1}\ } catch { SetListBox(string.Format(\"向{0}发送信息失败\ } } public void SendToBoth(GameTable gameTable, string str) { for (int i = 0; i < 2; i++) { if (gameTable.gamePlayer[i].someone == true) { SendToOne(gameTable.gamePlayer[i].user, str); } } } public void SendToAll(System.Collections.Generic.List for (int i = 0; i < userList.Count; i++) { 欧阳地创编 欧阳地创编 SendToOne(userList[i], str); } } } } //---------------Program.cs--------------// using System; using System.Collections.Generic; using System.Windows.Forms; namespace GameServer { static class Program { /// /// The main entry point for the application. /// static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new FormServer()); } } } 结语 本游戏软件启发于陈春丽面向对象编程课程,许多程 欧阳地创编 欧阳地创编 序功能设计都源于陈老师的启发,在此,感谢陈春丽老师的大力支持。 时间:2021.03.04 创作:欧阳地 欧阳地创编 因篇幅问题不能全部显示,请点此查看更多更全内容