C语言学习-数组应用-三子棋(4.1)

简介: C语言学习-数组应用-三子棋(4.1)


三子棋的设计思路:

我们创建三个文件拆分三子棋的实现过程:


一个测试文件(test.c)游戏实现文件(game.c)头文件(game.h)



我们先对测试文件进行编辑。


1. 游戏菜单功能的实现

在 test.c 中写一个主函数:


int main()//主函数尽量放的东西少一点
{
  test();//可以通过创建一个函数实现其他功能
  return 0;
}

我们通过刚刚创建的 test 函数实现一些功能:


1. 玩一把不过瘾,在玩一把


2. 创建游戏菜单


3. 创建游戏实现函数


void test()
{
  int choice = 0;
  do  //我们使用一个do while循环,如果玩一把三子棋不过瘾,可以再玩一把
  {
  menu();
  printf("请选择:>");
  scanf("%d", &choice);//接收玩家输入的值
  switch (choice)
  {
  case 1:
    printf("三子棋游戏开始\n");
    game();//我们将游戏的实现分装成一个函数
    break;
  case 0:
    printf("游戏已退出\n");
    break;
  default:
    printf("输入错误,请重新输入\n");
    break;
  }
  } while (choice);
}
这是我们的游戏菜单:
void menu()//打印游戏菜单界面
{
  printf("***************************************\n");
  printf("*****  开始游戏:1    退出游戏:0  *****\n");
  printf("***************************************\n");
}

写到这里,我们可以先测试一下代码运行的结果:


这样,我们就完成了菜单逻辑的制作


2. 游戏功能具体实现

接下来我们要具体实现函数 game 。


2.1 棋盘的初始化与打印

实现思路:


首先,我们需要记录玩家和电脑的落子情况



通过分析,能落子的地方有九个,


我们可以通过创建一个3*3的数组对其进行记录。


我们在头文件中用#define定义常量,便于日后观察或修改



再在测试文件中引用:


#include "game.h"//引用自己的头文件
void game()//三子棋的实现
{
  char board[ROW][COL];//存放玩家或电脑的落子情况
}

接下来我们需要让落子位置初始化,并将三子棋的棋盘打印出来:


我们将初始化和棋盘打印这两个步骤分装成两个函数并在 game.c 中实现:



为了能够使用这两个函数,我们需要在头文件中声明:


void init_board(char board[ROW][COL], int row, int col);

void print_board(char board[ROW][COL], int row, int col);

初始化棋盘的具体实现:


void init_board(char board[ROW][COL], int row, int col)
{
  int i = 0;
  for (i = 0; i < row; i++)
  {
  int j = 0;
  for (j = 0; j < col; j++)
  {
    board[i][j] = ' ';//将落子位置初始化成空格
  }
  }
}
打印棋盘的具体实现:
  void print_board(char board[ROW][COL], int row, int col)
  {
  int i = 0;
  for (i = 0; i < col; i++)
  {
    printf("  %d ", i + 1);//添加纵坐标
  }
  printf("\n");
  for (i = 0; i < row; i++)
  {
    int j = 0;
    printf("%d", i + 1);//添加横坐标
    for (j = 0; j < col; j++)
    {
    printf(" %c ", board[i][j]);//打印三行,每行三个 %c 
    if (j < col - 1)//井字棋的棋盘只需要中间两排竖着的分割线
    {
      printf("|");//打印三行,每行两个‘|’
    }
    }
    printf("\n");
    if (i < row - 1)//只需要两行分割线
    {
    printf(" ");//对齐
    for (j = 0; j < col; j++)
    {
      printf("---");//打印两行,每行三个‘---’
      if (j < col - 1)
      {
      printf("|");//打印两行,每行两个‘|’
      }
    }
    }
    printf("\n");
  }
  }

最后呈现的结果是这样的:



2.2 玩家与电脑对战的实现

接下来就是下棋了,我们把下棋分为两步:


1. 玩家回合


2. 电脑回合


并且每次下完把棋盘打印出来:



然后将函数在头文件中声明,在 game.c 中实现:


声明:


void player_move(char board[ROW][COL], int row, int col);

void computer_move(char board[ROW][COL], int row, int col);

玩家回合的实现:


void player_move(char board[ROW][COL], int row, int col)
  {
  printf("玩家回合\n");
  while (1)
  {
    printf("请输入要下的坐标:>");
    int x = 0;
    int y = 0;
    scanf("%d %d", &x, &y);
    //坐标合法(在棋盘中)
    if (x >= 1 && x <= row && y >= 1 && y <= col)
    {
    if (board[x - 1][y - 1] == ' ')//坐标是空的
    {
      board[x - 1][y - 1] = '*';
      break;//选择成功后就跳出循环
    }
    else
    {
      printf("那个位置已经被占了,请重新选择\n");
    }
    }
    else
    {
    printf("你选的坐标不在棋盘内,请重新选择\n");
    }
  }
  }


电脑回合的实现:


void computer_move(char board[ROW][COL], int row, int col)
  {
  printf("电脑回合\n");
  while (1)
  {
    int x = rand() % row;//生成随机数
    int y = rand() % col;
    if (board[x][y] == ' ')
    {
    board[x][y] = '#';
    break;
    }
  }
  }

