0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

【项目实战】轻松实现C/C++大作业:五子棋游戏!附带源码

C语言编程学习基地 来源:C语言编程学习基地 2023-02-06 11:21 次阅读

每天一个C语言小项目,提升你的编程能力!

基于 EasyX 的五子棋软件。

算法部分想了很久,也参考了网上的其他游戏的。原理主要就是:遍历每个空闲的点,根据下在那个点后连成的棋形来判断其分值,再选出分值最高的位置并返回给游戏函数。

还在上小学,更深层次的判定算法还没学,就先将就一下吧。

运行效果如下:

c1c59706-a532-11ed-bfe3-dac502259ad0.png

完整的游戏源代码如下:

#include 
#include 
#include 
#include 
#include 






// 类定义


// 保存位置的类
class seat
{
public:
  int i = 0;      // y 坐标
  int j = 0;      // x 坐标
  int number = 0; // 分数
};


// 保存棋盘的类
class box
{
public:
  void draw();            // 绘制
public:
  int x = 0;              // x 坐标
  int y = 0;              // y 坐标
  int value = -1;         // 值(黑棋:1,白棋:0,空位:-1)
  int modle;              // 模式
  bool isnew = false;     // 是否有选择框
  int number = 0;         // 分数
  COLORREF color = WHITE; // 棋盘背景色
};




// 函数声明
void draw();                  // 绘制
void init();                  // 初始化
seat findbestseat(int color); // 寻找最佳位置
void isWIN();                 // 判断输赢
void game();                  // 游戏主函数






// main函数
int main()
{
  initgraph(700, 700, NOMINIMIZE); // 初始化绘图环境
  setbkcolor(WHITE);
  cleardevice();
  setbkmode(TRANSPARENT); // 设置透明文字输出背景
  while (1)
  {
    init(); // 初始化
    game(); // 游戏开始
    cleardevice();
  }
}






// 全局变量
box BOX[19][19];      // 棋盘
int win = -1;         // 谁赢了(0:白棋,1:黑棋,2:平局)
int whoplay = 0;      // 轮到谁下棋了
int playercolor = 0;  // 玩家颜色
int dx[4]{ 1,0,1,1 }; // - |  / 四个方向
int dy[4]{ 0,1,1,-1 };






// 类函数定义


