广告位联系
返回顶部
分享到

C语言实现三子棋程序的代码

C语言 来源:互联网搜集 作者:秩名 发布时间:2020-03-21 18:40:45 人浏览
摘要

先直接上代码: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77

先直接上代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#define _CRT_SECURE_NO_WARNINGS 1
 
#include<stdio.h>   //2.实现三子棋游戏。
#include<Windows.h>  //Sleep() RAND_MAX 的头文件
 
void menu()      //打印菜单
{
 printf("****************************\n");
 printf("**** 欢迎来到三子棋游戏 ****\n");
 printf("**** 1、 进入游戏  ****\n");
 printf("**** 0、 退出游戏  ****\n");
 printf("****************************\n");
 printf("请输入:->");
}
 
void print_chessboard(char coord[][3]) //打印棋盘函数
//多维数组在传参时,接收数组的形参最多只能是第一个方括号里没有数字(下标范围)
   //否则就会出错(因为此时编译器不知道你要把传过来的数组的元素划分成几行几列,
   //但是当除第一个方括号的其他方括号都有值时,就可以经过计算知道第一个方括号的值是多少
 int i = 0;
 int index_x = 0;
 int index_y = 0;
 for (i = 1; i <= 153; i++)
 {   
  char out_ch = ' ';
  if ((i % 51 == 20) || (i % 51 == 26) || (i % 51 == 32) )
  {
   out_ch = coord[index_x][index_y];
   index_x++;
   if (index_x < 3)
   {
    index_x = 0;
    index_y++;
   }
  }
  else if ((i % 17 == 6) || (i % 17 == 12))
  {
   out_ch = '|';
  }
  else if( (i >= 35 && i <= 51 && i != 40 && i != 46) || \
     (i >= 86 && i <= 102 && i != 91 && i != 97))
  {
   out_ch = '_';
  }
  putchar(out_ch);
  if (i % 17 == 0)     //每输出 17 个字符换下一行输出
  {
   printf("\n");
  }
 }
}
 
void winer(char coord[][3], int *flag);  //赢家判断函数的声明
 
int computer(char coord[][3])        //电脑下棋
{
 int flag = 0;
 int index_x2 = 0;
 int index_y2 = 0;
 srand((unsigned)time(NULL));
 while (1)
 {
  index_x2 = 2 * rand() / RAND_MAX;     //产生 0--2 的随机数
  index_y2 = 2 * rand() / RAND_MAX;
  if ((coord[index_x2][index_y2] != '*') && (coord[index_x2][index_y2] != 'o'))
  {             //判断该位置是否已有落子
   coord[index_x2][index_y2] = 'o';
   winer(coord, &flag);
   if (flag == 1)
   {
    return 1;
   }
   return 0;
  }
 }
}
 
int player(char coord[][3], int index_x1, int index_y1) //玩家下棋
{
 int flag = 0;
 int ret = 0;
 if ((coord[index_x1][index_y1] == '*') || (coord[index_x1][index_y1] == 'o'))
 {              //判断该位置是否已有落子
  printf("此位置已有棋子,请重下!\n");
  return 0;
 }
 else
 {
  coord[index_x1][index_y1] = '*';
  winer(coord, &flag);
  if (flag == 1)
  {
   return 1;
  }
  ret = computer(coord);
  if (ret == 1)
  {
   return 1;
  }
  print_chessboard(coord);  //把打印棋盘放在是因为想在两人都走完一次后再打印当前棋盘状态
 }
 return 0;
}
 
void winer(char coord[][3],int *flag)   //判断是否产生赢家,赢家是谁
{
 char line_ch[8][4] = { { coord[0][0], coord[1][1], coord[2][2] }, { coord[0][0], coord[0][1], coord[0][2] }, \
       { coord[0][0], coord[1][0], coord[2][0] }, { coord[0][1], coord[1][1], coord[2][1] }, \
       { coord[0][2], coord[1][2], coord[2][2] }, { coord[1][0], coord[1][1], coord[1][2] }, \
       { coord[2][0], coord[2][1], coord[2][2] }, { coord[0][2], coord[1][1], coord[2][0] } };
       //把所有能赢的情况定义成一个字符串数组
 int i = 0;
 for (i = 0; i < 8; i++)
 {
  if (strcmp(line_ch[i],"***") == 0) //判断此时玩家已输入的落子能不能组成一个使玩家能赢的字符串
  {
   print_chessboard(coord);   //先打印棋盘,再判断谁胜谁负
   printf("\n恭喜您赢了!\n");
   *flag = 1;      //玩家赢,使最开始设置的赢的标志位为1,结束此次游戏
   return;
  }
  else if (strcmp(line_ch[i],"ooo") == 0)
  {
   print_chessboard(coord);
   printf("\n很遗憾,您输了!\n");
   *flag = 1;
   return;
  }
  else
  {
   ;
  }
 }
}
 