生成随机数时:



现在就到了最后一步,


2.3 判断胜负平局的实现

判断输赢:


void game()//三子棋的实现
{
  char ret = 0;//我们通过返回字符判断输赢
  char board[ROW][COL];//存放玩家或电脑的落子情况
  init_board(board, ROW, COL);//初始化棋盘
  print_board(board, ROW, COL);//打印棋盘
  while (1)//创建一个循环,直到分出胜负或平局再跳出
  {
  player_move(board, ROW, COL);//玩家下
  print_board(board, ROW, COL);
  ret = is_win(board, ROW, COL);
  if (ret != 'C')//判断游戏是否继续
  {
    break;//当ret不等于C时,跳出循环,判断输赢
  }
  computer_move(board, ROW, COL);//电脑下
  print_board(board, ROW, COL);
  ret = is_win(board, ROW, COL);
  if (ret != 'C')
  {
    break;
  }
  }
     //判断输赢
  if (ret == '*')
  {
  printf("你赢了\n");
  }
  else if (ret == '#')
  {
  printf("电脑获胜\n");
  }
  else if (ret == 'Q')
  {
    printf("平局\n");
  }
}

这样,当ret返回 * 是玩家获胜,返回 # 时电脑获胜,都不返回则平局。


接下来需要实现 is_win 函数:


(实现函数时,别忘了在头文件中声明哦)


char is_win(char board[ROW][COL], int row, int col)
  {
  int i = 0;
  //判断三行
  for (i = 0; i < row; i++)
  {
    if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
    {
    return board[i][0];
    }
  }
  //判断三列
  for (i = 0; i < col; i++)
  {
    if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
    {
    return board[0][i];
    }
  }
  //判断对角线
  if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
  {
    return board[1][1];
  }
  if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
  {
    return board[1][1];
  }
  }

还有平局的情况,可以再分装成一个函数实现:


//平局
  if (is_full(board, row, col) == 1)//判断棋盘是否满了
  {
    return 'Q';
  }
  return 'C';
函数 is_full 的实现:
  int is_full(char board[ROW][COL], int row, int col)
  {
  int i = 0;
  int j = 0;
  for (i = 0; i < row; i++)
  {
    for (j = 0; j < col; j++)
    {
    if (board[i][j] == ' ')
    {
      return 0;
    }
    }
  }
  return 1;
  }


现在,三子棋就做完了,我们一起赢一把看看效果:



学会了吗?


快去试试吧!


3. 三子棋源码

这里是源码:


1. test.c 文件:


