c#版五子棋AI人机对战
五子棋exe文件:http://photo.jiajiajia.club/file/wuziqi.exe
扫雷exe文件:http://photo.jiajiajia.club/file/sl.exe
资源文件
项目布局
主类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
页面设计
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
partial class Form1
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
private Ready re=new Ready(17,17);
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows 窗体设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
///
public static int s=0;
public static bool[,,] wins;
//五子棋的所有赢法,前两维代表棋盘,第三位代表所有赢法,每一个棋子都可以有多种赢法。
public static int[] myWin;//我方第i中赢法中,有n颗棋子,如果有5颗棋子代表已经赢了,例如:myWin[5]=2;代表第5中赢法中,已经有2颗棋子,
public static int[] computerWin;//计算机方第i中赢法中,有n颗棋子
public static int[,] chessBorad;//代表棋盘,值0代表没有下棋子,其他值代表已经下棋子了。
public static bool myFirst = true;
public bool me = true;//true代表应该我方下棋
public bool over = false;//游戏是否结束
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
this.panel1 = new System.Windows.Forms.Panel();
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
this.菜单ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.退出ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.重新开始游戏ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.帮助ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.checkBox1 = new System.Windows.Forms.CheckBox();
this.checkBox2 = new System.Windows.Forms.CheckBox();
this.button1 = new System.Windows.Forms.Button();
this.menuStrip1.SuspendLayout();
this.SuspendLayout();
//
// panel1
//
this.panel1.AutoSize = true;
this.panel1.BackColor = System.Drawing.SystemColors.GradientActiveCaption;
this.panel1.BackgroundImage = global::WindowsFormsApplication2.Properties.Resources.background3;
this.panel1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.panel1.Location = new System.Drawing.Point(10, 31);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(612, 612);
this.panel1.TabIndex = 0;
this.panel1.Paint += new System.Windows.Forms.PaintEventHandler(this.panel1_Paint);
this.panel1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.panel1_MouseClick);
//
// menuStrip1
//
this.menuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20);
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.菜单ToolStripMenuItem,
this.重新开始游戏ToolStripMenuItem,
this.帮助ToolStripMenuItem});
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
this.menuStrip1.Name = "menuStrip1";
this.menuStrip1.Size = new System.Drawing.Size(634, 28);
this.menuStrip1.TabIndex = 1;
this.menuStrip1.Text = "menuStrip1";
//
// 菜单ToolStripMenuItem
//
this.菜单ToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.退出ToolStripMenuItem});
this.菜单ToolStripMenuItem.Name = "菜单ToolStripMenuItem";
this.菜单ToolStripMenuItem.Size = new System.Drawing.Size(51, 24);
this.菜单ToolStripMenuItem.Text = "菜单";
//
// 退出ToolStripMenuItem
//
this.退出ToolStripMenuItem.Name = "退出ToolStripMenuItem";
this.退出ToolStripMenuItem.Size = new System.Drawing.Size(144, 26);
this.退出ToolStripMenuItem.Text = "退出游戏";
this.退出ToolStripMenuItem.Click += new System.EventHandler(this.退出ToolStripMenuItem_Click);
//
// 重新开始游戏ToolStripMenuItem
//
this.重新开始游戏ToolStripMenuItem.Name = "重新开始游戏ToolStripMenuItem";
this.重新开始游戏ToolStripMenuItem.Size = new System.Drawing.Size(111, 24);
this.重新开始游戏ToolStripMenuItem.Text = "重新开始游戏";
this.重新开始游戏ToolStripMenuItem.Click += new System.EventHandler(this.重新开始游戏ToolStripMenuItem_Click);
//
// 帮助ToolStripMenuItem
//
this.帮助ToolStripMenuItem.Name = "帮助ToolStripMenuItem";
this.帮助ToolStripMenuItem.Size = new System.Drawing.Size(51, 24);
this.帮助ToolStripMenuItem.Text = "帮助";
this.帮助ToolStripMenuItem.Click += new System.EventHandler(this.帮助ToolStripMenuItem_Click);
//
// checkBox1
//
this.checkBox1.AutoSize = true;
this.checkBox1.Checked = true;
this.checkBox1.CheckState = System.Windows.Forms.CheckState.Checked;
this.checkBox1.Location = new System.Drawing.Point(260, 6);
this.checkBox1.Name = "checkBox1";
this.checkBox1.Size = new System.Drawing.Size(74, 19);
this.checkBox1.TabIndex = 2;
this.checkBox1.Text = "我优先";
this.checkBox1.UseVisualStyleBackColor = true;
this.checkBox1.Click += new System.EventHandler(this.checkBox1_Click);
//
// checkBox2
//
this.checkBox2.AutoSize = true;
this.checkBox2.Location = new System.Drawing.Point(340, 6);
this.checkBox2.Name = "checkBox2";
this.checkBox2.Size = new System.Drawing.Size(104, 19);
this.checkBox2.TabIndex = 3;
this.checkBox2.Text = "计算机优先";
this.checkBox2.UseVisualStyleBackColor = true;
this.checkBox2.Click += new System.EventHandler(this.checkBox2_Click);
//
// button1
//
this.button1.Location = new System.Drawing.Point(512, 3);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(110, 23);
this.button1.TabIndex = 4;
this.button1.Text = "悔棋(0)";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click_1);
//
// Form1
//
//this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(634, 654);
this.Controls.Add(this.button1);
this.Controls.Add(this.checkBox2);
this.Controls.Add(this.checkBox1);
this.Controls.Add(this.panel1);
this.Controls.Add(this.menuStrip1);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MainMenuStrip = this.menuStrip1;
this.Name = "Form1";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "五子棋";
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
void init()
{
wins = re.initChess();
myWin = re.getMyWin();
computerWin = re.getConputerWin();
chessBorad = re.getChessBorad();
}
#endregion
private PictureBox pictureBox2;
private PictureBox pictureBox1;
private Panel panel1;
private MenuStrip menuStrip1;
private ToolStripMenuItem 菜单ToolStripMenuItem;
private ToolStripMenuItem 退出ToolStripMenuItem;
private ToolStripMenuItem 重新开始游戏ToolStripMenuItem;
private ToolStripMenuItem 帮助ToolStripMenuItem;
private CheckBox checkBox1;
private CheckBox checkBox2;
private Button button1;
}
}
主要逻辑代码
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
/**
* 记录三步状态
* */
MyList<State> states = new MyList<State>();
public Form1()
{
InitializeComponent();
init();
if (!myFirst)
{
me = !me;
winJudge(8,8);
MessageBox.Show(me + "");
}
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
}
private void pictureBox1_Click(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
}
private void panel1_MouseClick(object sender, MouseEventArgs e)
{
if (!me || over)
{//如果不该我方下棋或已结束,则返回
return;
}
int i = e.X;//棋盘位置(像素)
int j = e.Y;//棋盘位置(像素)
int px = i % 36;//通过鼠标点击的位置计算棋子应该下的位置
int py = j % 36;//通过鼠标点击的位置计算棋子应该下的位置
i = i - (px) + (px <= 18 ? -18 : 18);//通过鼠标点击的位置计算棋子应该下的位置
j = j - (py) + (py <= 18 ? -18 : 18);//通过鼠标点击的位置计算棋子应该下的位置
int x = (i + 18) / 36;//坐标位置(数组)
int y = (j + 18) / 36;//坐标位置(数组)
if (x == 0 || y == 0 || x >= 17 || y >= 17)
{//规则:第一行,第一列不能下棋。
MessageBox.Show(i + "," + j + ":" + x + "," + y);
return;
}
//paintNode(i, j);
myStep(i, j, x, y);
}
public void myStep(int i, int j, int x, int y)
{
if (chessBorad[x,y] == 0)
{
//下棋之前记住改变的状态
State s;
//s = new State();
if (states.count>=6)
{
s = states.getAndRemoveLast();
s.k_valueList = new ArrayList();
}
else
{
s = new State();
}
s.x = x;
s.y = y;
//先记录坐标
s.pictureBox = paintNode(i, j);
chessBorad[x,y] = 1;
for (int k = 0; k < re.getCount(); k++)
{
if (wins[x,y,k])
{
//直接之前的k中赢发的状态值
s.k_valueList.Add(new K_Value(k,myWin[k],computerWin[k]));
myWin[k]++;
computerWin[k] = 999;
if (myWin[k] == 5)
{
MessageBox.Show("你赢了");
over = true;
return;
}
}
}
states.add(s);
}
me = !me;
computerStep();
if (hui<3)
{
hui++;
button1.Text = "悔棋("+hui+")";
}
}
/**
* 计算机下棋
*/
public void computerStep()
{
if (over)
{//游戏结束
return;
}
int[,] myScore = new int[17, 17];//评估我方评分
int[,] computerScore = new int[17, 17];//评估计算机评分
int max = 0;
int x = 0;
int y = 0;
// 遍历棋盘
for (int i = 1; i< 17; i++) {//x轴
for (int j = 1; j< 17; j++) {//y轴
if (chessBorad[i,j] == 0) {// 当前可落子,如果不等于0代表已经有棋子
for (int k = 0; k<re.getCount(); k++) { // 每个点都在 多种赢法中,所以要遍历所有赢法
if (wins[i,j,k]) {// 计算他在K赢法中的 重要性
switch (myWin[k]) {//我方棋路,当前赢法中已经连上了几颗棋子
case 1:
myScore[i,j] += 200;
break;
case 2:
myScore[i,j] += 400;
break;
case 3:
myScore[i,j] += 2000;
break;
case 4:
myScore[i,j] += 10000;
break;
}
switch (computerWin[k]) {//计算机棋路,当前赢法中已经连上了几颗棋子
case 1:
computerScore[i,j] += 300;
break;
case 2:
computerScore[i,j] += 500;
break;
case 3:
computerScore[i,j] += 3000;
break;
case 4:
computerScore[i,j] += 20000;
break;
}
}
}
// 玩家最重要的落点
if (myScore[i,j] > max) {
max = myScore[i,j];
x = i;
y = j;
} else if (myScore[i,j] == max) {
if (computerScore[i,j] > computerScore[x,y]) { //
x = i;
y = j;
}
}
// AI最重要的落点
if (computerScore[i,j] > max) {
max = computerScore[i,j];
x = i;
y = j;
} else if (computerScore[i,j] == max) {
if (myScore[i,j] > myScore[x,y]) {
x = i;
y = j;
}
}
}
}
}
winJudge(x,y);
}
void winJudge(int x,int y)
{
//下棋之前记住改变的状态
State s;
//s = new State();
if (states.count >= 6)
{
s = states.getAndRemoveLast();
s.k_valueList = new ArrayList();
}
else
{
s = new State();
}
s.x = x;
s.y = y;
//记住坐标
s.pictureBox=paintNode(x * 36 - 18, y * 36 - 18);//下棋
chessBorad[x, y] = 2;//棋盘标记已下棋
for (int k = 0; k < re.getCount(); k++)
{//遍历所有的赢法
if (wins[x, y, k])
{//如果(x,y)这个点在某一种赢法中
//记录之前的k中赢发的状态值
s.k_valueList.Add(new K_Value(k, myWin[k], computerWin[k]));
computerWin[k]++; //那么该种赢法中有多了一个棋子
myWin[k] = 999; //那么我方的这种赢法就不可能赢了,设一个异常的值
if (computerWin[k] == 5)
{ //如果计算机在某种赢法上连上了五个子,那么计算机就赢了,我方就输了
MessageBox.Show("你输了");
over = true; //结束游戏
return;
}
}
}
states.add(s);
if (!over)
{//如果没有结束游戏
me = !me;//换我方下棋
}
}
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
public PictureBox paintNode(int x,int y)
{
PictureBox pictureBox = new PictureBox();
((System.ComponentModel.ISupportInitialize)(pictureBox)).BeginInit();
pictureBox.BackColor = System.Drawing.Color.Transparent;
if (me)
{
pictureBox.Image = WindowsFormsApplication2.Properties.Resources.b;
}
else
{
pictureBox.Image = WindowsFormsApplication2.Properties.Resources.w;
}
pictureBox.Location = new System.Drawing.Point(x, y);
pictureBox.Size = new System.Drawing.Size(36, 36);
pictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
pictureBox.TabIndex = 0;
pictureBox.TabStop = false;
this.panel1.Controls.Add(pictureBox);
((System.ComponentModel.ISupportInitialize)(pictureBox)).EndInit();
return pictureBox;
}
private void pictureBox2_Click(object sender, EventArgs e)
{
}
private void pictureBox3_Click(object sender, EventArgs e)
{
}
private void 开始ToolStripMenuItem_Click(object sender, EventArgs e)
{
}
private void 最初ToolStripMenuItem_Click(object sender, EventArgs e)
{
}
private void 重新开始游戏ToolStripMenuItem_Click(object sender, EventArgs e)
{
states = new MyList<State>();
this.panel1.Controls.Clear();
init();
over = false;
me = true;
hui = 0;
button1.Text = "悔棋(0)";
if (!myFirst)
{
me = !me;
winJudge(8, 8);
}
}
private void 帮助ToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show("五子棋都不会!还有脸点帮助");
}
private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
{
System.Environment.Exit(0);
}
private void checkBox1_Click(object sender, EventArgs e)
{
checkBox2.Checked = false;
checkBox1.Checked = true;
myFirst = true;
}
private void checkBox2_Click(object sender, EventArgs e)
{
checkBox1.Checked = false;
checkBox2.Checked = true;
myFirst = false;
}
int hui = 0;
//悔棋
private void button1_Click_1(object sender, EventArgs e)
{
if (over)
{
MessageBox.Show("游戏结束");
return;
}
if (!me)
{
MessageBox.Show("等待对方下棋");
}
if (states.count<=1)
{
MessageBox.Show("无法退棋");
return;
}
reStep();
reStep();
hui--;
button1.Text = "悔棋(" + hui + ")";
}
public void reStep()
{
State s = states.getAndRemoveFirst();
if (s != null)
{
chessBorad[s.x, s.y] = 0;
for (int i = 0; i < s.k_valueList.Count; i++)
{
K_Value k = (K_Value)s.k_valueList[i];
myWin[k.k] = k.myWinValue;
computerWin[k.k] = k.computerWinValue;
}
s.pictureBox.Dispose();
}
}
private void button2_Click(object sender, EventArgs e)
{
}
}
}
数据结构,容器,工具等
using System.Collections;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
class Ready
{
public int x;
public int y;
public int count;
public int getCount()
{
return this.count;
}
/**
* 计算所有赢法种类
* @return
*/
public Ready(int x, int y)
{
this.x = x;
this.y = y;
count = initCount();
}
private int initCount()
{
int count = 0;
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y - 4; j++)
{
count++;
}
}
// 横线上
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y - 4; j++)
{
count++;
}
}
// 斜线上
for (int i = 0; i < x - 4; i++)
{
for (int j = 0; j < y - 4; j++)
{
count++;
}
}
// 反斜线上
for (int i = 0; i < x - 4; i++)
{
for (int j = y - 1; j > 3; j--)
{
count++;
}
}
return count;
}
/**
* 初始化所有赢法
* @param c
* @return
*/
public bool[,,] initChess()
{
bool[,,] wins =new bool[x,y,count];
int counts = 0;
for (int i = 0; i<x; i++) {
for (int j = 0; j<y-4; j++) {
for (int k = 0; k< 5; k++) {
wins[i,j + k,counts] = true;
}
counts++;
}
}
for (int i = 0; i<x; i++) {
for (int j = 0; j<y-4; j++) {
for (int k = 0; k< 5; k++) {
wins[j + k,i, counts] = true;
}
counts++;
}
}
for (int i = 0; i<x-4; i++) {
for (int j = 0; j<y-4; j++) {
for (int k = 0; k< 5; k++) {
wins[i + k,j + k, counts] = true;
}
counts++;
}
}
for (int i = 0; i<x-4; i++) {
for (int j = y - 1; j > 3; j--) {
for (int k = 0; k< 5; k++) {
wins[i + k,j - k, counts] = true;//记录赢得可能性
}
counts++;
}
}
return wins;
}
public int[] getMyWin()
{
int[] myWin = new int[count];
return myWin;
}
public int[] getConputerWin()
{
int[] conputer = new int[count];
return conputer;
}
/**
* 初始化棋盘
* @return
*/
public int[,] getChessBorad()
{
int[,] chessBorad = new int[x,y];
return chessBorad;
}
}
class State
{
public int x;
public int y;
public PictureBox pictureBox;
public ArrayList k_valueList = new ArrayList();
}
class K_Value
{
public K_Value(int k,int myWinValue,int computerWinValue)
{
this.k = k;
this.myWinValue = myWinValue;
this.computerWinValue = computerWinValue;
}
public int k;
public int myWinValue;
public int computerWinValue;
}
//c#的集合太傻逼了,在此自制链表
class MyList<T>
{
public int count;//总数
public Node<T> first;//头节点
public Node<T> last;//尾节点
//添加函数
public void add(T t)
{
if (first == null)
{
first = new Node<T>(t);
last = first;
}
else
{
Node<T> node = new Node<T>(t);
node.next = first;
first.prev = node;
first = node;
}
count++;
}
/**
* 获取并删除最后一个元素
* **/
public T getAndRemoveLast()
{
Node<T> las = last;
if (last != null)
{
count--;
if (first == last)
{
last = null;
first = last;
return las.t;
}
else
{
last = last.prev;
las.prev = null;
last.next = null;
return las.t;
}
}
else
{
return default(T);
}
}
/**
* 获取并删除第一个元素
* **/
public T getAndRemoveFirst()
{
Node<T> fir = first;
if (first != null)
{
count--;
if (first == last)
{
last = null;
first = last;
return fir.t;
}
else
{
first = first.next;
fir.next = null;
first.prev = null;
return fir.t;
}
}
else
{
return default(T);
}
}
}
class Node<T>
{
public Node<T> next;
public Node<T> prev;
public T t;
public Node(T t)
{
this.t = t;
next = null;
prev = null;
}
}
}
fixed
没有一个冬天不可逾越,没有一个春天不会来临。最慢的步伐不是跬步,而是徘徊,最快的脚步不是冲刺,而是坚持。