目录
一、功能描述二、游戏部分功能介绍三、代码实现1. main()代码2.游戏菜单代码3.playgame()代码3.模式菜单和难度菜单4.初始化棋盘5.打印棋盘6.玩家下棋7.简单人机下棋8.困难人机下棋8.1 电脑检测自己这次落棋后是否能赢8.2 电脑检测是否要堵玩家的棋8.3 困难人机主函数9.判断输赢9.1 判断是否棋盘满9.2 判断输、赢、平局10.双人游戏四、游戏页面以及结果演示1.人机模式1.1 简单人机1.2 困难人机2.双人模式五、全部代码一、功能描述
该版本可以选择双人游戏和人机对战,并且人机对战分为两个等级(简单人机随机下棋;困难人机是优化后的算法具有堵棋、三连功能)。
二、游戏部分功能介绍
1.打印游戏菜单
2.初始化棋盘
3.打印棋盘
4.打印模式菜单
5.打印难度菜单
6.双人游戏
7.简单人机
8.困难人机
9.判断棋盘是否下满
10.判断输赢
三、代码实现
1. main()代码
用户输入
int main() {srand((unsigned int)time(NULL));//随机数int input = 0;do{menu();printf("请输入 >");scanf("%d", &input);switch (input) {case 1:playgame();break;case 0:printf("游戏退出...\n");break;default:printf("请输入正确的格式\n");}} while (input);return 0;}
2.游戏菜单代码
void menu() {printf("****************************\n");printf("***** 0 退出游戏 ******\n");printf("***** 1 进入游戏 ******\n");printf("****************************\n");}
3.playgame()代码
void playgame() {char model;//接收用户选择的模式char difficulty;//接收难度系数char ch;//接收数据 用于清空缓存区model_menu();printf("请你选择模式 >");while ((ch = getchar()) != '\n' && ch != EOF);//清空缓存区 scanf("%c", &model);if (model == 'a') {difficulty_menu();printf("请选择难度等级:");while ((ch = getchar()) != '\n' && ch != EOF);//清空缓存区 scanf("%c", &difficulty);if (difficulty == 'd') {printf("困难模式开始...\n");playgame_pvc(&difficulty);}else if (difficulty == 'e') {printf("简单模式开始...\n");playgame_pvc(&difficulty);}}else if (model == 'b') {printf("人人对战\n");play_game_pvp();}}
3.模式菜单和难度菜单
//模式菜单void model_menu() {printf("***************************\n");printf("** a 人机模式 b 双人模式 **\n");printf("***************************\n");}//难度菜单void difficulty_menu() {printf("***************************\n");printf("** e 简单模式 d 困难模式 **\n");printf("***************************\n");}
4.初始化棋盘
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] = ' ';}}}
5.打印棋盘
void print_board(char board[ROW][COL], int row, int col) {int i = 0;for (i = 0; i < row; i++) {//打印数据for (int j = 0; j < col; j++) {if (j < col - 1)printf(" %c |", board[i][j]);elseprintf(" %c\n", board[i][j]);}//打印分隔符if (i < row - 1) {for (int j = 0; j < row; j++) {if (j < row - 1)printf("---|");elseprintf("---\n");}}}}
6.玩家下棋
void person_move(char board[ROW][COL], int row, int col) {int i = 0, j = 0;while (1) {scanf("%d %d", &i, &j);if (board[i - 1][j - 1] == ' ') {//注意坐标与二维数组对应关系board[i - 1][j - 1] = '*';break;}else {printf("此位置已被下过,请重新落棋:");}}}
7.简单人机下棋
void computer_move_easy(char board[ROW][COL], int row, int col) {int i = 0, j = 0;printf("电脑走:\n");while (1) {i = rand() % row;j = rand() % col;if (board[i][j] == ' ') {board[i][j] = '#';break;}}}
8.困难人机下棋
8.1 电脑检测自己这次落棋后是否能赢
电脑检测棋盘在横向、纵向以及主副对角线是否有两个’#‘,如果有就代表电脑可以直接下上第三个’#‘;如果没有则需要继续判断是否需要堵玩家的棋子。代码://检查电脑是否一线两子 如果有直接赢int computer_will_win(char board[ROW][COL], int row, int col) {int i = 0;int j = 0;int p_win = 0;//标志是否直接赢if(0 == p_win){//判断电脑横行上是否会赢for (i = 0; i < row; i++){if (board[i][0] == board[i][1] && board[i][1] == '#' && board[i][2] == ' '){board[i][2] = '#';p_win = 1;break;}if (board[i][0] == board[i][2] && board[i][0] == '#' && board[i][1] == ' '){board[i][1] = '#';p_win = 1;break;}if (board[i][1] == board[i][2] && board[i][1] == '#' && board[i][0] == ' '){board[i][0] = '#';p_win = 1;break;}}if (p_win != 0)return p_win;//判断电脑列上是否有机会赢for (j = 0; j < col; j++){if (board[0][j] == board[1][j] && board[1][j] == '#' && board[2][j] == ' '){board[2][j] = '#';p_win = 1;break;}if (board[0][j] == board[2][j] && board[2][j] == '#' && board[1][j] == ' '){board[1][j] = '#';p_win = 1;break;}if (board[1][j] == board[2][j] && board[2][j] == '#' && board[0][j] == ' '){board[0][j] = '#';p_win = 1;break;}}if (p_win != 0)return p_win;}//判断电脑在对角线上是否会赢if (0 == p_win){if (board[0][0] == board[1][1] && board[1][1] == '#' && board[2][2] == ' '){board[2][2] = '#';p_win = 1;return p_win;}if (board[0][0] == board[2][2] && board[2][2] == '#' && board[1][1] == ' '){board[1][1] = '#';p_win = 1;return p_win;}if (board[1][1] == board[2][2] && board[1][1] == '#' && board[0][0] == ' '){board[0][0] = '#';p_win = 1;return p_win;}if (board[0][2] == board[1][1] && board[0][2] == '#' && board[2][0] == ' '){board[2][0] = '#';p_win = 1;return p_win;}if (board[0][2] == board[2][0] && board[2][0] == '#' && board[1][1] == ' '){board[1][1] = '#';p_win = 1;return p_win;}if (board[1][1] == board[2][0] && board[2][0] == '#' && board[0][2] == ' '){board[0][2] = '#';p_win = 1;return p_win;}}return p_win;//p_win==0 说明没有直接赢 需继续判断是否要堵棋}
8.2 电脑检测是否要堵玩家的棋
如果程序执行到此说明电脑不能直接赢,而是要判断玩家的棋子有没有一条线上出现二连’ * '的情况。如果有就“堵棋”;如果也不需要“堵棋”,那么电脑就随机下棋了(执行简单人机的核心下棋代码)。代码://检测玩家是否能一线两子 如果有就堵int people_will_win(char board[ROW][COL], int row, int col) {int i = 0;int j = 0;int k = 0;while (0 == k){//判断玩家在横行上是否会赢for (i = 0; i < row; i++){if (board[i][0] == board[i][1] && board[i][1] == '*' && board[i][2] == ' '){board[i][2] = '#';k = 1;break;}if (board[i][0] == board[i][2] && board[i][0] == '*' && board[i][1] == ' '){board[i][1] = '#';k = 1;break;}if (board[i][1] == board[i][2] && board[i][1] == '*' && board[i][0] == ' '){board[i][0] = '#';k = 1;break;}}if (k != 0)break;//判断玩家在竖列上是否会赢for (j = 0; j < col; j++){if (board[0][j] == board[1][j] && board[1][j] == '*' && board[2][j] == ' '){board[2][j] = '#';k = 1;break;}if (board[0][j] == board[2][j] && board[2][j] == '*' && board[1][j] == ' '){board[1][j] = '#';k = 1;break;}if (board[1][j] == board[2][j] && board[2][j] == '*' && board[0][j] == ' '){board[0][j] = '#';k = 1;break;}}break;}//判断玩家在对角线上是否会赢while (0 == k){if (board[0][0] == board[1][1] && board[1][1] == '*' && board[2][2] == ' '){board[2][2] = '#';k = 1;break;}if (board[0][0] == board[2][2] && board[2][2] == '*' && board[1][1] == ' '){board[1][1] = '#';k = 1;break;}if (board[1][1] == board[2][2] && board[1][1] == '*' && board[0][0] == ' '){board[0][0] = '#';k = 1;break;}if (board[0][2] == board[1][1] && board[0][2] == '*' && board[2][0] == ' '){board[2][0] = '#';k = 1;break;}if (board[0][2] == board[2][0] && board[2][0] == '*' && board[1][1] == ' '){board[1][1] = '#';k = 1;break;}if (board[1][1] == board[2][0] && board[2][0] == '*' && board[0][2] == ' '){board[0][2] = '#';k = 1;break;}break;}return k;//返回值如果是1那么已经对玩家进行了堵棋,如果是0则无需堵。}
8.3 困难人机主函数
//电脑下棋优化版void computer_move_diff(char board[ROW][COL], int row, int col) {int i = 0, j = 0;int p;printf("电脑走:\n");//电脑先检测自己这一次落棋后自己是否能赢p = computer_will_win( board, row, col);if (p == 1) {//电脑已经下过棋return;}//检查玩家是否会赢 会赢直接堵截p = people_will_win(board, row, col);if (p == 1) {//电脑对玩家进行了堵截不需要再下return;}//运行到这说明也没有赢 也没有堵截 随机下棋while (1) {i = rand() % row;j = rand() % col;if (board[i][j] == ' ') {board[i][j] = '#';break;}}}
9.判断输赢
9.1 判断是否棋盘满
代码://判断棋盘是否下满int is_full(char board[ROW][COL], int row, int col){int i, j;for (i = 0; i < row; i++){for (j = 0; j < col; j++){if (board[i][j] == ' ')//只要有位置为空就说明还没满return 0;}}//遍历全部都下满,则棋盘满了return 1;}
9.2 判断输、赢、平局
如果在任一方向出现三连一样的字符(排除三连空格情况),那么久说明有一方赢了,直接返回这个字符(#:代表电脑赢(或者玩家2)、* :代表玩家赢)。如果没有人赢就判断是否出现平局的情况(棋盘满了)。如果以上情况均未发生那就游戏继续。代码://检查是否有一方获胜char check_win(char board[ROW][COL], int row, int col){int i;//判断横向是否有一样的for (i = 0; i < row; i++){if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && (board[i][1] != ' '))return board[i][1];}//判断竖向是否有一样的for (i = 0; i < col; i++){if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')return board[1][i];}//判断对角线是否有一样的if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')return board[1][1];else if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ')return board[1][1];//如果没人赢 检查棋盘是否满 也就是平局else if (is_full(board, row, col))return '$';//以上情况都没有则分不出输赢return 0;}
10.双人游戏
有了以上各种函数基础双人游戏代码就很简单了,只需要让一方先下棋,打印出棋盘然后判断是否分出胜负;另一方下棋,打印出棋盘然后判断胜负。如此循环知道分出胜负。代码://双人对战游戏void play_game_pvp() {char key;//接收输赢结果//定义棋盘char board[ROW][COL];//初始化棋盘init_board(board, ROW, COL);//打印棋盘print_board(board, ROW, COL);while (1){printf("请p1下棋:(输入坐标)>");person_move(board, ROW, COL);//玩家1下棋print_board(board, ROW, COL);//打印棋盘key = check_win(board, ROW, COL);//判输赢平局//打印输赢结果if (key == '*'){printf("恭喜p1赢啦\n");break;}if (key == '#'){printf("恭喜p2赢了\n");break;}if (key == '$'){printf("平局了!\n");break;}printf("请p2下棋:(输入坐标)>");person2_move(board, ROW, COL);//玩家2下棋print_board(board, ROW, COL);//打印棋盘key = check_win(board, ROW, COL);//判输赢平局//打印输赢结果if (key == '*'){printf("恭喜你获得胜利啦\n");break;}if (key == '#'){printf("p2赢了\n");break;}if (key == '$'){printf("你们打平局了!\n");break;}}}
四、游戏页面以及结果演示
1.人机模式
1.1 简单人机
这时的人机还很呆 不会堵棋,玩家轻易获胜!1.2 困难人机
困难人机一旦二连就可以直接赢。困难人机可以在三个方向赌棋
2.双人模式
五、全部代码
全部代码内容较多 以上也展示的差不多了,避免页面太长,想要直接全部拷贝来自己玩一玩的小伙伴可以码云复制。
点击这里获取全部代码
写的思想比较简单 可能存在错误如有发现欢迎指正 咱再继续改进。