// 绘制函数
void box::draw()
{
  COLORREF thefillcolor = getfillcolor(); // 备份填充颜色
  setlinestyle(PS_SOLID, 2);              // 线样式设置
  setfillcolor(color);                    // 填充颜色设置
  solidrectangle(x, y, x + 30, y + 30);   // 绘制无边框的正方形
  if (isnew)
  {
    // 如果是新下的
    // 绘制边框线
    setlinecolor(LIGHTGRAY);
    line(x + 1, y + 2, x + 8, y + 2);
    line(x + 2, y + 1, x + 2, y + 8);
    line(x + 29, y + 2, x + 22, y + 2);
    line(x + 29, y + 1, x + 29, y + 8);
    line(x + 2, y + 29, x + 8, y + 29);
    line(x + 2, y + 22, x + 2, y + 29);
    line(x + 29, y + 29, x + 22, y + 29);
    line(x + 29, y + 22, x + 29, y + 29);
  }
  setlinecolor(BLACK);
  switch (modle)
  {
    // 以下是不同位置棋盘的样式
    case 0:
      line(x + 15, y, x + 15, y + 30);
      line(x - 1, y + 15, x + 30, y + 15);
      break;
      //  *
      // ***
      //  *
    case 1:
      line(x + 14, y + 15, x + 30, y + 15);
      setlinestyle(PS_SOLID, 3);
      line(x + 15, y, x + 15, y + 30);
      setlinestyle(PS_SOLID, 2);
      break;
      // *
      // ***
      // *
    case 2:
      line(x - 1, y + 15, x + 15, y + 15);
      setlinestyle(PS_SOLID, 3);
      line(x + 15, y, x + 15, y + 30);
      setlinestyle(PS_SOLID, 2);
      break;
      //   *
      // ***
      //   *
    case 3:
      line(x + 15, y + 15, x + 15, y + 30);
      setlinestyle(PS_SOLID, 3);
      line(x - 1, y + 15, x + 30, y + 15);
      setlinestyle(PS_SOLID, 2);
      break;
      // ***
      //  *
      //  *
    case 4:
      line(x + 15, y, x + 15, y + 15);
      setlinestyle(PS_SOLID, 3);
      line(x - 1, y + 15, x + 30, y + 15);
      setlinestyle(PS_SOLID, 2);
      break;
      //  *
      //  *
      // ***
    case 5:
      setlinestyle(PS_SOLID, 3);
      line(x + 15, y, x + 15, y + 15);
      line(x + 15, y + 15, x + 30, y + 15);
      setlinestyle(PS_SOLID, 2);
      break;
      // *
      // *
      // ***
    case 6:
      setlinestyle(PS_SOLID, 3);
      line(x + 15, y, x + 15, y + 15);
      line(x - 1, y + 15, x + 15, y + 15);
      setlinestyle(PS_SOLID, 2);
      break;
      //   *
      //   *
      // ***
    case 7:
      setlinestyle(PS_SOLID, 3);
      line(x - 1, y + 15, x + 15, y + 15);
      line(x + 15, y + 15, x + 15, y + 30);
      setlinestyle(PS_SOLID, 2);
      break;
      // ***
      //   *
      //   *
    case 8:
      setlinestyle(PS_SOLID, 3);
      line(x + 15, y + 15, x + 30, y + 15);
      line(x + 15, y + 15, x + 15, y + 30);
      setlinestyle(PS_SOLID, 2);
      break;
      // ***
      // *
      // *
    case 9:
      line(x + 15, y, x + 15, y + 30);
      line(x - 1, y + 15, x + 30, y + 15);
      setfillcolor(BLACK);
      setlinestyle(PS_SOLID, 1);
      fillcircle(x + 15, y + 15, 4);
      break;
      //  *
      // *O*
      //  *
  }
  switch (value)
  {
    case 0: // 白棋
      setfillcolor(WHITE);
      setlinestyle(PS_SOLID, 1);
      fillcircle(x + 15, y + 15, 13);
      break;
    case 1: // 黑棋
      setfillcolor(BLACK);
      setlinestyle(PS_SOLID, 1);
      fillcircle(x + 15, y + 15, 13);
      break;
  }
  setfillcolor(thefillcolor); // 还原填充色
}






// 其他函数定义


