趣味益智小游戏 三子棋+五子棋 优化版(可任意选择棋盘大小)

简介: 趣味益智小游戏 三子棋+五子棋 优化版(可任意选择棋盘大小)

一、游戏介绍


《三子棋》是一款益智小游戏,通常是在九宫格里面玩,所以也被称为”九宫棋“或”井字棋“。


游戏规则也极其简单,只要三子相连即可获胜。


例如:



c语言实现效果图:


三子棋:




五子棋:




二、游戏设计思路


分为三个模块化实现:


1.主函数测试区(test.c):用于打印菜单、实现调用游戏要使用的各种函数、退出游戏等功能。


重点在于其中的game函数()。


2.函数声明区(game.h):用于各种库函数、自定义函数的声明。


3.函数实现区(game.c):用于各种函数功能的具体的实现。


 1. 菜单界面选择开始或者退出游戏。
 2. 玩家选择游戏类型:1.三子棋 2.五子棋  
 3. 玩家选择棋盘大小。
 4. 创建棋盘并初始化.打印棋盘。(打印初始化后的棋盘)。
 5. 玩家落子(玩家输入行列坐标的方式来落子),'*’表示玩家落子。(注意坐标合法性)
 6. 打印棋盘(玩家落子后的棋盘)。
 7. 判定胜负关系(输,赢,和棋),'p’表示平局。.
 8.电脑落子(随机位置落子) ,'#’表示电脑落子。
 9. 打印棋盘(电脑落子后的棋盘)
 10.判定输赢情况。


2.1 主函数测试区(test.c)基本构成


2.11 创建游戏菜单


可用printf打印一个简易菜单,让玩家选择。


//在主函数测试区(test.c)
void menu()
{
  printf("*******************************************************************\n");
  printf("************                     *                    *************\n");
  printf("******************               *                *****************\n");
  printf("************************         *          ***********************\n");
  printf("*******************************  *   ******************************\n");
  printf("********    1.玩游戏         *        2.退出游戏          *********\n");
  printf("*******************************  *   ******************************\n");
  printf("************************         *          ***********************\n");
  printf("******************               *                *****************\n");
  printf("************                     *                     ************\n");
  printf("*******************************************************************\n");
  printf("请选择:\n");
}


2.12 主测试区基本框架


通过switch语句来实现根据玩家选择结果来调用game函数


int main()
{
  int n = 0;//记录玩家在菜单中的选择
  srand((unsigned int)time(NULL));//与前面介绍的猜数字游戏一样,改变种子值来使得rand函数每次生成不同的随机数列。用于后面的电脑下棋
  do
  {
    menu();
    scanf("%d", &n);//让玩家在菜单中选择
    switch (n)
    {
    case 1://代表玩游戏
      game();//这个是重点函数
      printf("再来一局吗?\n");//游戏结束后
      printf("1.再来一局   2. 没意思不玩了\n");
      int again = 0;//存放玩家是否再玩的结果。
      scanf("%d", &again);
      if (again == 1)
      {
        break;
      }
      else
        n = 2;//令n=2循环结束
      break;
    case 2:
      printf("退出游戏");
      break;
    default:
      printf("没有这个选项哦。\n");//玩家不小心输错了
      break;
    }
  } while (n - 2);//当玩家选择2时,代表不玩了
}


2.2 game函数的实现(在主函数测试区(test.c))


 1. 玩家选择游戏类型:1.三子棋 2.五子棋  
 2. 玩家选择棋盘大小。
 3. 创建棋盘并初始化.打印棋盘。(打印初始化后的棋盘)。
 4. 玩家落子(玩家输入行列坐标的方式来落子),'*’表示玩家落子。(注意坐标合法性)
 5. 打印棋盘(玩家落子后的棋盘)。
 6. 判定胜负关系(输,赢,和棋),'p’表示平局。.
 7.电脑落子(随机位置落子) ,'#’表示电脑落子。
 8. 打印棋盘(电脑落子后的棋盘)
 9.判定输赢情况。


2.21 棋盘的创建:


创建一个大小为15行15列的二维数组(可修改,不建议太大)用于存放棋子。


这里使用宏定义是为了方便改变棋盘的最大大小,下次需要修改的时候只需要修改这里就行,不需要每个函数都一 一去改。


