c语言黑白棋ai游戏源码

简介: c语言黑白棋ai游戏源码
#include <graphics.h> // EasyX_2011惊蛰版
#include <strstream>
#include <ctime>
#pragma comment(lib, "Winmm.lib")
#define T(c) ((c == 'B') ? 'W' : 'B')
using namespace std;
// 来自公众号:c语言与cpp编程
/*******************************定义全局变量*****************************/
const int difficult = 6;  // 难度
const int move[8][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1},
            {-1, -1}, {1, -1}, {1, 1}, {-1, 1}};
              // 八个方向扩展
char map[8][8];       // 棋盘
IMAGE img[5];       // 保存图片
int black, white;     // 双方的棋子数
int X, Y;         // 白棋的下子点
/**********************************函数声明*****************************/
void load(void);        // 加载素材
void print(void);       // 画棋盘
void draw(int, int, char);    // 下当前子
int judge(int, int, char);    // 判断当前是否可以落下
bool baidu(char);       // 判断是否有棋可吃
bool quit(char);        // 判断是否有棋存活
bool ask(void);         // 弹出对话框
int D(char, int);       // 动态规划
void play(void);        // 游戏过程
/**********************************定义函数*****************************/
void load(void)   // 加载素材
{
  // 加载图片
  loadimage(&img[0], "图片\\空位.bmp");
  loadimage(&img[1], "图片\\黑子.bmp");
  loadimage(&img[2], "图片\\白子.bmp");
  loadimage(&img[3], "图片\\黑子1.bmp");
  loadimage(&img[4], "图片\\白子1.bmp");
  // 加载音乐
  mciSendString("open 音乐\\背景音乐.wma", NULL, 0, NULL);
  mciSendString("open 音乐\\和局.wma", NULL, 0, NULL);
  mciSendString("open 音乐\\胜利.wma", NULL, 0, NULL);
  mciSendString("open 音乐\\失败.wma", NULL, 0, NULL);
  mciSendString("open 音乐\\下子.wma", NULL, 0, NULL);
  // 初始化棋盘
  initgraph(340, 340);
  IMAGE qipan;
  loadimage(&qipan, "图片\\棋盘.bmp");
  putimage(0, 0, &qipan);
  setorigin(26, 26);
  SetWindowText(GetHWnd(), "黑白棋AI版");
}
void print(void)  // 画棋盘
{
  int x, y;
  black = white = 0;
  for(x = 0; x < 8; x++)
    for(y = 0; y < 8; y++)
      switch(map[x][y])
      {
        case 0:
            putimage(37 * y, 37 * x, &img[0]);
          break;
        case 'B':
            putimage(37 * y, 37 * x, &img[1]);
          black++;
          break;
        case 'W':
            putimage(37 * y, 37 * x, &img[2]);
          white++;
          break;
      }
}
void draw(int x, int y, char a) // 下当前子
{
  char b = T(a);                  // 敌方子
  int i, x1, y1, x2, y2;
  bool sign;      
  for (i = 0; i < 8; i++)
  {
    sign = false;
    x1 = x + move[i][0];
    y1 = y + move[i][1];
    while (0 <= x1 && x1 < 8 && 0 <= y1 && y1 < 8 && map[x1][y1])
    {
      if(map[x1][y1] == b)
        sign = true;
      else
      {
        if(sign)
        {
          x1 -= move[i][0];
          y1 -= move[i][1];
          x2 = x + move[i][0];
          y2 = y + move[i][1];
          while (((x <= x2 && x2 <= x1) || (x1 <= x2 && x2 <= x)) && ((y <= y2 && y2 <= y1) || (y1 <= y2 && y2 <= y)))
          {
            map[x2][y2] = a;
            x2 += move[i][0];
            y2 += move[i][1];
          }
        }
        break;
      }
      x1 += move[i][0];
      y1 += move[i][1];
    }
  }
  map[x][y] = a;
}
int judge(int x, int y, char a) // 判断当前是否可以落下,同draw函数
{
  if(map[x][y])           // 如果当前不是空的返回0值
    return 0;
  char b = T(a);
  int i, x1, y1;
  int n = 0, sign;
  for (i = 0; i < 8; i++)
  {
    sign = 0;
    x1 = x + move[i][0];
    y1 = y + move[i][1];
    while (0 <= x1 && x1 < 8 && 0 <= y1 && y1 < 8 && map[x1][y1])
    {
      if(map[x1][y1] == b)
        sign++;
      else
      {
        n += sign;
        break;
      }
      x1 += move[i][0];
      y1 += move[i][1];
    }
  }
  return n;   // 返回可吃棋数
}
bool baidu(char c)  // 判断是否有棋可吃
{
  int x, y;
  for(x = 0; x < 8; x++)
    for(y = 0; y < 8; y++)
      if(judge(x, y, c))
        return true;
  return false;
}
bool quit(char c) // 判断是否有棋存活
{
  int x, y;
  bool b = false, w = false;
  for(x = 0; x < 8; x++)
    for(y = 0; y < 8; y++)
    {
      if(map[x][y] == c)
        return false;
    }
  return true;
}
bool ask(void)  // 弹出对话框
{
  HWND wnd = GetHWnd();
  int key;
  char str[50];
  ostrstream strout(str, 50);
  strout <<"黑:" <<black <<"  白:" <<white <<endl;
  if (black == white)
    strout <<"世界和平";
  else if(black > white)
    strout <<"恭喜你赢了!";
  else
    strout <<"小样,还想赢我。";
  strout <<"\n再来一局吗?" <<ends;
  if(black == white)
    key = MessageBox(wnd, str, "和局", MB_YESNO | MB_ICONQUESTION);
  else if(black > white)
    key = MessageBox(wnd, str, "黑胜", MB_YESNO | MB_ICONQUESTION);
  else
    key = MessageBox(wnd, str, "白胜", MB_YESNO | MB_ICONQUESTION);
  if(key == IDYES)
    return true;
  else
    return false;
}
int D(char c, int step)
{
  // 判断是否结束递归
  if (step > difficult) // 约束步数之内
    return 0;
  if (!baidu(c))
  {
    if (baidu(T(c)))
      return -D(T(c), step);
    else
      return 0;
  }
  int i, j, max = 0, temp, x, y;
  bool ans = false;
  // 建立临时数组
  char **t = new char *[8];
  for (i = 0; i < 8; i++)
    t[i] = new char [8];
  for (i = 0; i < 8; i++)
    for (j = 0; j < 8; j++)
      t[i][j] = map[i][j];
  // 搜索解法
  for (i = 0; i < 8; i++)
    for (j = 0; j < 8; j++)
      if (temp = judge(i, j, c))
      {
        draw(i, j, c);
        temp -= D(T(c), step + 1);
        if (temp > max || !ans)
        {
          max = temp;
          x = i;
          y = j;
          ans = true;
        }
        for (int k = 0; k < 8; k++)
          for (int l = 0; l < 8; l++)
            map[k][l] = t[k][l];
      }
  // 撤销空间
  for (i = 0; i < 8; i++)
    delete [] t[i];
  delete [] t;
  // 如果是第一步则标识白棋下子点
  if (step == 1)
  {
    X = x;
    Y = y;
  }
  return max; // 返会最优解
}
void play(void)     // 游戏过程
{
  MOUSEMSG m;
  int x, y;
  // 初始化棋子
  for(x = 0; x < 8; x++)
    for(y = 0; y < 8; y++)
      map[x][y] = 0;
  map[3][4] = map[4][3] = 'B';
  map[3][3] = map[4][4] = 'W';
  // 开始游戏
  print();
  mciSendString("play 音乐\\背景音乐.wma from 0 repeat", NULL, 0, NULL);
  do
  {
    if (baidu('B'))                   // 如果玩家有下子位置              
    {
      A:
      while(true)
      {
        m = GetMouseMsg();              // 获取鼠标消息
        if(m.uMsg == WM_LBUTTONDOWN && m.x - 26 < 37 * 8 && m.y - 26 < 37 * 8)
                              // 如果左键点击
          break;
      }
      x = (m.y - 26) / 37;
      y = (m.x - 26) / 37;
      if(judge(x, y, 'B'))              // 如果当前位置有效
      {
        draw(x, y, 'B');              // 下子
        mciSendString("play 音乐\\下子.wma from 0", NULL, 0, NULL);
        print();
        putimage(37 * y, 37 * x, &img[3]);      // 标识下子点
      }
      else
        goto A;
      if (quit('W'))                  // 计算机是否失败
        break;
    }
    if (baidu('W'))                   // 如果计算机有下子位置
    {
      clock_t start;
      start = clock();
      D('W', 1);                    // 搜索解法
      while (clock() - start < CLOCKS_PER_SEC);
      draw(X, Y, 'W');
      print();
      mciSendString("play 音乐\\下子.wma from 0", NULL, 0, NULL);
      putimage(37 * Y, 37 * X, &img[4]);  // 标识下子点
      if (quit('B'))                  // 玩家是否失败
        break;
    }
  }while (baidu('B') || baidu ('W'));
  // 播放庆祝音乐
  mciSendString("stop 音乐\\背景音乐.wma", NULL, 0, NULL);
  if (black > white)
    mciSendString("play 音乐\\胜利.wma from 0", NULL, 0, NULL);
  else if (black < white)
    mciSendString("play 音乐\\失败.wma from 0", NULL, 0, NULL);
  else
    mciSendString("play 音乐\\和局.wma from 0", NULL, 0, NULL);
}
// 主函数
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
  load();
  do
  {
    play();
  } while(ask());
  // 关闭音乐
  mciSendString("close 音乐\\背景音乐.wma", NULL, 0, NULL);
  mciSendString("close 音乐\\和局.wma", NULL, 0, NULL);
  mciSendString("close 音乐\\胜利.wma", NULL, 0, NULL);
  mciSendString("close 音乐\\失败.wma", NULL, 0, NULL);
  mciSendString("close 音乐\\下子.wma", NULL, 0, NULL);
  closegraph();
  return 0;
}
/***********************************THE END************************************/
相关文章
|
2月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
241 9
|
2月前
|
C语言
C语言之斗地主游戏
该代码实现了一个简单的斗地主游戏,包括头文件引入、宏定义、颜色枚举、卡牌类、卡牌类型类、卡牌组合类、玩家类、游戏主类以及辅助函数等,涵盖了从牌的生成、分配、玩家操作到游戏流程控制的完整逻辑。
87 8
|
2月前
|
存储 人工智能 关系型数据库
拥抱Data+AI|解码Data+AI助力游戏日志智能分析
「拥抱Data+AI」系列第2篇:阿里云DMS+AnalyticDB助力游戏日志数据分析与预测
拥抱Data+AI|解码Data+AI助力游戏日志智能分析
|
2月前
|
存储 算法 C语言
用C语言开发游戏的实践过程,包括选择游戏类型、设计游戏框架、实现图形界面、游戏逻辑、调整游戏难度、添加音效音乐、性能优化、测试调试等内容
本文探讨了用C语言开发游戏的实践过程,包括选择游戏类型、设计游戏框架、实现图形界面、游戏逻辑、调整游戏难度、添加音效音乐、性能优化、测试调试等内容,旨在为开发者提供全面的指导和灵感。
53 2
|
2月前
|
人工智能 知识图谱
轻松搭建AI版“谁是卧底”游戏,muAgent框架让知识图谱秒变编排引擎,支持复杂推理+在线协同
蚂蚁集团推出muAgent,兼容现有市面各类Agent框架,同时可实现复杂推理、在线协同、人工交互、知识即用四大核心差异技术功能。
56 2
|
2月前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
109 16
|
2月前
|
搜索推荐 算法 C语言
【排序算法】八大排序(下)(c语言实现)(附源码)
本文继续学习并实现了八大排序算法中的后四种:堆排序、快速排序、归并排序和计数排序。详细介绍了每种排序算法的原理、步骤和代码实现,并通过测试数据展示了它们的性能表现。堆排序利用堆的特性进行排序,快速排序通过递归和多种划分方法实现高效排序,归并排序通过分治法将问题分解后再合并,计数排序则通过统计每个元素的出现次数实现非比较排序。最后,文章还对比了这些排序算法在处理一百万个整形数据时的运行时间,帮助读者了解不同算法的优劣。
148 7
|
2月前
|
搜索推荐 算法 C语言
【排序算法】八大排序(上)(c语言实现)(附源码)
本文介绍了四种常见的排序算法:冒泡排序、选择排序、插入排序和希尔排序。通过具体的代码实现和测试数据,详细解释了每种算法的工作原理和性能特点。冒泡排序通过不断交换相邻元素来排序,选择排序通过选择最小元素进行交换,插入排序通过逐步插入元素到已排序部分,而希尔排序则是插入排序的改进版,通过预排序使数据更接近有序,从而提高效率。文章最后总结了这四种算法的空间和时间复杂度,以及它们的稳定性。
122 8
|
2月前
|
存储 人工智能 关系型数据库
拥抱Data+AI|玩家去哪儿了?解码Data+AI如何助力游戏日志智能分析
本文为阿里云瑶池数据库「拥抱Data+AI」系列连载第2篇,基于真实客户案例和最佳实践,探讨如何利用阿里云Data+AI解决方案应对游戏行业挑战,通过AI为游戏行业注入新的活力。文章详细介绍了日志数据的实时接入、高效查询、开源开放及AI场景落地,展示了完整的Data+AI解决方案及其实际应用效果。
|
2月前
|
C语言
【数据结构】二叉树(c语言)(附源码)
本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
147 8