// 绘制棋盘
void draw()
{
  int modle = 0;  // 棋盘样式
  int number = 0; // 坐标输出的位置
  // 坐标(数值)
  TCHAR strnum[19][3] = { _T("1"),_T("2") ,_T("3") ,_T("4"),_T("5") ,_T("6") ,_T("7"),_T("8"),_T("9"),_T("10"), _T("11"),_T("12") ,_T("13") ,_T("14"),_T("15") ,_T("16") ,_T("17"),_T("18"),_T("19") };
  // 坐标(字母)
  TCHAR strabc[19][3] = { _T("A"),_T("B") ,_T("C") ,_T("D"),_T("E") ,_T("F") ,_T("G"),_T("H"),_T("I"),_T("J"), _T("K"),_T("L") ,_T("M") ,_T("N"),_T("O") ,_T("P") ,_T("Q"),_T("R"),_T("S") };
  for (int i = 0, k = 0; i < 570; i += 30)
  {
    for (int j = 0, g = 0; j < 570; j += 30)
    {
      BOX[k][g].color = RGB(255, 205, 150);// 棋盘底色
      // x、y 坐标
      BOX[k][g].x = 65 + j;
      BOX[k][g].y = 50 + i;
      BOX[k][g].number = 0;// 初始化分数
      // 棋盘样式的判断
      if (k == 0 && g == 0)
      {
        modle = 8;
      }
      else if (k == 0 && g == 18)
      {
        modle = 7;
      }
      else if (k == 18 && g == 18)
      {
        modle = 6;
      }
      else if (k == 18 && g == 0)
      {
        modle = 5;
      }
      else if (k == 0)
      {
        modle = 3;
      }
      else if (k == 18)
      {
        modle = 4;
      }
      else if (g == 0)
      {
        modle = 1;
      }
      else if (g == 18)
      {
        modle = 2;
      }
      else  if ((k == 3 && g == 3) || (k == 3 && g == 15) || (k == 15 && g == 3) || (k == 15 && g == 15) || (k == 3 && g == 9) || (k == 9 && g == 3) || (k == 15 && g == 9) || (k == 9 && g == 15) || (k == 9 && g == 9))
      {
        modle = 9;
      }
      else
      {
        modle = 0;
      }
      BOX[k][g].modle = modle;
      BOX[k][g].draw(); // 绘制
      if (BOX[k][g].isnew == true)
      {
        BOX[k][g].isnew = false; // 把上一个下棋位置的黑框清除
      }
      g++;
    }
    k++;
  }
  // 画坐标
  LOGFONT nowstyle;
  gettextstyle(&nowstyle);
  settextstyle(0, 0, NULL);
  for (int i = 0; i < 19; i++)
  {
    outtextxy(75 + number, 35, strnum[i]);
    outtextxy(53, 55 + number, strabc[i]);
    number += 30;
  }
  settextstyle(&nowstyle);
}


// 对局初始化
void init()
{
  win = -1;// 谁赢了
  for (int i = 0; i < 19; i++)
  {
    for (int j = 0; j < 19; j++)
    {
      BOX[i][j].number = 0;// 分数
      BOX[i][j].value = -1;// 值
    }
  }
}






// 核心函数