//函数声明区(game.h)
#define ROW 15//为了方便改变棋盘大小
#define COL 15


//game函数的实现(在主函数测试区(test.c))
void game()
{
  printf("欢迎玩家进入游戏:\n");
  int gametype = 0;//游戏类型
  int boardtype = 0;//棋盘大小的确定
    again://玩家选择错误后返回到此处
  printf("请选择游戏类型: 1.三子棋游戏(建议3*3的棋盘)  2.五子棋游戏\n");
  scanf("%d", &gametype);//让玩家选择游戏类型
  if (gametype != 1 && gametype != 2)//玩家选择错误给出提示,并重新选择
  {
    printf("选择错误,牛牛还未开发此类型游戏。\n");
    printf("请重新选择:\n");
    goto again;//跳转到again语句处
  }
  printf("请选择棋盘类型:n*n,你希望n的值为多少?(1<n<15)\n");
  scanf("%d", &boardtype);//得到玩家想要的棋盘大小
  if (gametype == 2 && boardtype < 5 || gametype == 1 && boardtype < 3)//避免选五子棋的棋盘小于5*5,和三子棋小于3*3的棋盘
  {
    printf("棋盘不符合要求:请重新选择:\n");
    goto again;//跳转到again语句处
  }
  else if (boardtype > ROW)//选择的棋盘最大不得超过15*15
  {
    printf("超出棋盘最大设置范围(15*15):\n请重新选择:\n");
    goto again;//跳转到again语句处
  }
  char board[ROW][COL] = { 0 };//定义一个2维数组,最大为15*15,用于存放棋子
  char ret = 0;//设置判断输赢的返回值。
  //打印数组的元素
  init_board(board, ROW, COL);//初始化棋盘,使其值全为空格
  print_board(board, boardtype, boardtype);//打印棋盘的外观和内容
  while (1)//游戏开始
  {
    palyer(board, boardtype, boardtype);//玩家下棋
    print_board(board, boardtype, boardtype);//打印棋盘
    if (gametype == 1)//根据类型现在判断输赢的类型
    {
      ret = who_win3(board, boardtype, boardtype);//三子棋判断输赢
    }
    else
    ret = who_win5(board, boardtype, boardtype);//五子棋判断输赢
    if (ret != 'c')
    {
      break;
    }
    computer(board, boardtype, boardtype);//电脑下棋
    print_board(board, boardtype, boardtype);//打印棋盘
    if (gametype == 1)//根据类型现在判断输赢的类型
    {
      ret = who_win3(board, boardtype, boardtype);//三子棋判断输赢
    }
    else
      ret = who_win5(board, boardtype, boardtype);//五子棋判断输赢
    if (ret != 'c')
    {
      break;
    }
  }
  if (ret == '*')
  {
    printf("玩家胜利\n");
  }
  else if (ret == '#')
  {
    printf("电脑胜利\n");
  }
  else
  {
    printf("平局\n");
  }
}


补充知识:goto语句:用于跳转到自己设定的语句处。

提示:虽然棋盘大小是用户选择,但其实并不是用户选择多大的棋盘就创建多大的棋盘,棋盘最大值已经限定,只是在打印棋盘的时候,根据传递过去的参数要求打印棋盘的部分内容。


例如:


玩家输入:5,那么程序就只打印5×5的棋盘,但是棋盘的真实大小还是15×15,程序只是打印了其中的5行5列罢了(部分内容)。


2.3函数实现区(game.c)


2.31 棋盘的初始化函数(init_board)


void init_board(char board[ROW][COL], int row, int col)//初始化棋盘
{
  int i = 0, j = 0;
  for (i = 0; i < row; i++)
  {
    for (j = 0; j < col; j++)
    {
      board[i][j] = ' ';//初始化棋盘的内容为全空格
    }
  }
}


2.32 棋盘的打印函数(print_board)


牛牛为了美观,这里设计起来显得有些繁琐,但是牛牛会尽量解释清楚的。


先看效果图:



棋盘打印实现的分步讲解:


分割行打印讲解:(由于空格不能显示,这里用口表示,棋子未输入前用%c表示)



特殊:由于分割行总共有row+1行,所以我们可以先打印第一行,再循环打印后面的row行。


