分析需求

  1. 制作菜单进入或退出游戏
  2. 实现棋盘和落子的显示
  3. 玩家落子
  4. 判断是否获胜
  5. 判断是否和棋

代码实现

1.制作菜单进入或退出游戏

void menu()
{printf("1、开始游戏\n");printf("0、退出游戏\n");
}

通过printf打印简洁的菜单

2.实现棋盘和落子的显示

char arr[3][3] = { '1','2', '3', '4', '5', '6', '7', '8', '9' };
void checkerboard(char arr[3][3])
{printf(" %c | %c | %c \n", arr[0][0], arr[0][1], arr[0][2]);printf("-----------\n");printf(" %c | %c | %c \n", arr[1][0], arr[1][1], arr[1][2]);printf("-----------\n");printf(" %c | %c | %c \n", arr[2][0], arr[2][1], arr[2][2]);
}

由于三子棋落子的范围是一个面,故选用二维数组,使落子更加直观,方便理解。

3.玩家落子

落子时需要包含对落子位置是否正确的判断,使用循环实现落子错误重新落子,确认位置正确后再将落子存入二维数组,在落子结束后,判断是否满足获胜条件,也可以将判断获胜的步骤单独写在main函数中。

int choice1(char arr[3][3])//一号选手下
{int choice = 0;while (true)//死循环实现输入错误重新输入{printf("一号玩家请选择位置:\n");scanf("%d", &choice);printf("\n");if (choice <= 0 || choice > 9)//输入错误情况{printf("输入错误,请重新输入!\n\n");continue;//结束本次循环,开始下一次循环}if (check(arr, choice) == 0)//检查落子处是否不含子{continue;}if (choice <= 3 && choice > 0)//写入{arr[0][choice - 1] = '*';break;}else if (choice <= 6 && choice > 3){arr[1][choice - 4] = '*';break;}else if (choice > 6){arr[2][choice - 7] = '*';break;}}if (win(arr, choice) == 1)//判断是否获胜{printf("一号玩家获胜!\n\n");return 1;//获胜返回1到main函数}else{return 0;}
}

4.判断是否获胜

对于是否获胜的判断是整个游戏的难点,涉及到多种情况,需要逐步分析。

