用c语言写一个简单的三子棋(井字棋)
2018-04-08 13:01
447 查看
emmmm…大致就是这个效果
目录
目录1.所需的知识
2.总体思路
3.详细实现
打印菜单
执行菜单
游戏主体
棋盘打印
玩家下棋
判断输赢
电脑下棋(核心)
判断盘满
3.效果演示
1.所需的知识
c语言基本语法,二维数组。2.总体思路
将三子棋看作3x3的一个二维数组,由玩家和电脑分别填充这个数组。当行、列、叉能够达到三连时,就判断输赢。默认玩家先行且棋子为 ‘ X ’,电脑后手棋子为 ‘ 0 ’。
下面是用到的一些函数。
//game.h #ifndef __GAME_H__ #define __GAME_H__ #define ROW 3 #define CLO 3 #include <stdio.h> #include <stdlib.h> #include <time.h> #include <memory.h> void menu(); //打印菜单 void game(char arr[ROW][CLO], int row, int clo); //执行菜单 void play(char arr[ROW][CLO], int row, int clo); //游戏主体 void InitBoard(char arr[ROW][CLO], int row, int clo); //打印棋盘 void Pmove(char arr[ROW][CLO], int row, int clo); //玩家下棋 void Cmove(char arr[ROW][CLO], int row, int clo); //电脑下棋 int Isfull(char arr[ROW][CLO], int row, int clo); //检测盘满 int Iswin(char arr[ROW][CLO], int row, int clo); //判断输赢 #endif
下面是主函数
//test.c #include"game.h" int main() { srand((unsigned int)time(NULL)); //产生随机数种子 char arr[ROW][CLO]; game(arr,ROW,CLO); system("pause"); return 0; }
3.详细实现
打印菜单
void menu() { printf("*******************\n"); printf("*******1.play *****\n"); printf("*******2.exit *****\n"); printf("*******************\n"); }
这个函数打印菜单选项。
执行菜单
void game(char arr[ROW][CLO], int row, int clo) { int input = 0; do { menu(); scanf_s("%d",&input); memset(arr, ' ', ROW*CLO * sizeof(arr[0][0])); switch (input) { case 1: play(arr, row, clo); break; case 2: exit(0); break; default:printf("你按错键了?\n"); } } while (input); }
这个函数是菜单执行部分。其中 memset 用来初始化二位字符数组为全‘ 空格 ’。
接着,用switch语句来判断玩家选项。
游戏主体
void play(char arr[ROW][CLO], int row, int clo) { int flag = 0; InitBoard(arr, row, clo); while (1) { printf("人类走\n"); Pmove(arr, row, clo); InitBoard(arr, row, clo); flag = Iswin(arr, row, clo); if (flag == 1) { printf("玩家赢\n"); break; } flag = Isfull(arr, row, clo); if (flag == 4) { printf("棋盘满,游戏结束\n"); break; } printf("电脑走\n"); Cmove(arr, row, clo); InitBoard(arr, row, clo); flag = Iswin(arr, row, clo); if (flag == 1) { printf("电脑赢\n"); break; } } }
这个函数里面拥有一个 while 死循环,它的跳出条件是 玩家赢 、 电脑赢 、棋盘满。
flag == 1 表示电脑或者玩家获胜,flag == 4 表示棋盘满了。
这里将棋盘满的检测放在玩家行动后,因为只有先手才能使棋盘满。
棋盘打印
void InitBoard(char arr[ROW][CLO], int row, int clo) { int i = 0; int j = 0; for (j = 0; j < row; j++) { for (i = 0; i < clo; i++) { printf(" %c ", arr[j][i]); if (i < (clo - 1)) { printf("|"); } } printf("\n"); if (j < row - 1) { for (i = 0; i < clo; i++) { printf("---"); if (i < (clo - 1)) { printf("|"); } } } printf("\n"); } }
这个棋盘打印函数可以扩展。只要改变ROW 和 CLO 的值就可以改变棋盘大小。
例如: 7x7的棋盘
玩家下棋
void Pmove(char arr[ROW][CLO], int row, int clo) { printf("请输入坐标(空格隔开)\n"); int m = 0, n = 0; while (1) { scanf_s("%d %d", &m, &n); if (((m >= 1) && (m <= 3)) && ((n >= 1) && (n <= 3))) { if (arr[m - 1][n - 1] == ' ') { arr[m - 1][n - 1] = 'X'; break; } else { printf("这里可能已经有棋子了\n"); } } else { printf("可能你输错了\n"); } } }
这个是玩家输入函数。这里注意判断输入是否合法,输入范围1~3,并查看该点是否有棋子。考虑玩家因素,将获取的数字-1,使之成为数组变量。
判断输赢
int Iswin(char arr[ROW][CLO], int row, int clo) { //行 int i = 0; for (i = 0; i < row; i++) { if (((arr[i][0] == arr[i][1]) && (arr[i][1] == arr[i][2])) && ((arr[i][0] != ' '))) { return 1; } } //列 for (i = 0; i < clo; i++) { if ((arr[0][i] == arr[1][i]) && (arr[1][i] == arr[2][i]) && ((arr[0][i] != ' ') )) { return 1; } } //叉 if ((arr[0][0] == arr[1][1]) && (arr[1][1] == arr[2][2]) && ((arr[0][0] != ' ') )) { return 1; } if ((arr[0][2] == arr[1][1]) && (arr[1][1] == arr[2][0]) && ((arr[0][2] != ' '))) { return 1; } return 0; }
这个函数判断输赢。由于3行3列,所以用for循环扫描3次。当连续三字相同且不为‘ 空格 ’,那么取得胜利。
电脑下棋(核心)
void Cmove(char arr[ROW][CLO], int row, int clo) { int flag = 0; int m = 0, n = 0; for (m = 0; m < row; m++) { for (n = 0; n < row; n++) { if (arr[m] == ' ') { arr[m] = '0'; flag = Iswin(arr, row, clo); if (flag == 0) { arr[m] = ' '; } if (flag == 1) { break; } } } if (flag == 1) { break; } } if (flag == 0) { for (m = 0; m < row; m++) { for (n = 0; n < row; n++) { if (arr[m] == ' ') { arr[m] = 'X'; flag = Iswin(arr, row, clo); if (flag == 0) { arr[m] = ' '; } if (flag == 1) { arr[m] = '0'; break; } } } if (flag == 1) { break; } } if ((m == 3) && (n == 3)) { while (1) { m = rand() % 3; n = rand() % 3; if (arr[m] == ' ') { arr[m] = '0'; break; } } } } }
这是个电脑下棋函数。这里动了点歪脑筋。
第一个双层for循环的作用是:依次检测空位。如果是空位,那么先让该空位被’ 0 ‘填充,然后判断能不能获胜。能获胜就跳出 且 flag == 1,不能获胜就把改位再次置成空位。
接上述不能获胜。如果扫描完后发现并不能获胜,那么采取防守策略。
第二个双层for循环也是检测空位。如果是空位,那么让该位被 ’ X ‘填充,(相当电脑伪装成玩家先走一步)。填充后判断输赢,如果能够获胜,那么电脑再将这个位置改为‘ 0 ’,达到阻止玩家取胜的目的。
最后如果既不能取得胜利,也不用阻止玩家获胜。那么,就让电脑随机找位置下棋。
判断盘满
int Isfull(char arr[ROW][CLO], int row, int clo) { int i = 0, j = 0; int count = 0; for (i = 0; i < row; i++) { for (j = 0; j < clo; j++) { if (arr[i][j] != ' ') { count ++; } } } if (count == 9) { return 4; } return 3; }
这个函数是判断棋盘是否满。使用count变量计数,扫描棋盘,如果不为‘ 空格 ’的位置有九个,那么就表示棋盘满了。
3.效果演示
会堵人的电脑会优先自己胜利的电脑
棋盘满效果
PS:先手优势很大,不出意外的话是先手赢,或是平局。
依此类推,五子棋在15x15及其以上的棋盘,先手必胜。
但是电脑获胜算法非常复杂,反正我是写不出来。
相关文章推荐
- Apache模块开发/用C语言扩展apache(3:一个非常简单的apache module)
- 【C语言】简单实现三子棋
- 【C语言】简单思路找一个数组中重复次数最多的数
- 用c语言简单实现三子棋游戏
- 【C语言基础】C语言三子棋的简单实现
- 一个简单用C语言实现的日志函数
- 【C语言】实现一个简单的通讯录
- 一个简单的双向链表(C语言)
- 一个简单的三子棋游戏(c语言实现)
- 为什么C语言在2013年仍然很重要:一个简单的例子
- 一个简单的四则运算程序C语言实现--无法处理括号
- 一个简单的C语言嵌套问题
- 关于一个简单shellcode封装成C语言的形式
- C语言循环结构简单练习2——判断一个数是否为素数
- C语言写了一个简单的通讯录
- 一个简单的c语言题目
- C语言模块化开发简单实例——实现一个计算器的加减乘除
- 一个通用简单线程池实现的初步封装(C语言)
- 用C语言实现一个简单的HTTP客户端(HTTP Client)
- 用c语言实现简单三子棋游戏