// 寻找最佳位置
seat findbestseat(int color)
{
  // 评分表
  int Score[3][5] = {
    { 0, 20, 360, 5800, 92840 }, // 防守0子
    { 0, 0, 20, 360, 92840 },    // 防守1子
    { 0, 0, 0, 0, 92840 }        // 防守2子
  };
  seat bestseat;              // 最佳位置
  int MAXnumber[361] = { 0 }; // 最佳分数(可能有多个)
  int MAXx[361] = { 0 };      // 最佳 x 坐标(可能有多个)
  int MAXy[361] = { 0 };      // 最佳 y 坐标(可能有多个)
  int number = 0;             // 下一个最佳分数储存位置
  int truenumber;             // 输出的最佳分数位置
  int nowi = 0;               // 现在遍历到的y坐标
  int nowj = 0;               // 现在遍历到的x坐标
  int length[4];              // 四个方向的长度
  int emeny[4];               // 四个方向的敌子
  for (int i = 0; i < 19; i++)
  {
    for (int j = 0; j < 19; j++)
    {
      if (BOX[i][j].value == -1)
      {
        // 遍历每一个可能的位置


        // 自己
        BOX[i][j].value = color; // 尝试下在这里
        for (int k = 0; k < 4; k++)
        {
          length[k] = 0;
          emeny[k] = 0;
          nowi = i;
          nowj = j;
          while (nowi <= 18 && nowj <= 18 && nowi >= 0 && nowj >= 0 && BOX[nowi][nowj].value == color)
          {
            length[k]++;
            nowj += dx[k];
            nowi += dy[k];
          }
          if (BOX[nowi][nowj].value == 1 - color || nowi < 0 || nowj < 0 || nowi > 18 || nowj > 18)
          {
            emeny[k]++;
          }
          nowi = i;
          nowj = j;
          while (nowi <= 18 && nowj <= 18 && nowi >= 0 && nowj >= 0 && BOX[nowi][nowj].value == color)
          {
            length[k]++;
            nowj -= dx[k];
            nowi -= dy[k];
          }
          if (BOX[nowi][nowj].value == 1 - color || nowi < 0 || nowj < 0 || nowi > 18 || nowj > 18)
          {
            emeny[k]++;
          }
          length[k] -= 2; // 判断长度
          if (length[k] > 4)
          {
            length[k] = 4;
          }
          BOX[i][j].number += Score[emeny[k]][length[k]] * 4 + !(!length[k]) * 20;//加分系统
          length[k] = 0;
          emeny[k] = 0;
        }
        // 敌人(原理同上)
        BOX[i][j].value = 1 - color;
        for (int k = 0; k < 4; k++)
        {
          length[k] = 0;
          emeny[k] = 0;
          nowi = i;
          nowj = j;
          while (nowi <= 18 && nowj <= 18 && nowi >= 0 && nowj >= 0 && BOX[nowi][nowj].value == 1 - color)
          {
            length[k]++;
            nowj += dx[k];
            nowi += dy[k];
          }
          if (BOX[nowi][nowj].value == color || nowi < 0 || nowj < 0 || nowi > 18 || nowj > 18)
          {
            emeny[k]++;
          }
          nowi = i;
          nowj = j;
          while (nowi <= 18 && nowj <= 18 && nowi >= 0 && nowj >= 0 && BOX[nowi][nowj].value == 1 - color)
          {
            length[k]++;
            nowj -= dx[k];
            nowi -= dy[k];
          }
          if (BOX[nowi][nowj].value == color || nowi < 0 || nowj < 0 || nowi > 18 || nowj > 18)
          {
            emeny[k]++;
          }
          length[k] -= 2;
          if (length[k] > 4)
          {
            length[k] = 4;
          }
          BOX[i][j].number += Score[emeny[k]][length[k]];
          length[k] = 0;
          emeny[k] = 0;
        }
        BOX[i][j].value = -1;
      }
      if (BOX[i][j].number == MAXnumber[0])
      {
        // 如果和最高分数相同
        MAXnumber[number] = BOX[i][j].number;
        MAXy[number] = i;
        MAXx[number] = j;
        number++;
        // 新增一个分数及坐标
      }
      if (BOX[i][j].number > MAXnumber[0])
      {
        // 如果比最高分数高
        for (int k = 0; k < number; k++)
        {
          MAXnumber[k] = 0;
          MAXy[k] = 0;
          MAXx[k] = 0;
        }
        number = 0;
        MAXnumber[number] = BOX[i][j].number;
        MAXy[number] = i;
        MAXx[number] = j;
        number++;
        // 清空数组再加入
      }
    }
  }
  // 生成随机位置
  srand(time(NULL));
  truenumber = rand() % number;
  bestseat.i = MAXy[truenumber];
  bestseat.j = MAXx[truenumber];
  bestseat.number = MAXnumber[truenumber];
  // 返回位置
  return bestseat;
}


// 判断输赢
void isWIN()
{
  bool isinit = true; // 是否刚刚开局
  for (int i = 0; i < 19; i++)
  {
    for (int j = 0; j < 19; j++)
    {
      if (BOX[i][j].value != -1)
      {
        // 遍历每个可能的位置
        isinit = false;                 // 如果有,那么就不是刚刚开局
        int nowcolor = BOX[i][j].value; // 现在遍历到的颜色
        int length[4] = { 0,0,0,0 };    // 四个方向的长度
        for (int k = 0; k < 4; k++)
        {
          // 原理同寻找最佳位置
          int nowi = i;
          int nowj = j;
          while (nowi <= 18 && nowj <= 18 && nowi >= 0 && nowj >= 0 && BOX[nowi][nowj].value == nowcolor)
          {
            length[k]++;
            nowj += dx[k];
            nowi += dy[k];
          }
          nowi = i;
          nowj = j;
          while (nowi <= 18 && nowj <= 18 && nowi >= 0 && nowj >= 0 && BOX[nowi][nowj].value == 1 - nowcolor)
          {
            length[k]++;
            nowj -= dx[k];
            nowi -= dy[k];
          }
        }
        for (int k = 0; k < 4; k++)
        {
          if (length[k] >= 5) {
            // 如果满五子
            if (nowcolor == playercolor)
            {
              win = playercolor; // 玩家胜
            }
            if (nowcolor == 1 - playercolor)
            {
              win = 1 - playercolor; // 电脑胜
            }
          }
        }
        if ((!isinit) && findbestseat(playercolor).number == 0 && findbestseat(1 - playercolor).number == 0)
        {
          // 如果不是开局且双方无最佳位置
          win = 2; // 平局
        }
      }
    }
  }
}