int win(char arr[3][3], int choice)
{char a;//用于存放落子(白子‘*’或黑子‘#’),以判断是否存在三子连线if (choice <= 3 && choice > 0)//落子于第一行{a = arr[0][choice - 1];//arr[0][choice - 1]即为落子位置if (choice - 1 == 0 || choice - 1 == 2)//如果落子于边缘两点(左上或右上){if (arr[0][choice - 1] == arr[1][1] && arr[0][choice - 1] == arr[2][abs(3 - choice)])//斜情况{//无论左上还是右上,斜情况必过中心点,即arr[1][1],abs()目的是计算绝对值,头文件<math.h>,使输1得2,输3得0return 1;//1即代表玩家获胜}else if (arr[0][choice - 1] == arr[0][1] && arr[0][choice - 1] == arr[0][abs(3 - choice)])//横情况{//第一排横情况必过一排中间点,即arr[0][1],再使用abs(),实现使输1得2,输3得0return 1;}else if (arr[0][choice - 1] == arr[1][choice - 1] && arr[0][choice - 1] == arr[2][choice - 1])//竖情况{//竖情况列固定,只需要更改行return 1;}else//如果都不符合{return 0;//玩家未获胜}}else if (choice - 1 == 1)//落子位于第一行中心{if (arr[0][choice - 1] == arr[0][0] && arr[0][choice - 1] == arr[0][2])//横情况{//需要检查是否相等的位置固定为左上点arr[0][0],右上点arr[0][2]return 1;}else if (arr[0][choice - 1] == arr[1][1] && arr[0][choice - 1] == arr[2][1])//竖情况{//竖情况列固定,只需要更改行return 1;}else//如果都不符合{return 0;//玩家未获胜}}}else if (choice <= 6 && choice > 3)//落子于第二行{a = arr[1][choice - 4];//在我们的棋盘上,第二行位置为:4,5,6,所以需要-4,以寻找落子位置if (choice - 4 == 1)//落子位于第二行中心{if (arr[0][0] == arr[1][choice - 4] && arr[2][2] == arr[1][choice - 4])//右斜情况‘\’{//右斜情况需检查的位置固定,为左上arr[0][0],右下arr[2][2]return 1;}else if (arr[0][2] == arr[1][choice - 4] && arr[2][0] == arr[1][choice - 4])//左斜情况‘/’{//左斜情况需检查的位置固定,为右上arr[0][2],左下arr[2][0]return 1;}else if (arr[1][choice - 4] == arr[1][0] && arr[1][choice - 4] == arr[1][2])//横情况{//横情况需检查的位置固定,为中左arr[1][0],中右arr[1][2]return 1;}else if (arr[1][choice - 4] == arr[0][1] && arr[1][choice - 4] == arr[2][1])//竖情况{//竖情况需检查的位置固定,为中上arr[0][1],中下arr[2][1]return 1;}else//如果都不符合{return 0;//玩家未获胜}}else if (choice - 4 != 1)//如果落子于边缘两点(中左或中右){if (arr[1][choice - 4] == arr[1][1] && arr[1][choice - 4] == arr[1][6 - choice])//横情况{//横情况必过第二行中心点,即arr[1][1],6 - choice实现输4得2,输6得0return 1;}else if (arr[1][choice - 4] == arr[0][choice - 4] && arr[1][choice - 4] == arr[2][choice - 4])//竖情况{//竖情况列确定,行改变return 1;}else//没有斜情况{return 0;//玩家未获胜}}}else if (choice > 6)//位于第三行{a = arr[2][choice - 7];//在我们的棋盘上,第三行位置为:7,8,9,所以需要-7,以寻找落子位置if (choice - 7 == 0 || choice - 7 == 2)//如果落子于边缘两点(左下或右下){if (arr[2][choice - 7] == arr[1][1] && arr[2][choice - 7] == arr[0][9 - choice])//斜情况{//无论左上还是右上,斜情况必过中心点,即arr[1][1],9 - choice实现输7得2,输9得0return 1;}else if (arr[2][choice - 7] == arr[2][1] && arr[2][choice - 7] == arr[2][9 - choice])//横情况{//横情况必过中心点,即arr[1][1],9 - choice实现输7得2,输9得0return 1;}else if (arr[2][choice - 7] == arr[1][choice - 7] && arr[2][choice - 7] == arr[0][choice - 7])//竖情况{//竖情况列确定,行改变return 1;}else//如果都不符合{return 0;//玩家未获胜}}else if (choice - 7 == 1)//落子位于第三行中心{if (arr[2][choice - 7] == arr[2][0] && arr[2][choice - 7] == arr[2][2])//横情况{//横情况需要检查的点固定为左下arr[2][0]和右下arr[2][2]return 1;}else if (arr[2][choice - 7] == arr[1][choice - 7] && arr[2][choice - 7] == arr[0][choice - 7])//竖情况{//竖情况列确定,行改变return 1;}else//如果都不符合{return 0;//玩家未获胜}}}
}

5.判断是否和棋

由于三子棋最多有九步,所以和棋只需要在白子下完后进行检查即可(第九步为白棋下)。

int finish(char arr[3][3])
{int i = 0;int j = 0;for (i = 0; i < 3; i++){for (j = 0; j < 3; j++){if (arr[i][j] != '*'&&arr[i][j] != '#'){return 0;}if (i == 2 && j == 2){if (arr[i][j] == '*' || arr[i][j] == '#'){printf("和棋!\n\n");return 1;}}}}
}

当数组中每一个位置都有白子‘*’或黑子‘#’时,游戏和棋。


整体代码

为使代码条理清晰,编写过程中使用了两个源文件'prepare.cpp'和'main.cpp',一个头文件‘prepare.h’,头文件用于存放函数声明,'prepare.cpp'用于定义mian函数所需要的函数,‘main.cpp’存放main函数。