int main()
{
 while (1)
 {
  int num = 0;   //决定开始或退出游戏
  int x = 0;
  int y = 0;
  int i = 4;    //一次游戏最多的内层while循环可循环的次数
  int ret = 0;   //是否结束此次游戏的标志位
  int is_play = 0;  //是否再次玩游戏的标志位
  char coordinate[3][3] = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' };
        //为了拓展游戏比较方便,可以把行和列定义成宏定义
  menu();    
  scanf("%d", &num);
  if (num == 0)
  {
   printf("5秒后退出程序!\n");
   Sleep(5000);
   exit(0);
  }
  computer(coordinate);  //因为设计电脑智商低,所以游戏开始前先让电脑落一子
  print_chessboard(coordinate);
  while ((i))    //因为总共有九个位置可以落子,已用一个,还剩八个,每次循环不结束的话会用掉两个
         //所以最多循环四次
  {
   printf("请输入 X、Y 的坐标(0--2)来确定你下棋的位置:"); //也可以加一个判断输入是否合法
   scanf("%d %d", &x, &y);
   ret = player(coordinate, x, y);
   if (ret == 1)
   {
    break;
   }
   i--;
  }
  printf("\n");
  printf("请选择接下来的操作:\n");
  printf("1、 再玩一次游戏 0、退出游戏系统\n");
  scanf("%d", &is_play);
  if(is_play == 0)
  {
   printf("5秒后退出程序!\n");
   Sleep(5000);
   exit(0);
  }
  else
  {
   system("cls");
  }
 }
 system("pause");
 return 0;
}
 

程序一共设计了六个函数,一个主函数,五个自定义函数— 菜单打印函数、棋盘打印函数、电脑下棋函数、玩家下棋函数、赢家判断函数。

其中最难设计的就是棋盘打印函数和赢家判断函数。这两个函数需要完成的任务多,计算量大,逻辑设计麻烦。

下面来分析一下几个函数的设计思路:

1.菜单打印函数

这个函数很简单,一看就能明白,这儿就不多说了。

2.棋盘打印函数

首先得构思一下三子棋的棋盘应该是什么样

简单点,上图就可以作为三子棋棋盘(其实就是利用 putchar() 函数和 printf() 把显示在屏幕上的字符一个个,一行行打印上去)。设计时可把其分成四部分来看,(1) 短竖杠 ; (2) 短横杠 ; (3) 棋子(用一个二维字符数组来定义每一个棋子,用二维是因为方便输入的 X 和 Y 值与数组下标对应) ; (4) 空格(一开始打印的时候,因为还没有落子,所以把棋子也设计成空格)。 先确定要输入几行几列字符,以确定循环输出的次数,还有确定每个位置该输出的字符,这样就可以依靠循环和判断打印出棋盘了。

3 . 赢家判断函数

在每次落子后都要先进行一次判断,看是否已经产生赢家了。
因为会出现赢家的情况就八种———–

{ coord[0][0], coord[1][1], coord[2][2] }, { coord[0][0], coord[0][1], coord[0][2] },
{ coord[0][0], coord[1][0], coord[2][0] }, { coord[0][1], coord[1][1], coord[2][1] },
{ coord[2][0], coord[2][1], coord[2][2] }, { coord[1][0], coord[1][1], coord[1][2] },
{ coord[2][0], coord[2][1], coord[2][2] }, { coord[0][2], coord[1][1], coord[2][0] }

定义一个字符串数组,里面共有八个字符串,每一个字符串就是上面的一个花括弧里的内容,当某个字符串的内容与 * 或 ooo 相等,那么说明产生赢家了,否则不会产生赢家,那么就用一个循环,遍历字符串数组里的每一个字符串,判断是否会产生赢家。