数据行打印讲解:




行号和列标的打印讲解:


为了让玩家更好的找到棋盘的对应位置,我们可以打印行号和列标来辅助。


只是苦了我们程序猿了,要加代码来实现。


行号:可以在打印棋盘之前用for循环打印得到1到col之间的数字。


列标:则是每打印一行数据行,在前面加上行号。


打印棋盘函数代码实现:


//函数代码实现区(game.c)
void print_board(char board[ROW][COL], int row, int col)//打印棋盘//建议参照棋盘的外观查看代码
{
  int i = 0, j = 0;
  printf(" ");//打印空格是为了对齐(因为下面的行号占用位置)
  for (i = 1; i <= row; i++)//打印显示在第一行的列标
  {
    printf("%3d ",i);//因为一个数据行的格子占3个位置,所以我们这里用%3d占用三个位置的空间
  }
  printf("\n");//打印列标后换行。
  printf("  +");//先打印一个+,可以观察棋盘外观,将棋盘外观拆分打印。//为了对齐加了一个空格,因为分割行前面没有行号占用位置,只能补空格。
  for (i = 0; i < row; i++)//打印第一行的分割线
  {
    printf("---+");//上图讲解了拆分过程。
  }
  printf("\n");//每次打印一行就要换行
  for (i = 0; i < row; i++)
  {
    printf("%2d", i+1);//打印数据行前面的行号,%2d是因为当行数>9的时候,两位数会占用两个位置,影响对齐。(细节)
    printf("|");//和上面一样,先打印一个 | ,可以观察棋盘外观,将数据行拆分打印。
    for (j = 0; j < col; j++)//打印一行中间的棋子和其它分割线
    {
      printf(" %c |", board[i][j]);//这里打印的是“空格”“棋子”“空格”“|”
    }
    printf("\n");//每次打印一行就要换行
    //打印剩余的分割行
    printf("  +");//先打印一个+,可以观察棋盘外观,将棋盘外观拆分打印。//为了对齐加了一个空格
    for (j = 0; j < col; j++)//打印一行外观的分割线
    {
      printf("---+");//每次打印一行就要换行
    }
    printf("\n");
  }
}


2.33 玩家下棋函数(palyer)


注意:此处的ROW(大写)与row(小写)大小不一定相同,ROW(大写)是宏定义的15,而row(小写)是由玩家选择的。


void palyer(char board[ROW][COL], int row, int col)
{
  int x = 0, y = 0;//定义x 和 y变量存储棋子的坐标
  printf("请玩家下棋:\n");
  while (1)
  {
    printf("请输入行号和列标:(用空格隔开)\n");
    scanf("%d%d", &x, &y);
    if (x >= 1 && x <= ROW && y >= 1 && y <= COL)//判断坐标是否合法,由于玩家并不是程序员,所以坐标要正常从1开始
    {
      if (board[x - 1][y - 1] == ' ')//落子处为空格,表示此处还未被占用。x-1,y-1是因为2维数组的坐标是从0开始的。
      {
        board[x - 1][y - 1] = '*';//玩家下棋为‘*’,将输入的坐标位置占据。
        break;//表示落子成功,结束循环,判断输赢后,轮到电脑下了
      }
      else//如果此处不是空格,则表示此处已经有棋子了。
      {
        printf("该处已经被占用了,请重新选择\n");
      }
    }
    else//如果坐标不在1到row之间,则棋子超出合法范围,
    {
      printf("该坐标非法,已经超过棋盘,无法识别\n");
      printf("请重新选择:\n");
    }
  }
}


2.33 电脑下棋函数(computer)


电脑下棋是随机下棋,我们需要得到两个随机数作为电脑棋子的下标。


void computer(char board[ROW][COL], int row, int col)//电脑下棋中
{
  printf("电脑下棋中:\n");
  while (1)
  {
    int x = rand() % row;//生成0到2的随机数作为棋子下标
    int y = rand() % col;
    if (board[x][y] == ' ')//找到棋盘中的空余位置进行下棋
    {
      board[x][y] = '#';
      break;
    }
  }
}


2.34 判断是否平局函数(draw)


平局的判断很简单,当棋盘上没有空余棋子的时候,表示棋盘已经满了,并且没有一方获胜,则显示平局。