流程:打印棋盘棋子->落子->判断获胜与否->判断和棋与否->落子->判断获胜与否->开始下一轮

//头文件"prepare.h"
#pragma once#include <stdio.h>//放于自己编写的头文件中,避免重复使用
#include <math.h>//实现abs()函数void menu();//菜单void checkerboard(char arr[3][3]);//打印棋子棋盘int choice1(char arr[3][3]);//一号玩家落子int choice2(char arr[3][3]);//二号玩家落子int win(char arr[3][3], int choice);//判断是否获胜int finish(char arr[3][3]);//和棋int check(char arr[3][3], int choice);//用于判断落子是否正确
#include "prepare.h"//使用自己编写的头文件int main()
{int input = 0;//选择do//do...while使循环至少执行一次{char arr[3][3] = { '1','2', '3', '4', '5', '6', '7', '8', '9' };//二维数组menu();//菜单printf("请输入你的选择:");scanf("%d", &input);switch (input){case 1:printf("游戏开始!\n\n");while (true)//死循环实现多次下子{static int i = 1;//使用static修饰,防止开始下一次循环时i变成1printf("第%d轮开始!\n", i);//提示checkerboard(arr);//打印棋盘和棋子if (choice1(arr) == 1)//一号选手下,当返回值为1,代表一号选手获胜,具体查看函数choice1(arr){checkerboard(arr);//展示棋盘和棋子printf("\n");i = 1;//在下一次游戏开始时,i重新计数。break;//该次游戏结束}if (finish(arr) == 1)//由于三子棋最多有九步,所以和棋只需要在白子下完后进行检查即可{checkerboard(arr);//同上printf("\n");i = 1;break;}checkerboard(arr);//展示棋盘供二号选手落子if (choice2(arr) == 1)//二号选手下{checkerboard(arr);//同上printf("\n");i = 1;break;}++i;//计数加1printf("\n");}break;//退出switchcase 0:printf("退出成功!\n");break;//退出switchdefault:printf("输入错误,请重新选择!\n");break;//退出switch}} while (input);//如果输入0,则不符合条件,结束循环,输入其他则循环继续return 0;
}
#include "prepare.h"void menu()
{printf("1、开始游戏\n");printf("0、退出游戏\n");
}void checkerboard(char arr[3][3])
{printf(" %c | %c | %c \n", arr[0][0], arr[0][1], arr[0][2]);printf("-----------\n");printf(" %c | %c | %c \n", arr[1][0], arr[1][1], arr[1][2]);printf("-----------\n");printf(" %c | %c | %c \n", arr[2][0], arr[2][1], arr[2][2]);
}int choice1(char arr[3][3])//一号选手下
{int choice = 0;while (true)//死循环实现输入错误重新输入{printf("一号玩家请选择位置:\n");scanf("%d", &choice);printf("\n");if (choice <= 0 || choice > 9)//输入错误情况{printf("输入错误,请重新输入!\n\n");continue;//结束本次循环,开始下一次循环}if (check(arr, choice) == 0)//检查落子处是否不含子{continue;}if (choice <= 3 && choice > 0)//写入{arr[0][choice - 1] = '*';break;}else if (choice <= 6 && choice > 3){arr[1][choice - 4] = '*';break;}else if (choice > 6){arr[2][choice - 7] = '*';break;}}if (win(arr, choice) == 1)//判断是否获胜{printf("一号玩家获胜!\n\n");return 1;//获胜返回1到main函数}else{return 0;}
}int choice2(char arr[3][3])//除落子为黑子‘#’外,其余与choice1相同
{int choice = 0;while (true){printf("二号玩家请选择位置:\n");scanf("%d", &choice);if (choice <= 0 || choice > 9){printf("输入错误,请重新输入!\n\n");continue;}if (check(arr, choice) == 0){continue;}if (choice <= 3 && choice > 0){arr[0][choice - 1] = '#';break;}else if (choice <= 6 && choice > 3){arr[1][choice - 4] = '#';break;}else if (choice > 6){arr[2][choice - 7] = '#';break;}}if (win(arr, choice) == 1)//判断是否获胜{printf("二号玩家获胜!\n\n");return 1;}else{return 0;}
}int check(char arr[3][3], int choice)//逐行判断
{if (choice <= 3 && choice > 0)//第一行{if (arr[0][choice - 1] == '*' || arr[0][choice - 1] == '#'){printf("该位置已被选择,请重新下子!\n\n");return 0;}}else if (choice <= 6 && choice > 3)//第二行{if (arr[1][choice - 4] == '*' || arr[1][choice - 4] == '#'){printf("该位置已被选择,请重新下子!\n\n");return 0;}}else if (choice > 6)//第三行{if (arr[2][choice - 7] == '*' || arr[2][choice - 7] == '#'){printf("该位置已被选择,请重新下子!\n\n");return 0;}}
}int win(char arr[3][3], int choice)
{char a;//用于存放落子(白子‘*’或黑子‘#’),以判断是否存在三子连线if (choice <= 3 && choice > 0)//落子于第一行{a = arr[0][choice - 1];//arr[0][choice - 1]即为落子位置if (choice - 1 == 0 || choice - 1 == 2)//如果落子于边缘两点(左上或右上){if (arr[0][choice - 1] == arr[1][1] && arr[0][choice - 1] == arr[2][abs(3 - choice)])//斜情况{//无论左上还是右上,斜情况必过中心点,即arr[1][1],abs()目的是计算绝对值,头文件<math.h>,使输1得2,输3得0return 1;//1即代表玩家获胜}else if (arr[0][choice - 1] == arr[0][1] && arr[0][choice - 1] == arr[0][abs(3 - choice)])//横情况{//第一排横情况必过一排中间点,即arr[0][1],再使用abs(),实现使输1得2,输3得0return 1;}else if (arr[0][choice - 1] == arr[1][choice - 1] && arr[0][choice - 1] == arr[2][choice - 1])//竖情况{//竖情况列固定,只需要更改行return 1;}else//如果都不符合{return 0;//玩家未获胜}}else if (choice - 1 == 1)//落子位于第一行中心{if (arr[0][choice - 1] == arr[0][0] && arr[0][choice - 1] == arr[0][2])//横情况{//需要检查是否相等的位置固定为左上点arr[0][0],右上点arr[0][2]return 1;}else if (arr[0][choice - 1] == arr[1][1] && arr[0][choice - 1] == arr[2][1])//竖情况{//竖情况列固定,只需要更改行return 1;}else//如果都不符合{return 0;//玩家未获胜}}}else if (choice <= 6 && choice > 3)//落子于第二行{a = arr[1][choice - 4];//在我们的棋盘上,第二行位置为:4,5,6,所以需要-4,以寻找落子位置if (choice - 4 == 1)//落子位于第二行中心{if (arr[0][0] == arr[1][choice - 4] && arr[2][2] == arr[1][choice - 4])//右斜情况‘\’{//右斜情况需检查的位置固定,为左上arr[0][0],右下arr[2][2]return 1;}else if (arr[0][2] == arr[1][choice - 4] && arr[2][0] == arr[1][choice - 4])//左斜情况‘/’{//左斜情况需检查的位置固定,为右上arr[0][2],左下arr[2][0]return 1;}else if (arr[1][choice - 4] == arr[1][0] && arr[1][choice - 4] == arr[1][2])//横情况{//横情况需检查的位置固定,为中左arr[1][0],中右arr[1][2]return 1;}else if (arr[1][choice - 4] == arr[0][1] && arr[1][choice - 4] == arr[2][1])//竖情况{//竖情况需检查的位置固定,为中上arr[0][1],中下arr[2][1]return 1;}else//如果都不符合{return 0;//玩家未获胜}}else if (choice - 4 != 1)//如果落子于边缘两点(中左或中右){if (arr[1][choice - 4] == arr[1][1] && arr[1][choice - 4] == arr[1][6 - choice])//横情况{//横情况必过第二行中心点,即arr[1][1],6 - choice实现输4得2,输6得0return 1;}else if (arr[1][choice - 4] == arr[0][choice - 4] && arr[1][choice - 4] == arr[2][choice - 4])//竖情况{//竖情况列确定,行改变return 1;}else//没有斜情况{return 0;//玩家未获胜}}}else if (choice > 6)//位于第三行{a = arr[2][choice - 7];//在我们的棋盘上,第三行位置为:7,8,9,所以需要-7,以寻找落子位置if (choice - 7 == 0 || choice - 7 == 2)//如果落子于边缘两点(左下或右下){if (arr[2][choice - 7] == arr[1][1] && arr[2][choice - 7] == arr[0][9 - choice])//斜情况{//无论左上还是右上,斜情况必过中心点,即arr[1][1],9 - choice实现输7得2,输9得0return 1;}else if (arr[2][choice - 7] == arr[2][1] && arr[2][choice - 7] == arr[2][9 - choice])//横情况{//横情况必过中心点,即arr[1][1],9 - choice实现输7得2,输9得0return 1;}else if (arr[2][choice - 7] == arr[1][choice - 7] && arr[2][choice - 7] == arr[0][choice - 7])//竖情况{//竖情况列确定,行改变return 1;}else//如果都不符合{return 0;//玩家未获胜}}else if (choice - 7 == 1)//落子位于第三行中心{if (arr[2][choice - 7] == arr[2][0] && arr[2][choice - 7] == arr[2][2])//横情况{//横情况需要检查的点固定为左下arr[2][0]和右下arr[2][2]return 1;}else if (arr[2][choice - 7] == arr[1][choice - 7] && arr[2][choice - 7] == arr[0][choice - 7])//竖情况{//竖情况列确定,行改变return 1;}else//如果都不符合{return 0;//玩家未获胜}}}
}int finish(char arr[3][3])//和棋判断
{int i = 0;int j = 0;for (i = 0; i < 3; i++){for (j = 0; j < 3; j++){if (arr[i][j] != '*'&&arr[i][j] != '#'){return 0;}if (i == 2 && j == 2){if (arr[i][j] == '*' || arr[i][j] == '#'){printf("和棋!\n\n");return 1;}}}}
}