// 游戏主函数
void game()
{
  // 上一个鼠标停的坐标
  int oldi = 0;
  int oldj = 0;
  // 随机化玩家颜色
  srand(time(NULL));
  playercolor = rand() % 2;
  // 绘制背景
  setfillcolor(RGB(255, 205, 150));
  solidrectangle(40, 25, 645, 630);
  // 设置字体样式
  settextstyle(30, 15, 0, 0, 0, 1000, false, false, false);
  settextcolor(BLACK);
  // 输出标示语
  if (playercolor == 0)
  {
    outtextxy(150, 650, _T("玩家执白后行,电脑执黑先行"));
    whoplay = 1;
  }
  else
  {
    outtextxy(150, 650, _T("玩家执黑先行,电脑执白后行"));
    whoplay = 0;
  }
  draw(); // 绘制
  while (1)
  {
  NEXTPLAYER:
    if (whoplay == 0)
    {
      // 玩家下棋
      MOUSEMSG mouse = GetMouseMsg(); // 获取鼠标信息
      for (int i = 0; i < 19; i++)
      {
        for (int j = 0; j < 19; j++)
        {
          if (mouse.x > BOX[i][j].x && mouse.xBOX[i][j].y && mouse.y < BOX[i][j].y + 30//判断y坐标
            && BOX[i][j].value == -1)//判断是否是空位置
          {
          // 如果停在某一个空位置上面
            if (mouse.mkLButton)
            {
              // 如果按下了
              BOX[i][j].value = playercolor; // 下棋
              BOX[i][j].isnew = true;        // 新位置更新
              oldi = -1;
              oldj = -1;
              // 下一个玩家
              whoplay = 1;
              goto DRAW;
            }
            // 更新选择框
            BOX[oldi][oldj].isnew = false;
            BOX[oldi][oldj].draw();
            BOX[i][j].isnew = true;
            BOX[i][j].draw();
            oldi = i;
            oldj = j;
          }
        }
      }
    }
    else
    {
      // 电脑下棋
      seat best;
      best = findbestseat(1 - playercolor); // 寻找最佳位置
      if (best.number == 0)
      {
        // 开局情况
        int drawi = 9;
        int drawj = 9;
        while (BOX[drawi][drawj].value != -1)
        {
          drawi--;
          drawj++;
        }
        BOX[drawi][drawj].value = 1 - playercolor;
        BOX[drawi][drawj].isnew = true;
      }
      else
      {
        BOX[best.i][best.j].value = 1 - playercolor;//下在最佳位置
        BOX[best.i][best.j].isnew = true;
      }
      whoplay = 0;
      goto DRAW; // 轮到下一个
    }
  }
DRAW: // 绘制
  isWIN(); // 检测输赢
  draw();
  if (win == -1)
  {
    // 如果没有人胜利
    Sleep(500);
    goto NEXTPLAYER; // 前往下一个玩家
  }
  // 胜利处理
  settextcolor(RGB(0, 255, 0));
  Sleep(1000);
  if (win == 0)
  {
    outtextxy(320, 320, _T("白胜"));
  }
  if (win == 1)
  {
    outtextxy(320, 320, _T("黑胜"));
  }
  if (win == 2)
  {
    outtextxy(320, 320, _T("平局"));
  }
  // 给反应时间
  Sleep(5000);
  return;
}

