C语言实现三子棋程序
脚本之家 / 编程助手:解决程序员“几乎”所有问题!
脚本之家官方知识库 → 点击立即使用
本文实例为大家分享了C语言实现三子棋的具体代码,供大家参考,具体内容如下
先直接上代码:
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. 主函数
在主函数里适当调用以上定义的几个函数,实现正确的逻辑功能。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
微信公众号搜索 “ 脚本之家 ” ,选择关注
程序猿的那些事、送书等活动等着你
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 reterry123@163.com 进行投诉反馈,一经查实,立即处理!
最新评论