热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

利用C语言实现五子棋游戏

利用C语言实现五子棋游戏-本文实例为大家分享了C语言实现五子棋游戏的具体代码,供大家参考,具体内容如下一、前言本文将先介绍五子棋运行所需要的函数,最后串联成完整代码。我们需要实现的

本文实例为大家分享了C语言实现五子棋游戏的具体代码,供大家参考,具体内容如下

一、前言

本文将先介绍五子棋运行所需要的函数,最后串联成完整代码。

我们需要实现的功能有:1.菜单menu函数

                                        2.初始化棋盘Initboard函数

                                        3.显示棋盘Displayboard函数

                                        4.实现人机、人人模式的选择

                                        5.落子函数 playermove  computermove

                                        6.判断输赢ifwin函数

先来看看运行效果吧!

二、头文件

#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include
#include
#include
#define ROW 10  //定义棋盘的宽
#define COL 10  //定义棋盘的长
                //定义常量方便全局的修改
void Initboard(char board[ROW][COL], int row, int col);
//初始化棋盘
void Displayboard(char board[ROW][COL], int row, int col);
//展示棋盘
void Playermove_1(char board[ROW][COL], int row, int col,int*px,int *py);
//玩家一下棋
void Playermove_2(char board[ROW][COL], int row, int col,int*px, int *py);
//玩家二下棋
void computermove(char board[ROW][COL], int row, int col);
//电脑下棋
void game1(char board[ROW][COL], int row, int col);
//人机模式
void game2(char board[ROW][COL], int row, int col);
//人人模式
int Ifwin(char board[ROW][COL], int row, int col, int x, int y);
//判断输赢
int check_x(char board[ROW][COL], int row, int col, int x, int y);
//判断竖直五子
int check_y(char board[ROW][COL], int row, int col, int x, int y);
//判断水平五子
int check_xy_up(char board[ROW][COL], int row, int col, int x, int y);
//判断斜上五子
int check_xy_down(char board[ROW][COL], int row, int col, int x, int y);
//判断斜下五子

三、menu菜单函数

void menu()
{   //完成菜单的初始化
 printf("***********************\n");
 printf("***********************\n");
 printf("*****1.play  0.exit****\n");
 printf("***********************\n");
 printf("***********************\n");
 printf("请输入:");
}

很简单,就不多说了

四、初始化棋盘Initboard函数

初始化棋盘,为数组一一存入空格