#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"//引用自己的头文件
void menu()//打印游戏菜单界面
{
  printf("***************************************\n");
  printf("*****  开始游戏:1   退出游戏:0  *****\n");
  printf("***************************************\n");
}
void game()//三子棋的实现
{
  char ret = 0;//我们通过返回字符判断输赢
  char board[ROW][COL];//存放玩家或电脑的落子情况
  init_board(board, ROW, COL);//初始化棋盘
  print_board(board, ROW, COL);//打印棋盘
  while (1)//创建一个循环,直到分出胜负或平局再跳出
  {
  player_move(board, ROW, COL);//玩家下
  print_board(board, ROW, COL);
  ret = is_win(board, ROW, COL);
  if (ret != 'C')//判断游戏是否继续
  {
    break;//当ret不等于C时,跳出循环,判断输赢
  }
  computer_move(board, ROW, COL);//电脑下
  print_board(board, ROW, COL);
  ret = is_win(board, ROW, COL);
  if (ret != 'C')
  {
    break;
  }
  }
     //判断输赢
  if (ret == '*')
  {
  printf("你赢了\n");
  }
  else if (ret == '#')
  {
  printf("电脑获胜\n");
  }
  else if (ret == 'Q')
  {
    printf("平局\n");
  }
}
void test()
{
  srand((unsigned int)time(NULL));//通过时间戳生成随机数
  int choice = 0;
  do  //我们使用一个do while循环,如果玩一把三子棋不过瘾,可以再玩一把
  {
  menu();
  printf("请选择:>");
  scanf("%d", &choice);//接收玩家输入的值
  switch (choice)
  {
  case 1:
    printf("三子棋游戏开始:\n");
    game();//我们将游戏的实现分装成一个函数
    break;
  case 0:
    printf("游戏已退出\n");
    break;
  default:
    printf("输入错误,请重新输入\n");
    break;
  }
  } while (choice);
}
int main()//主函数尽量放的东西少一点
{
  test();//可以通过创建一个函数实现其他功能
  return 0;
}
2. game.h 文件:
#pragma once
#include
#include
#include
#define ROW 3 
#define COL 3
void init_board(char board[ROW][COL], int row, int col);
void print_board(char board[ROW][COL], int row, int col);
void player_move(char board[ROW][COL], int row, int col);
void computer_move(char board[ROW][COL], int row, int col);
char  is_win(char board[ROW][COL], int row, int col);
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;
  for (i = 0; i < row; i++)
  {
  int j = 0;
  for (j = 0; j < col; j++)
  {
    board[i][j] = ' ';//将落子位置初始化成空格
  }
  }
}
  void print_board(char board[ROW][COL], int row, int col)
  {
  int i = 0;
  for (i = 0; i < col; i++)
  {
    printf("  %d ", i + 1);//添加纵坐标
  }
  printf("\n");
  for (i = 0; i < row; i++)
  {
    int j = 0;
    printf("%d", i + 1);//添加横坐标
    for (j = 0; j < col; j++)
    {
    printf(" %c ", board[i][j]);//打印三行,每行三个 %c 
    if (j < col - 1)//井字棋的棋盘只需要中间两排竖着的分割线
    {
      printf("|");//打印三行,每行两个‘|’
    }
    }
    printf("\n");
    if (i < row - 1)//只需要两行分割线
    {
    printf(" ");//对齐
    for (j = 0; j < col; j++)
    {
      printf("---");//打印两行,每行三个‘---’
      if (j < col - 1)
      {
      printf("|");//打印两行,每行两个‘|’
      }
    }
    }
    printf("\n");
  }
  }
  void player_move(char board[ROW][COL], int row, int col)
  {
  printf("玩家回合\n");
  while (1)
  {
    printf("请输入要下的坐标:>");
    int x = 0;
    int y = 0;
    scanf("%d %d", &x, &y);
    //坐标合法(在棋盘中)
    if (x >= 1 && x <= row && y >= 1 && y <= col)
    {
    if (board[x - 1][y - 1] == ' ')//坐标是空的
    {
      board[x - 1][y - 1] = '*';
      break;//选择成功后就跳出循环
    }
    else
    {
      printf("那个位置已经被占了,请重新选择\n");
    }
    }
    else
    {
    printf("你选的坐标不在棋盘内,请重新选择\n");
    }
  }
  }
  void computer_move(char board[ROW][COL], int row, int col)
  {
  printf("电脑回合\n");
  while (1)
  {
    int x = rand() % row;//生成随机数
    int y = rand() % col;
    if (board[x][y] == ' ')
    {
    board[x][y] = '#';
    break;
    }
  }
  }
  int is_full(char board[ROW][COL], int row, int col)
  {
  int i = 0;
  int j = 0;
  for (i = 0; i < row; i++)
  {
    for (j = 0; j < col; j++)
    {
    if (board[i][j] == ' ')
    {
      return 0;
    }
    }
  }
  return 1;
  }
  char is_win(char board[ROW][COL], int row, int col)
  {
  int i = 0;
  //判断三行
  for (i = 0; i < row; i++)
  {
    if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
    {
    return board[i][0];
    }
  }
  //判断三列
  for (i = 0; i < col; i++)
  {
    if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
    {
    return board[0][i];
    }
  }
  //判断对角线
  if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
  {
    return board[1][1];
  }
  if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
  {
    return board[1][1];
  }
  //平局
  if (is_full(board, row, col) == 1)//判断棋盘是否满了
  {
    return 'Q';
  }
  return 'C';
  }

写在最后:

以上就是本篇文章的内容了,感谢你的阅读。


如果喜欢本文的话,欢迎点赞和评论,写下你的见解。


如果想和我一起学习编程,不妨点个关注,我们一起学习,一同成长。



相关文章
|
17天前
|
存储 人工智能 程序员
一文彻底搞明白C语言的数组
本文详细介绍了C语言中的数组,包括定义、初始化(静态与动态)、存储方式、访问方法及常用操作,如遍历、修改元素和作为函数参数传递。数组是C语言中最基本的数据结构之一,掌握它对编程至关重要。下篇将介绍二维数组,敬请期待!
30 0
一文彻底搞明白C语言的数组
|
3月前
|
传感器 算法 安全
【C语言】两个数组比较详解
比较两个数组在C语言中有多种实现方法,选择合适的方法取决于具体的应用场景和性能要求。从逐元素比较到使用`memcmp`函数,再到指针优化,每种方法都有其优点和适用范围。在嵌入式系统中,考虑性能和资源限制尤为重要。通过合理选择和优化,可以有效提高程序的运行效率和可靠性。
250 6
|
4月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
110 5
|
4月前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
4月前
|
机器学习/深度学习 算法 数据挖掘
C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出
本文探讨了C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出。文章还介绍了C语言在知名机器学习库中的作用,以及与Python等语言结合使用的案例,展望了其未来发展的挑战与机遇。
94 1
|
4月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
107 1
|
算法 编译器 程序员
C语言学习笔记—P11(数组<2>+图解+题例+三子棋游戏<初级>)
C语言学习笔记(数组<2>+图解+题例+三子棋游戏<初级>)
151 0
C语言学习笔记—P11(数组<2>+图解+题例+三子棋游戏<初级>)
|
存储 C语言
C语言学习笔记—P10(数组<1>+图解+题例)
C语言学习笔记(数组<1>+图解+题例)
181 0
|
C语言
C语言学习笔记——数组(二)
C语言学习笔记——数组
202 0
C语言学习笔记——数组(二)
|
C语言
C语言学习笔记——数组(一)
C语言学习笔记——数组
183 0
C语言学习笔记——数组(一)