int draw(char board[ROW][COL], int row, int col)//判断平局
{
  int i = 0, j = 0;
  for (i = 0; i < row; i++)
  {
    for (j = 0; j < col; j++)
    {
      if (board[i][j] == ' ')
      {
        return 0;//如果还要一个空格,即表示棋盘还没有满
      }
    }
  }
  return 1;//棋盘满了
}


2.35 三子棋的判断输赢函数(who_win3)



char who_win3(char board[ROW][COL], int row, int col)//三子棋判断输赢
{
  int i = 0, j = 0;
  for (i = 0; i < row; i++)//判断每行,所以i要取0到row(不包含row)
  {
    for (j = 0; j + 2 < col; j++)
    {
      if (board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2] && board[i][j] != ' ')
        //判断每行是否有相连的3个元素,并且不是空格
      {
        return board[i][j];
      }
    }
  }
  for (j = 0; j < col; j++)//判断每列
  {
    for (i = 0; i + 2 < row; i++)
    {
      if (board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j] && board[i][j] != ' ')
        //判断每列是否有相连的3个元素,并且不是空格
      {
        return board[i][j];
      }
    }
  }
  for (i = 0; i + 2 < row; i++)//判断主对角线和主对角线平行的线
  {
    for (j = 0; j + 2 < col; j++)
    {
      if (board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2] && board[i][j] != ' ')//判断主对角线和主对角线平行的线是否有三个相连,且不是空格
        return board[i][j];
    }
  }
  for (i = 2; i < row; i++)//判断反对角线和与反对角线平行的线
  {
    for (j = 0; j + 2 < col; j++)
    {
      if (board[i][j] == board[i - 1][j + 1] && board[i - 1][j + 1] == board[i - 2][j + 2]  && board[i][j] != ' ')//判断反对角线和反对角线平行的线是否有三个相连,且不是空格
        return board[i][j];
    }
  }
  if (1 == draw(board, ROW, COL))
  {
    return 'p';
  }
  else
    return 'c';
}


2.36 五子棋的判断输赢函数(who_win5)


char who_win5(char board[ROW][COL], int row, int col)//五子棋判断输赢
{
  int i = 0;
  int j = 0;
  for (i = 0; i < row; i++)//判断每行
  {
    for (j = 0; j + 4 < col; j++)
    {
      if (board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2] && board[i][j + 2] == board[i][j + 3] && board[i][j + 3] == board[i][j + 4] && board[i][j] != ' ')/判断每一行的是否有五个相连的元素,并且不是空格
        return board[i][j];
    }
  }
  for (j = 0; j < row; j++)//判断每列
  {
    for (i = 0; i + 4 < row; i++)
    {
      if (board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j] && board[i + 2][j] == board[i + 3][j] && board[i + 3][j] == board[i + 4][j] && board[i][j] != ' ')//判断每一列的是否有五个相连的元素,并且不是空格
        return board[i][j];
    }
  }
  for (i = 0; i + 4 < row; i++)//判断主对角线和主对角线平行的线
  {
    for (j = 0; j + 4 < col; j++)
    {
      if (board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2] && board[i + 2][j + 2] == board[i + 3][j + 3] && board[i + 3][j + 3] == board[i + 4][j + 4] && board[i][j] != ' ')//判断主对角线和反对角线平行的线是否有五个相连,且不是空格
        return board[i][j];
    }
  }
  for (i = 4; i < row; i++)//判断反对角线和与反对角线平行的线
  {
    for (j = 0; j + 4 < col; j++)
    {
      if (board[i][j] == board[i - 1][j + 1] && board[i - 1][j + 1] == board[i - 2][j + 2] && board[i - 2][j + 2] == board[i - 3][j + 3] && board[i - 3][j + 3] == board[i - 4][j + 4] && board[i][j] != ' ')//判断反对角线和反对角线平行的线是否有五个相连,且不是空格
        return board[i][j];
    }
  }
  if (1 == draw(board, ROW, COL))
  {
    return 'p';
  }
  else
    return 'c';
}


三、游戏总代码


3.1.主函数测试区(test.c):