void Initboard(char board[ROW][COL], int row, int col)
{
 int i = 0;
 int j = 0;
 for (i = 0; i 

五、显示棋盘Displayboard函数

打印简单的方格线,并打印数据内容

void Displayboard(char board[ROW][COL], int row, int col)
{
 int i = 0;
 int j = 0;
 for (j = 0; j 

六、落子函数

玩家一落子——playermove_1

void Playermove_1(char board[ROW][COL], int row, int col, int *px, int*py)//ROW可以省,COL不行
{
 int x = *px;
 int y = *py;
 while (1)
 {
  
  if (x >= 1 && x <= row && y >= 1 && y <= col)//判断输入坐标的合法性
  {
   if (board[x -1][y- 1] == ' ')//保证落子点为空
   {        
    board[x-1 ][y -1] = '*';
    *px = x; *py = y;//如果开始xy输入不合法,则要对外部xy修改,所以选择传址操作
    break;
   }
   else
   {
    printf("你不能在此处落子\n");
    printf("玩家1落子,请重新输入x y坐标: ");
    scanf("%d%d", &x, &y);
   }
  }
  else
  {
   printf("输入坐标不合法\n");
   printf("玩家落子,请重新输入x y坐标: ");
   scanf("%d%d", &x, &y);
  }
 }
 
}

玩家2落子完全相同,就不赘叙了

电脑落子

void computermove(char board[ROW][COL], int row, int col)
{
 int x = 0;
 int y = 0;
 
    //rand函数的使用需要srand函数的初始化,但srand不可以被重复调用,所以放在外部
 while (1)
 {
  x = rand() % ROW;
  y = rand() % COL;
  if (board[x][y] == ' ')//x的范围在0~row-1,所以这里x不用-1了
  {
   board[x][y] = '#';
   break;
  }
 }
 
}

七、判断输赢ifwin

根据我们下五子棋的经验,能获胜的地方必定是最后落子的水平线、竖直线、和两个斜对角线,我们只需对其进行检索即可。ifwin的返回值决定之后的switch语句

弱弱的说一句,虽然看起来多,但很多都是重复的。

int Ifwin(char board[ROW][COL], int row, int col, int x, int y)
{
 int ret;
 {
  ret = check_x(board, row, col, x, y);
  if (ret >= 5)
   return 0;
 
  ret = check_y(board, row, col, x, y);
  if (ret >= 5)
   return 0;
  ret = check_xy_up(board, row, col, x, y);
  if (ret >= 5)
   return 0;
  ret = check_xy_down(board, row, col, x, y);
  if (ret >= 5)
   return 0;
 }
 
  return 3;
}
 
 
int check_x(char board[ROW][COL], int row, int col, int x, int y)//检查x轴竖直方向
{
 int sum = 1;
 int old_x = x;
 while (x = 0 && board[x - 1][y - 1] == board[x - 2][y - 1] )
 {
  sum++;
  x--;
 }
 return sum;
}
 
 
int check_y(char board[ROW][COL], int row, int col, int x, int y)//检查y轴水平方向
{
 int sum = 1;
 int old_y = y;
 while (y= 0 && board[x-1][y-1] == board[x-1][y -2]  )
 {
  sum++;
  y--;
 }
 return sum;
}
 
 
int check_xy_up(char board[ROW][COL], int row, int col, int x, int y)//检查斜上45度
{
 int sum = 1;
 int old_x = x;
 int old_y = y;
 while (x= 0 && board[x - 1][y - 1] == board[x][y - 2])
 {
  sum++;
  x++;
  y--;
 }
 x = old_x;
 y = old_y;
 while (x - 2 >= 0 && y =0  && y-2 >=0)
 {
  sum++;
  x--;
  y--;
 }
 return sum;
}

八、人机、人人模式的选择

初始选择界面

void game()
{
 int input;
 char board[ROW][COL] = { 0 };
 Initboard(board, ROW, COL);
 //初始化棋盘
 Displayboard(board, ROW, COL);
 //展示棋盘
 printf("请选择模式:1.人机;2.玩家对战\n");
 printf("请选择:");
 
 
 do{
  scanf("%d", &input);
  printf("\n");
  switch (input)
  {
  case 1:printf("游戏模式1开始!(注意:竖为x轴,横为y轴)\n");  game1(board, ROW, COL); break;
  case 2:printf("游戏模式2开始!(注意:竖为x轴,横为y轴)\n"); ; game2(board, ROW, COL); break;
  default:printf("请重新输入\n"); break;
  }
 } while (input != 1 && input != 2);//do while语句在输入错误时反复输入
}

game1的具体实现

void game1(char board[ROW][COL], int row, int col)
{
 srand((unsigned int)time(NULL));//srand只要设置一次就可以,所以要放在while循环外
 while (1)
 {
  int ret;
  int count = 0;
  int flag = 0;
  //判读玩家的下棋
  int x; int y;
  printf("玩家落子,请依次输入x y坐标: ");
  scanf("%d%d", &x, &y);
  Playermove_1(board, row, col,&x, &y);
  count++;
  Displayboard(board, ROW, COL);
  if (count == ROW*COL)//全下满则认为平局
   ret = 1;
  else 
      ret = Ifwin(board, ROW, COL, x, y);
  switch (ret)
  {
  case 0:printf("玩家获胜\n"); flag = 1; break;
  case  1:printf("平局\n"); flag = 1; break;
  default: break;
  }
  if (flag == 1)//用flag跳出while循环
   break;
 
 
  //判断计算机的下棋
  computermove(board, row, col);
  count++;
  Displayboard(board, ROW, COL);
  if (count == ROW*COL)
   ret = 1;
  else
   ret = Ifwin(board, ROW, COL, x, y);
  switch (ret)
  {
  case 0:printf("电脑获胜\n"); flag = 1; break;
  case  1:printf("平局\n"); flag = 1; break;
  default: break;
 
  }
  if (flag == 1)
   break;
 
 }
 
 
}

作者觉得写的是挺??拢?队?粞越ㄒ椤?ame2和game1玩家一的内容很相近,就不赘述

九、作者遇到的坑点

1.输入的坐标和存在数组里的下标有减一的关系,在写的时候不要写忘记了

2.传址操作才能改变函数外的变量值

十、完整的代码

头文件就省了

int main()
{
 int input;
 do{
  system("cls");//清屏
  menu();
  scanf("%d", &input);
  switch (input)
  {
  case 1:
   printf("游戏开始\n\n");  game(); break;
  case 0:
   printf("退出游戏\n"); break;
  default:
   printf("请重新输入\n"); break;
  }
  
  Sleep(3000);//暂停3秒
 } while (input);//do while语句实现可以反复玩
 
 
 return 0;
} 
 
 
void menu()
{   //完成菜单的初始化
 printf("***********************\n");
 printf("***********************\n");
 printf("*****1.play  0.exit****\n");
 printf("***********************\n");
 printf("***********************\n");
 printf("请输入:");
}
 

void Initboard(char board[ROW][COL], int row, int col)
{
 int i = 0;
 int j = 0;
 for (i = 0; i = 1 && x <= row && y >= 1 && y <= col)//判断输入坐标的合法性
  {
   if (board[x -1][y- 1] == ' ')//保证落子点为空
   {        
    board[x-1 ][y -1] = '*';
    *px = x; *py = y;//如果开始xy输入不合法,要对外部xy修改,所以要传址操作
    break;
   }
   else
   {
    printf("你不能在此处落子\n");
    printf("玩家1落子,请重新输入x y坐标: ");
    scanf("%d%d", &x, &y);
   }
  }
  else
  {
   printf("输入坐标不合法\n");
   printf("玩家落子,请重新输入x y坐标: ");
   scanf("%d%d", &x, &y);
  }
 }
 
}
 
 
void Playermove_2(char board[ROW][COL], int row, int col, int *px, int*py)
{
 int x = *px;
 int y = *py;
 while (1)
 {
  
  if (x >= 1 && x <= row && y >= 1 && y <= col)//判断输入坐标的合法性
  {
   if (board[x - 1][y - 1] == ' ')//保证落子点为空
   {
    board[x - 1][y - 1] = '#';
    *px = x; *py = y;
    break;
   }
   else
   {
    printf("你不能在此处落子\n");
    printf("玩家2落子,请重新输入x y坐标: ");
    scanf("%d%d", &x, &y);
   }
  }
  else
  {
   printf("输入坐标不合法\n");
   printf("玩家落子,请重新输入x y坐标: ");
   scanf("%d%d", &x, &y);
  }
 }
 
}
 
 
void computermove(char board[ROW][COL], int row, int col)
{
 int x = 0;
 int y = 0;
 
 
 while (1)
 {
  x = rand() % ROW;
  y = rand() % COL;
  if (board[x][y] == ' ')
  {
   board[x][y] = '#';
   break;
  }
 }
 
}
 

int Ifwin(char board[ROW][COL], int row, int col, int x, int y)
{
 int ret;
 {
  ret = check_x(board, row, col, x, y);
  if (ret >= 5)
   return 0;
 
  ret = check_y(board, row, col, x, y);
  if (ret >= 5)
   return 0;
  ret = check_xy_up(board, row, col, x, y);
  if (ret >= 5)
   return 0;
  ret = check_xy_down(board, row, col, x, y);
  if (ret >= 5)
   return 0;
 }
 
  return 3;
}
 

int check_x(char board[ROW][COL], int row, int col, int x, int y)//检查x轴竖直方向
{
 int sum = 1;
 int old_x = x;
 while (x = 0 && board[x - 1][y - 1] == board[x - 2][y - 1] )
 {
  sum++;
  x--;
 }
 return sum;
}
 

int check_y(char board[ROW][COL], int row, int col, int x, int y)//检查y轴水平方向
{
 int sum = 1;
 int old_y = y;
 while (y= 0 && board[x-1][y-1] == board[x-1][y -2]  )
 {
  sum++;
  y--;
 }
 return sum;
}
 
 
 
int check_xy_up(char board[ROW][COL], int row, int col, int x, int y)//检查斜上45度
{
 int sum = 1;
 int old_x = x;
 int old_y = y;
 while (x= 0 && board[x - 1][y - 1] == board[x][y - 2])
 {
  sum++;
  x++;
  y--;
 }
 x = old_x;
 y = old_y;
 while (x - 2 >= 0 && y =0  && y-2 >=0)
 {
  sum++;
  x--;
  y--;
 }
 return sum;
}

如果对你有帮助和启发,作者感到很高兴。


推荐阅读
  • 《2017年3月全国计算机等级考试二级C语言上机题库完全版》由会员分享,可在线阅读,更多相关《2017年3月全国计算机等级考试二级C语言上机题库完全版( ... [详细]
  • 本文介绍了在Windows系统上使用C语言命令行参数启动程序并传递参数的方法,包括接收参数程序的代码和bat文件的编写方法,同时给出了程序运行的结果。 ... [详细]
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
  • C语言判断正整数能否被整除的程序
    本文介绍了使用C语言编写的判断正整数能否被整除的程序,包括输入一个三位正整数,判断是否能被3整除且至少包含数字3的方法。同时还介绍了使用qsort函数进行快速排序的算法。 ... [详细]
  • 本文介绍了GTK+中的GObject对象系统,该系统是基于GLib和C语言完成的面向对象的框架,提供了灵活、可扩展且易于映射到其他语言的特性。其中最重要的是GType,它是GLib运行时类型认证和管理系统的基础,通过注册和管理基本数据类型、用户定义对象和界面类型来实现对象的继承。文章详细解释了GObject系统中对象的三个部分:唯一的ID标识、类结构和实例结构。 ... [详细]
  • C语言自带的快排和二分查找
    Author🚹:CofCaiEmail✉️:cai.dongjunnexuslink.cnQQ😙:1664866311personalPage&#x ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • C语言注释工具及快捷键,删除C语言注释工具的实现思路
    本文介绍了C语言中注释的两种方式以及注释的作用,提供了删除C语言注释的工具实现思路,并分享了C语言中注释的快捷键操作方法。 ... [详细]
  • c语言\n不换行,c语言printf不换行
    本文目录一览:1、C语言不换行输入2、c语言的 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • 本文介绍了PE文件结构中的导出表的解析方法,包括获取区段头表、遍历查找所在的区段等步骤。通过该方法可以准确地解析PE文件中的导出表信息。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • C语言常量与变量的深入理解及其影响
    本文深入讲解了C语言中常量与变量的概念及其深入实质,强调了对常量和变量的理解对于学习指针等后续内容的重要性。详细介绍了常量的分类和特点,以及变量的定义和分类。同时指出了常量和变量在程序中的作用及其对内存空间的影响,类似于const关键字的只读属性。此外,还提及了常量和变量在实际应用中可能出现的问题,如段错误和野指针。 ... [详细]
author-avatar
巴黎来的
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有