大家赶紧去动手试试吧!

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 游戏
    +关注

    关注

    2

    文章

    736

    浏览量

    26276
  • C语言
    +关注

    关注

    180

    文章

    7597

    浏览量

    136122
  • 编程
    +关注

    关注

    88

    文章

    3587

    浏览量

    93582
  • 源码
    +关注

    关注

    8

    文章

    633

    浏览量

    29134
  • C++
    C++
    +关注

    关注

    22

    文章

    2104

    浏览量

    73482

原文标题:【项目实战】轻松实现C/C++大作业:五子棋游戏!附带源码

文章出处:【微信号:cyuyanxuexi,微信公众号:C语言编程学习基地】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    labview五子棋程序

    本帖最后由 桂花酒 于 2012-6-10 13:43 编辑 labview五子棋程序,想用的可以看看!本来是发的求助帖,找五子棋程序,不过刚才下了一个,鉴于论坛上现在已经搜不着了(我原来下过,不过删了)一起学习!
    发表于 06-10 13:16

    五子棋游戏里如何实现悔棋功能啊

    基于labview的五子棋游戏,有人机对弈和双人对弈模式,双人对弈在不联网的情况下
    发表于 10-10 14:18

    五子棋

    求一个五子棋的程序
    发表于 06-26 16:09

    五子棋

    自己做的五子棋,说不上有什么难的
    发表于 08-12 21:44

    基于labview五子棋游戏,添加悔棋功能

    基于labview五子棋游戏,添加悔棋功能,自己做的实现不了这个
    发表于 01-07 16:28

    C语言实现双人对战五子棋游戏

    在编写五子棋游戏前首先对整个项目进行分析:1、五子棋的界面绘制及显示2、对输入的数据进行写入3、判断输入的数据多对应的位置上是否可以下棋其中包括检测此位置是否为空及是否超出下棋的有效位
    发表于 08-17 09:18

    C语言五子棋程序分享!

    先输入棋盘规模,然后输棋子的坐标,先输入纵轴的,再输入横轴,悔棋算法用的是堆栈,记得当时刚开始学数据结构~很简单的一个程序~五子棋.c (4.13 KB )
    发表于 09-30 01:35

    LabVIEW五子棋游戏

    使用LabVIEW2016版本实现五子棋游戏程序,游戏分为左右手互搏模式和随机人机对战模式,人机对战只是实现了在玩家落子后电脑随机落子的
    发表于 10-13 13:30

    怎样去设计一种人机对弈五子棋程序

    五子棋游戏应达到几方面的要求?怎样去设计一种人机对弈五子棋程序?
    发表于 09-29 07:26

    怎么实现c语言简易五子棋的设计?

    怎么实现c语言简易五子棋的设计?
    发表于 10-15 07:10

    怎么实现基于STM32的五子棋游戏的设计?

    怎么实现基于STM32的五子棋游戏的设计?
    发表于 11-26 07:08

    五子棋程序源代码-Matlab实现

    五子棋程序源代码-M
    发表于 07-04 16:15 50次下载

    C语言五子棋

    C语言五子棋,有趣的东西,值得玩玩,不用看着黑框发呆
    发表于 01-12 16:49 2次下载

    C语言教程之五子棋游戏的问题

    C语言教程之五子棋游戏的问题,很好的C语言资料,快来学习吧。
    发表于 04-25 17:07 0次下载

    基于LabVIEW的五子棋博弈算法

    对棋局的局势进行分析;同时为了提高下棋的效率,对型进行了分类,并对原有的博弈算法进行改进,采用进攻和防守两个权值简化决策过程。通过真实的对弈测试表明,基于LabVIEW的博弈算法能快速、准确地
    发表于 12-17 11:32 29次下载