#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
  printf("*******************************************************************\n");
  printf("************                     *                    *************\n");
  printf("******************               *                *****************\n");
  printf("************************         *          ***********************\n");
  printf("*******************************  *   ******************************\n");
  printf("********    1.玩游戏         *        2.退出游戏          *********\n");
  printf("*******************************  *   ******************************\n");
  printf("************************         *          ***********************\n");
  printf("******************               *                *****************\n");
  printf("************                     *                     ************\n");
  printf("*******************************************************************\n");
  printf("请选择:\n");
}
void game()
{
  printf("欢迎玩家进入游戏:\n");
  int gametype = 0;//游戏类型
  int boardtype = 0;//棋盘大小的确定
    again:
  printf("请选择游戏类型: 1.三子棋游戏(建议3*3的棋盘)  2.五子棋游戏\n");
  scanf("%d", &gametype);//让玩家选择游戏类型
  if (gametype != 1 && gametype != 2)
  {
    printf("选择错误,牛牛还未开发此类型游戏。\n");
    printf("请重新选择:\n");
    goto again;
  }
  printf("请选择棋盘类型:n*n,你希望n的值为多少?(1<n<15)\n");
  scanf("%d", &boardtype);
  if (gametype == 2 && boardtype < 5 || gametype == 1 && boardtype < 3)//避免选五子棋的棋盘小于5*5,和三子棋小于3*3的棋盘
  {
    printf("棋盘不符合要求:请重新选择:\n");
    goto again;
  }
  else if (boardtype > ROW)//选择的棋盘最大不得超过15*15
  {
    printf("超出棋盘最大设置范围(15*15):\n请重新选择:\n");
    goto again;
  }
  char board[ROW][COL] = { 0 };//定义一个2维数组,最大为15*15,用于存放棋子
  char ret = 0;//设置判断输赢的返回值。
  //打印数组的元素
  init_board(board, ROW, COL);//初始化棋盘,使其值全为空格
  print_board(board, boardtype, boardtype);//打印棋盘的外观和内容
  while (1)//游戏开始
  {
    palyer(board, boardtype, boardtype);//玩家下棋
    print_board(board, boardtype, boardtype);//打印棋盘
    if (gametype == 1)//根据类型现在判断输赢的类型
    {
      ret = who_win3(board, boardtype, boardtype);//三子棋判断输赢
    }
    else
    ret = who_win5(board, boardtype, boardtype);//五子棋判断输赢
    if (ret != 'c')
    {
      break;
    }
    computer(board, boardtype, boardtype);//电脑下棋
    print_board(board, boardtype, boardtype);//打印棋盘
    if (gametype == 1)//根据类型现在判断输赢的类型
    {
      ret = who_win3(board, boardtype, boardtype);//三子棋判断输赢
    }
    else
      ret = who_win5(board, boardtype, boardtype);//五子棋判断输赢
    if (ret != 'c')
    {
      break;
    }
  }
  if (ret == '*')
  {
    printf("玩家胜利\n");
  }
  else if (ret == '#')
  {
    printf("电脑胜利\n");
  }
  else
  {
    printf("平局\n");
  }
}
int main()
{
  int n = 0;//记录玩家在菜单中的选择
  srand((unsigned int)time(NULL));//与前面介绍的猜数字游戏一样,改变种子值来使得rand函数每次生成不同的随机数列。
  do
  {
    menu();
    scanf("%d", &n);//让玩家在菜单中选择
    switch (n)
    {
    case 1://代表玩游戏
      game();
      printf("再来一局吗?\n");
      printf("1.再来一局   2. 没意思不玩了\n");
      int again = 0;//存放玩家是否再玩的结果。
      scanf("%d", &again);
      if (again == 1)
      {
        break;
      }
      else
        n = 2;//令n=2循环结束
      break;
    case 2:
      printf("退出游戏");
      break;
    default:
      printf("没有这个选项哦。\n");//玩家不小心输错了
      break;
    }
  } while (n - 2);//当玩家选择2时,代表不玩了
}


3.2.函数声明区(game.h):