总结

编写三子棋游戏的难度不高,主要是要有完整的逻辑,该代码仍然有很多可以优化的地方,但是笔者认为这种写法是能比较容易地将代码和人的语言逻辑结合起来的,如有代码错误,欢迎大家批评指正。

C语言三子棋(九宫棋)游戏相关推荐

  1. 三子棋(九宫棋)游戏的实现(详细片)

    目录 1.前言 2.游戏准备 3.实现游戏的步骤 (1)生成菜单界面 (2)游戏的实现逻辑 1.棋盘的初始化 2.生成九宫格 3.玩家下棋 4.电脑下棋 5.判断输赢 (3)额外补充(实现游戏先手或者 ...

  2. C语言-三子棋游戏的实现

    C语言-三子棋游戏的实现 目录 C语言-三子棋游戏的实现 游戏背景介绍 游戏实现思路 test模块 menu模块 **game模块** init_board(初始化棋盘) print_board(打印 ...

  3. Tic_Tac_Toe(三子棋)小游戏——C语言实现

    1 需求分析 三子棋是一种民间传统游戏,又叫九宫棋.圈圈叉叉.一条龙.井字棋等.游戏规则:双方轮流落子,率先将三个棋子在横.竖.对角落成一条直线的一方胜. 该项目旨在使用C语言实现简单的人机对战,主要 ...

  4. C语言—三子棋小游戏解析

    一.问题描述 三子棋是一种民间传统游戏,又叫九宫棋.圈圈叉叉.一条龙.井字棋.田字棋.对角棋等.将正方形对角线连起来,相对两边依次摆上三个双方棋子,只要将自己的三个棋子走成一条线,对方就算输了.但是, ...

  5. 萌新的九宫棋(C语言)

    萌新的九宫棋 文章目录 萌新的九宫棋 一.概述 1.实现功能 2.介绍 3.编译器 4.致谢 二.设计思路 三.程序实现 (一).函数设计 (二).部分具体实现 1.main()函数的实现 2.pcM ...

  6. 程序员成长之旅——C语言三子棋

    程序员成长之旅--C语言三子棋 简易介绍三子棋 三子棋编程过程 三子棋代码总览 game.h game.c test.c 简易介绍三子棋 进行了这么多天的c语言学习,今天给大家讲一下三子棋是如何用c语 ...

  7. C语言三子棋,五子棋,n子棋的代码实现

    C语言三子棋,五子棋,n子棋的代码实现 这里以五子棋为例,来说明开发过程 开发思路 菜单打印 棋盘的打印 棋子的打印 电脑下棋(随机数) 判断输赢 代码整合 注意事项 这里以五子棋为例,来说明开发过程 ...

  8. 简单c语言实现三子棋/多子棋

    简单c语言实现三子棋/多子棋主要是想实现以下几个功能 (先做再循环)do while 一.目录: 1.play 0.exit 二.选择:(Switch)选择 三.进行游戏: 1.储存数据 - 二维数组 ...

  9. c语言井字棋程序框图,C语言实现井字棋(三子棋)

    本文实例为大家分享了C语言实现井字棋的具体代码,供大家参考,具体内容如下 一.实现思路 1.初始化数组 三子棋是九宫格的格式,所以用二维数组接收数据.用'O"代表电脑下的子,'X" ...

  10. [Python] 黑白棋(翻转棋)小游戏

    [Python] 黑白棋(翻转棋)小游戏 游戏介绍 黑白棋(Reversi or Othello)在西方和日本很流行.游戏通过相互翻转对方的棋子,最后以棋盘上谁的棋子多来判断胜负. 规则 黑白棋的每颗 ...

最新文章

  1. Entity Framework:Code-First Tutorial开篇
  2. 【Linux入门到精通系列讲解】Centos 7软件安装的三种方式
  3. 分布式系统——zabbix 用 onealert实现报警、agent主动模式、proxy代理
  4. K8s 应用管理之道 - 有状态服务
  5. <学习日记>计算机网络第一章预习记录
  6. qt 设计师缩放_重新设计缩放体验
  7. thinking-in-java(21)并发2
  8. Excel VBA 词根管理工具
  9. 信息学奥赛一本通 1848:【07NOIP提高组】字符串的展开 | OpenJudge NOI 1.7 35:字符串的展开 | 洛谷 P1098 [NOIP2007 提高组] 字符串的展开
  10. springBoot shiro
  11. HCI实验图常见类型
  12. 正充电手机自动订了总统套房!公安介入调查:排除被植入后门或被控制可能...
  13. 2021-2027全球与中国弹簧加载探针市场现状及未来发展趋势
  14. 2.1 Hadoop环境搭建
  15. sketchup 2018下载与安装教程
  16. talentq测试题库rb_talentq测试题目拐
  17. 1.4.3 ASBR-Summary-LSA
  18. php教程--案例4(判断闰年)
  19. Java身份证处理工具
  20. Mac的自带软件grapher

热门文章

  1. 男子杀害女友幼子 两年后被判死缓
  2. c语言程序设计实验教程清华大学,清华大学出版社-图书详情-《C程序设计实验教程》...
  3. 详解Linux系统Vi 和 Vim中正常模式、编辑模式、命令模式相互转化,以及vim命令使用
  4. python如何画出多个独立的图片_如何使用python语言中的可视化工具绘制多个图
  5. 关闭 TSVNCache.exe 进程
  6. html css animate,animate.css
  7. 使用U盘安装统信UOS20服务器操作系统1050a出现“设置基础软件仓库时出错”报错导致无法继续安装的解决方法
  8. 简单了解Unity Terrain
  9. HttpClient示例及资源释放
  10. 头像动漫化——微信小程序+Flask后端调用AnimeGanV2