4. 玩家下棋函数

玩家通过输入 x,y 坐标来确定落子的位置, x,y 对应的就是 定义的棋子二维字符数组的下标,每次先判断输入的 x,y 值对应数组下标的元素是否是 * 或 o ,是的话就说明此处已有落子,得重新输入,不是的话就落下该棋子,接着判断是否产生赢家,是的话就结束此次游戏,不是的话就判断棋盘上是否还有空位置没落子,有的话就轮到电脑继续落子,没有的话就结束此次游戏。

5. 电脑下棋函数

因为电脑是自动落子,所以得为电脑产生一个随机的 棋子二维数组下标值,使电脑随机落子,这个用srand((unsigned)time(NULL)); index_x2 = 2 * rand() / RAND_MAX; index_y2= 2 * rand() / RAND_MAX;来实现把它们放在一个while 死循环里,因为可能产生的两个随机下标那儿已经有棋子了,需要重新产生一次随机下标,当下标值与已落棋子不冲突时,就落下该棋子,接着判断是否产生赢家,是的话,就结束此次游戏,不是的话就判断棋盘上是否还有空位置没落子,有的话就轮到玩家继续落子,没有的话就结束此次游戏。

6. 主函数

在主函数里适当调用以上定义的几个函数,实现正确的逻辑功能。


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://blog.csdn.net/ljx_5489464/article/details/50342195
相关文章
  • C++中类的六大默认成员函数的介绍

    C++中类的六大默认成员函数的介绍
    一、类的默认成员函数 二、构造函数Date(形参列表) 构造函数主要完成初始化对象,相当于C语言阶段写的Init函数。 默认构造函数:无参的构
  • C/C++实现遍历文件夹最全方法总结介绍

    C/C++实现遍历文件夹最全方法总结介绍
    一、filesystem(推荐) 在c++17中,引入了文件系统,使用起来非常方便 在VS中,可以直接在项目属性中调整: 只要是C++17即以上都可 然后头文件
  • C语言实现手写Map(数组+链表+红黑树)的代码

    C语言实现手写Map(数组+链表+红黑树)的代码
    要求 需要准备数组集合(List) 数据结构 需要准备单向链表(Linked) 数据结构 需要准备红黑树(Rbtree)数据结构 需要准备红黑树和链表适配策略
  • MySQL系列教程之使用C语言来连接数据库

    MySQL系列教程之使用C语言来连接数据库
    写在前面 知道了 Java中使用 JDBC编程 来连接数据库了,但是使用 C语言 来连接数据库却总是连接不上去~ 立即安排一波使用 C语言连接 MySQL数
  • 基于C语言实现简单学生成绩管理系统

    基于C语言实现简单学生成绩管理系统
    一、系统主要功能 1、密码登录 2、输入数据 3、查询成绩 4、修改成绩 5、输出所有学生成绩 6、退出系统 二、代码实现 1 2 3 4 5 6 7 8 9 10 11
  • C语言实现共享单车管理系统

    C语言实现共享单车管理系统
    1.功能模块图; 2.各个模块详细的功能描述。 1.登陆:登陆分为用户登陆,管理员登陆以及维修员登录,登陆后不同的用户所执行的操作
  • C++继承与菱形继承的介绍

    C++继承与菱形继承的介绍
    继承的概念和定义 继承机制是面向对象程序设计的一种实现代码复用的重要手段,它允许程序员在保持原有类特性的基础上进行拓展,增加
  • C/C++指针介绍与使用介绍

    C/C++指针介绍与使用介绍
    什么是指针 C/C++语言拥有在程序运行时获得变量的地址和操作地址的能力,这种用来操作地址的特殊类型变量被称作指针。 翻译翻译什么
  • C++进程的创建和进程ID标识介绍
    进程的ID 进程的ID,可称为PID。它是进程的唯一标识,类似于我们的身份证号是唯一标识,因为名字可能会和其他人相同,生日可能会与其他
  • C++分析如何用虚析构与纯虚析构处理内存泄漏

    C++分析如何用虚析构与纯虚析构处理内存泄漏
    一、问题引入 使用多态时,如果有一些子类的成员开辟在堆区,那么在父类执行完毕释放后,没有办法去释放子类的内存,这样会导致内存
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计