#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 15//为了方便改变棋盘大小
#define COL 15
void init_board(char board[ROW][COL], int row, int col);//初始化棋盘
void print_board(char board[ROW][COL], int row, int col);//打印棋盘
void palyer(char board[ROW][COL], int row, int col);//玩家下棋
void computer(char board[ROW][COL], int row, int col);//电脑下棋
char who_win3(char board[ROW][COL], int row, int col);//判断三子棋输赢
char who_win5(char board[ROW][COL], int row, int col);//判断五子棋输赢


3.3.函数实现区(game.c):


#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void init_board(char board[ROW][COL], int row, int col)//初始化棋盘
{
  int i = 0, j = 0;
  for (i = 0; i < row; i++)
  {
    for (j = 0; j < col; j++)
    {
      board[i][j] = ' ';//初始化棋盘的内容为全空格
    }
  }
}
void print_board(char board[ROW][COL], int row, int col)//打印棋盘//建议参照棋盘的外观
{
  int i = 0, j = 0;
  printf(" ");//为了对齐
  for (i = 1; i <= row; i++)//打印显示在第一行的列标
  {
    printf("%3d ",i);//因为一个格子3个位置
  }
  printf("\n");
  printf("  +");//先打印一个+,可以观察棋盘外观,将棋盘外观拆分打印。//为了对齐加了一个空格
  for (i = 0; i < row; i++)//打印一行外观的分割线
  {
    printf("---+");
  }
  printf("\n");//每次打印一行就要换行
  for (i = 0; i < row; i++)
  {
    printf("%2d", i+1);
    printf("|");//和上面一样,先打印一个 | ,可以观察棋盘外观,将棋盘外观拆分打印。
    for (j = 0; j < col; j++)//打印一行中间的棋子和其它分割线
    {
      printf(" %c |", board[i][j]);//这里打印的是“空格”“棋子”“空格”“|”
    }
    printf("\n");//每次打印一行就要换行
    printf("  +");//先打印一个+,可以观察棋盘外观,将棋盘外观拆分打印。//为了对齐加了一个空格
    for (j = 0; j < col; j++)//打印一行外观的分割线
    {
      printf("---+");//每次打印一行就要换行
    }
    printf("\n");
  }
}
void palyer(char board[ROW][COL], int row, int col)
{
  int x = 0, y = 0;//定义x 和 y变量存储棋子的坐标
  printf("请玩家下棋:\n");
  while (1)
  {
    printf("请输入行号和列标:(用空格隔开)\n");
    scanf("%d%d", &x, &y);
    if (x >= 1 && x <= ROW && y >= 1 && y <= COL)//判断坐标是否合法,由于玩家并不是程序员,所以坐标要正常从1开始
    {
      if (board[x - 1][y - 1] == ' ')//落子处为空格,表示此处还未被占用。
      {
        board[x - 1][y - 1] = '*';//玩家下棋为‘*’,将输入的坐标位置占据。
        break;//表示落子成功,结束循环,轮到电脑下了
      }
      else//如果此处不是空格,则表示此处已经有棋子了。
      {
        printf("该处已经被占用了,请重新选择\n");
      }
    }
    else//如果坐标不在1到3之间,则棋子超出合法范围,
    {
      printf("该坐标非法,已经超过棋盘,无法识别\n");
      printf("请重新选择:\n");
    }
  }
}
void computer(char board[ROW][COL], int row, int col)//电脑下棋中
{
  printf("电脑下棋中:\n");
  while (1)
  {
    int x = rand() % row;//生成0到2的随机数作为棋子下标
    int y = rand() % col;
    if (board[x][y] == ' ')//找到棋盘中的空余位置进行下棋
    {
      board[x][y] = '#';
      break;
    }
  }
}
int draw(char board[ROW][COL], int row, int col)//判断平局
{
  int i = 0, j = 0;
  for (i = 0; i < row; i++)
  {
    for (j = 0; j < col; j++)
    {
      if (board[i][j] == ' ')
      {
        return 0;
      }
    }
  }
  return 1;
}
char who_win3(char board[ROW][COL], int row, int col)//三子棋判断输赢
{
  int i = 0, j = 0;
  for (i = 0; i < row; i++)//判断每行,所以i要取0到row(不包含row)
  {
    for (j = 0; j + 2 < col; j++)
    {
      if (board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2] && board[i][j] != ' ')
        //判断每行是否有相连的3个元素,并且不是空格
      {
        return board[i][j];
      }
    }
  }
  for (j = 0; j < col; j++)//判断每列
  {
    for (i = 0; i + 2 < row; i++)
    {
      if (board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j] && board[i][j] != ' ')
        //判断每列是否有相连的3个元素,并且不是空格
      {
        return board[i][j];
      }
    }
  }
  for (i = 0; i + 2 < row; i++)//判断主对角线和主对角线平行的线
  {
    for (j = 0; j + 2 < col; j++)
    {
      if (board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2] && board[i][j] != ' ')
        return board[i][j];
    }
  }
  for (i = 2; i < row; i++)//判断反对角线和与反对角线平行的线
  {
    for (j = 0; j + 2 < col; j++)
    {
      if (board[i][j] == board[i - 1][j + 1] && board[i - 1][j + 1] == board[i - 2][j + 2]  && board[i][j] != ' ')
        return board[i][j];
    }
  }
  if (1 == draw(board, ROW, COL))
  {
    return 'p';
  }
  else
    return 'c';
}
char who_win5(char board[ROW][COL], int row, int col)//五子棋判断输赢
{
  int i = 0;
  int j = 0;
  for (i = 0; i < row; i++)//判断每行
  {
    for (j = 0; j + 4 < col; j++)
    {
      if (board[i][j] == board[i][j + 1] && board[i][j + 1] == board[i][j + 2] && board[i][j + 2] == board[i][j + 3] && board[i][j + 3] == board[i][j + 4] && board[i][j] != ' ')
        return board[i][j];
    }
  }
  for (j = 0; j < row; j++)//判断每列
  {
    for (i = 0; i + 4 < row; i++)
    {
      if (board[i][j] == board[i + 1][j] && board[i + 1][j] == board[i + 2][j] && board[i + 2][j] == board[i + 3][j] && board[i + 3][j] == board[i + 4][j] && board[i][j] != ' ')
        return board[i][j];
    }
  }
  for (i = 0; i + 4 < row; i++)//判断主对角线和主对角线平行的线
  {
    for (j = 0; j + 4 < col; j++)
    {
      if (board[i][j] == board[i + 1][j + 1] && board[i + 1][j + 1] == board[i + 2][j + 2] && board[i + 2][j + 2] == board[i + 3][j + 3] && board[i + 3][j + 3] == board[i + 4][j + 4] && board[i][j] != ' ')
        return board[i][j];
    }
  }
  for (i = 4; i < row; i++)//判断反对角线和与反对角线平行的线
  {
    for (j = 0; j + 4 < col; j++)
    {
      if (board[i][j] == board[i - 1][j + 1] && board[i - 1][j + 1] == board[i - 2][j + 2] && board[i - 2][j + 2] == board[i - 3][j + 3] && board[i - 3][j + 3] == board[i - 4][j + 4] && board[i][j] != ' ')
        return board[i][j];
    }
  }
  if (1 == draw(board, ROW, COL))
  {
    return 'p';
  }
  else
    return 'c';
}


目录
相关文章
|
11月前
|
人工智能 供应链 搜索推荐
国内知名AI Agent智能体全解析:从技术原理到顶尖产品,一篇读懂
凌晨三点,财务实习生还在手动粘贴数据?市场经理苦于海量反馈无法分析?2025年,AI Agent正悄然改变职场:它能听懂指令、跨系统操作、自动生成报告,成为真正“会干活”的数字员工。从实在Agent的实用落地,到百度“伐谋”的自我演化,再到讯飞星火、通义千问、飞书Aily的行业深耕,智能体已进入金融、制造、医疗一线。成本降本、效率翻倍、决策更准——这不是未来,是正在发生的现实。了解国内主流智能体产品与真实应用场景,掌握这场“人工智能+”变革的关键入口。
1870 0
|
8月前
|
人工智能 Linux API
零成本私有AI助理:OpenClaw阿里云/本地部署+Ollama本地模型对接+免费大模型配置新手教程
在AI工具普及的今天,API调用成本、数据隐私、网络限制成为普通用户使用AI助理的主要阻碍。OpenClaw(Clawdbot)与Ollama的组合完美解决这些问题:**完全免费、数据本地留存、无API密钥、无信用卡要求、离线可用**。Ollama作为轻量化本地大模型运行工具,支持macOS/Linux/Windows三大平台,可一键运行Llama3、Qwen2.5等开源模型;OpenClaw则作为任务执行与交互层,提供技能扩展、自动化流程、多渠道交互能力。
2319 6
|
域名解析 Kubernetes Java
图文详述Nacos配置中心使用:应用间配置共享、扩展配置文件加载优先级、新老版本差异
图文详述Nacos配置中心使用:应用间配置共享、扩展配置文件加载优先级、新老版本差异
7769 1
图文详述Nacos配置中心使用:应用间配置共享、扩展配置文件加载优先级、新老版本差异
|
人工智能 监控 安全
提效40%?揭秘AI驱动的支付方式“一键接入”系统
本项目构建AI驱动的研发提效系统,通过Qwen Coder与MCP工具链协同,实现跨境支付渠道接入的自动化闭环。采用多智能体协作模式,结合结构化Prompt、任务拆解、流程管控与安全约束,显著提升研发效率与交付质量,探索大模型在复杂业务场景下的高采纳率编码实践。
1018 26
提效40%?揭秘AI驱动的支付方式“一键接入”系统
|
关系型数据库 MySQL 分布式数据库
航天壹进制 PolarDB-X 1.0(DRDS) 数据备份容灾解决方案
本方案基于航天壹进制黑方系统,结合MySQL逻辑备份技术,为阿里云PolarDB-X 1.0(DRDS)构建非侵入式、高可靠的数据备份与恢复体系,支持全量备份、AES-256加密、压缩重删及灵活策略管理,兼容RDS MySQL操作习惯,保障数据安全与业务连续性。
|
安全 Java Docker
Docker 部署 Java 应用实战指南与长尾优化方案
本文详细介绍了Docker容器化部署Java应用的最佳实践。首先阐述了采用多阶段构建和精简JRE的镜像优化技术,可将镜像体积减少60%。其次讲解了资源配置、健康检查、启动优化等容器化关键配置,并演示了Spring Boot微服务的多模块构建与Docker Compose编排方案。最后深入探讨了Kubernetes生产部署、监控日志集成、灰度发布策略以及性能调优和安全加固措施,为Java应用的容器化部署提供了完整的解决方案指南。文章还包含大量可落地的代码示例,涵盖从基础到高级的生产环境实践。
1032 3
|
Windows
windows调整pagefile.sys,hiberfil.sys 大小
windows调整pagefile.sys,hiberfil.sys 大小
3466 1
|
Rust 安全 C++
系统编程的未来之战:Rust能否撼动C++的王座?
【8月更文挑战第31天】Rust与C++:现代系统编程的新选择。C++长期主导系统编程,但内存安全问题频发。Rust以安全性为核心,通过所有权和生命周期概念避免内存泄漏和野指针等问题。Rust在编译时确保内存安全,简化并发编程,其生态系统虽不及C++成熟,但发展迅速,为现代系统编程提供了新选择。未来有望看到更多Rust驱动的系统级应用。
559 1
|
人工智能 安全 大数据
元宇宙游戏:沉浸式体验的新纪元
在科技飞速发展的今天,元宇宙游戏作为融合了虚拟现实(VR)、增强现实(AR)、人工智能(AI)与区块链等前沿技术的数字新世界,正引领我们进入一个前所未有的沉浸式体验时代。本文将深入探讨元宇宙游戏的特点、技术基础及其如何引领沉浸式体验的新潮流。
|
Kubernetes 架构师 Java
史上最全对照表:大厂P6/P7/P8 职业技能 薪资水平 成长路线
40岁老架构师尼恩,专注于帮助读者提升技术能力和职业发展。其读者群中,多位成员成功获得知名互联网企业的面试机会。尼恩不仅提供系统化的面试准备指导,还特别针对谈薪酬环节给予专业建议,助力求职者在与HR谈判时更加自信。此外,尼恩还分享了阿里巴巴的职级体系,作为行业内广泛认可的标准,帮助读者更好地理解各职级的要求和发展路径。通过尼恩的技术圣经系列PDF,如《尼恩Java面试宝典》等,读者可以进一步提升自身技术实力,应对职场挑战。关注“技术自由圈”公众号,获取更多资源。