目录

1.游戏规则

2.设计思路

1.棋盘的初始化

2.打印棋盘

3.玩家操作

4.电脑下棋

6.输赢判断

7.完整代码展示


1.游戏规则

井字棋又叫三子棋,作为童年经典小游戏,相信各位无论是在上课摸鱼亦或者打磨时间的时候一定与小伙伴来过这么几局游戏。游戏规则很简单,玩家只需要在3*3格子棋盘上进行连珠,双方轮流依次下棋,率先在棋盘上连成三子者获胜。

2.设计思路


  1.主体思路

作为玩家,我们面对一个游戏首先进入眼帘的是菜单部分,然后根据个人意愿再选择进行游戏或者退出游戏,因此我们可以轻易创建出test.c项目文件并写出以下代码

void menu()
{printf("***********************************\n");printf("***********  1.游戏开始  **********\n");printf("***********  0.退出游戏  **********\n");printf("***********************************\n");
}void text()
{int input = 0;do{menu();printf("请选择:");scanf("%d ", &input);switch (input){case 0:printf("退出游戏\n");break;case 1:printf("开始游戏\n");game();break;default :printf("选择错误,请重新输入\n");break;}} while (input);}int main()
{text();return 0;
}

到这里,游戏的框架就完成了一半了,随后我们就需要对game进行详细补充。

要设计game函数内的部分,我们就要先清楚游戏是如何进行的。首先是创建一个3*3的棋盘,在游戏开始前棋盘内为空格,随后展示出棋盘,紧接着玩家下棋,随后电脑下棋;并且在每一次下棋结束后判断输赢。有了这样一个思路,我们就可以轻松的写出

void game()
{char board[ROW][COL];char ret = 0;init_board(board, ROW, COL);//初始化棋盘print_board(board, ROW, COL);//打印棋盘while (1)//确保能够重复进行下棋{player_move(board, ROW, COL);//玩家操作print_board(board, ROW, COL);ret = is_win(board, ROW, COL);//判断输赢//    C-继续游戏 #-电脑获胜,玩家失败  *-玩家胜利 Q-平局if (ret != 'C'){break;}computer_move(board, ROW, COL);//电脑操作print_board(board, ROW, COL);ret = is_win(board, ROW, COL);if (ret != 'C'){break;}}if (ret == '#'){printf("很遗憾,您失败了\n");}else if (ret == '*'){printf("恭喜您获得胜利\n");}else if (ret == 'Q'){printf("平局\n");}
}

(对于board[ROW][COL]中棋盘的变量,为了方便后续更改变量大小,我们可以才用宏定义的方法来创建ROW与COL;当然对于本游戏也可直接写成board[3][3],这里是为了代码更工程化)

#define ROW 3
#define COL 3
//直接修改ROW/COL后的数字即可重新定义变量大小

由于在这里直接引用了我们自定义的函数,因此为了使项目整洁,可以再创建两个项目game.c和game.h前者用来实现自定义函数的内容,后者声明函数。这样我们就需要在test.c和game.c中包含game.h,即

#include "game.h"
//自己创建的头文件用“ ”
//game.h#define ROW 3
#define COL 3#include <stdio.h>void init_board(char board[ROW][COL], int row, int col);
void print_board(char board[ROW][COL], int row, int col);
void player_move(char board[ROW][COL], int row, int col);
void computer_move(char board[ROW][COL], int row, int col);
char is_win(char board[ROW][COL], int row, int col);

而在game.c中,我们就要一步一步实现各个函数内容了。

2.函数设计

前面我们说到函数内容我们要在game.c内完成设计,因此以下内容全部在game.c内进行。

1.棋盘的初始化

我们创建好3*3的二维数组后,在游戏开始前需要棋盘内全部为 ‘空格’ 。对此,我们只需要将棋盘内每一格的内容都设置成 ‘空格’ 即可

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] = ' ';}}
}

2.打印棋盘

我们希望一个棋盘是这样子的,为了美观我们需要适当加入边界线。而为了达到这个效果,我们可以将棋盘内容与边界线的两行看成一行来进行打印,这样就能写出

void print_board(char board[ROW][COL], int row, int col)
{int i = 0;for (i = 0; i < row; i++){printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);if (i < row - 1)//最后一行不打印{printf("---|---|---\n");}}
}

到这里棋盘打印的函数就创建好了,但是存在一个弊端

这一行代码中,我们默认只存在3列棋盘,而事实上我们棋盘的行列是由row和col确定的。而为了程序的严谨性,我们需要重新设计函数内容。

怎么办呢?显然,我们只需要依次打印出每一个格子的内容即可,从而产生了

void print_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++){printf(" %c ", board[i][j]);if (j < col - 1){printf("|");}}printf("\n");if (i < row - 1){for (j=0; j < col; j++){printf("---");if (j < col - 1){printf("|");}}}printf("\n");}
}

3.玩家操作

我们希望在这一个函数中实现玩家落子(‘ * ’),而对于玩家给出的落子位置,我们也需要对其进行判断合理性。同时,数组下标是从0开始的,因此对于玩家所下位置我们需要-1来得到合理的下标。

void player_move(char board[ROW][COL], int row, int col)
{printf("玩家请下棋\n");while (1){printf("请输入所下位置坐标: ");int x = 0;int y = 0;scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col)//判断坐标合法性{if (board[x - 1][y - 1] == ' ')//空位落子{board[x - 1][y - 1] = '*';break;}else{printf("该位置被占用,请重新选择坐标\n");}}else{printf("输入坐标不合理,请重新输入正确坐标\n");}}
}

4.电脑下棋

对于电脑下棋,思路和玩家下棋其实差不多,但是也存在差异。首先电脑可以识别从0开始的下标,因此我们也就不必要进行-1操作了;其次电脑落子位置随机,也就需要产生随机数,而说到随机数我们很容易想到time函数这样也就能写出

//game.h#include <stdlib.h>
#include <time.h>
//修改test.c的内容void text()
{srand((unsigned int)time(NULL));//time函数作为随机值的调用int input = 0;do{menu();printf("请选择:");scanf("%d ", &input);switch (input){case 0:printf("退出游戏\n");break;case 1:printf("开始游戏\n");game();break;default :printf("选择错误,请重新输入\n");break;}} while (input);}
//game.cvoid computer_move(char board[ROW][COL], int row, int col)
{printf("电脑下棋\n");while (1){int x = rand() % row;//将随机值的范围固定在0~3之间int y = rand() % col;if (board[x][y] == ' '){board[x][y] = '#';break;}}
}

6.输赢判断

为了让游戏能够完整,我们在最后加入判断游戏输赢的函数。这一步需要判断相邻的三个元素是否相同且不为空,这里就很简单了,不难写出

char is_win(char board[ROW][COL], int row, int col)
{int i = 0;for (i = 0; i < row; i++){if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' '){return board[i][0];//返回的#或者*在test.c的game函数中直接作为判断条件}}for (i = 0; i < col; i++){if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' '){return board[0][i];}}if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' '){return board[1][1];}if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' '){return board[1][1];}
}

到这里我们判断完了游戏的输赢,但是还存在平局的情况。而所谓平局也就是棋盘填满且没有三子相连的情况,这里我们可以创建函数is_full来判断,而这个函数我们只需要在game.c中实现就可以,因此不需要在game.h中进行声明。对于is_full我们可以写出

int is_full(char board[ROW][COL], int row, int col)
{int i = 0; int j = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++){if (board[i][j] == ' ')return 0;}}return 1;
}
//完整的判断函数char is_win(char board[ROW][COL], int row, int col)
{int i = 0;for (i = 0; i < row; i++){if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' '){return board[i][0];}}for (i = 0; i < col; i++){if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' '){return board[0][i];}}if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' '){return board[1][1];}if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' '){return board[1][1];}if (is_full(board, row, col) == 1){return 'Q';}return 'C';
}

7.完整代码展示

//test.c#include "game.h"void menu()
{printf("***********************************\n");printf("***********  1.游戏开始  **********\n");printf("***********  0.退出游戏  **********\n");printf("***********************************\n");
}void game()
{char board[ROW][COL];char ret = 0;init_board(board, ROW, COL);print_board(board, ROW, COL);while (1){player_move(board, ROW, COL);print_board(board, ROW, COL);ret = is_win(board, ROW, COL);if (ret != 'C'){break;}computer_move(board, ROW, COL);print_board(board, ROW, COL);ret = is_win(board, ROW, COL);if (ret != 'C'){break;}}if (ret == '#'){printf("很遗憾,您失败了\n");}else if (ret == '*'){printf("恭喜您获得胜利\n");}else if (ret == 'Q'){printf("平局\n");}
}void text()
{srand((unsigned int)time(NULL));int input = 0;do{menu();printf("请选择:");scanf("%d ", &input);switch (input){case 0:printf("退出游戏\n");break;case 1:printf("开始游戏\n");game();break;default :printf("选择错误,请重新输入\n");break;}} while (input);}int main()
{text();return 0;
}
//game.h#define ROW 3
#define COL 3#include <stdio.h>
#include <stdlib.h>
#include <time.h>void init_board(char board[ROW][COL], int row, int col);
void print_board(char board[ROW][COL], int row, int col);
void player_move(char board[ROW][COL], int row, int col);
void computer_move(char board[ROW][COL], int row, int col);
char is_win(char board[ROW][COL], int row, int col);
//game.c#include "game.h"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] = ' ';}}
}void print_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++){printf(" %c ", board[i][j]);if (j < col - 1){printf("|");}}printf("\n");if (i < row - 1){for (j=0; j < col; j++){printf("---");if (j < col - 1){printf("|");}}}printf("\n");}
}void player_move(char board[ROW][COL], int row, int col)
{printf("玩家请下棋\n");while (1){printf("请输入所下位置坐标: ");int x = 0;int y = 0;scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){if (board[x - 1][y - 1] == ' '){board[x - 1][y - 1] = '*';break;}else{printf("该位置被占用,请重新选择坐标\n");}}else{printf("输入坐标不合理,请重新输入正确坐标\n");}}
}void computer_move(char board[ROW][COL], int row, int col)
{printf("电脑下棋\n");while (1){int x = rand() % row;int y = rand() % col;if (board[x][y] == ' '){board[x][y] = '#';break;}}
}int is_full(char board[ROW][COL], int row, int col)
{int i = 0; int j = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++){if (board[i][j] == ' ')return 0;}}return 1;
}char is_win(char board[ROW][COL], int row, int col)
{int i = 0;for (i = 0; i < row; i++){if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' '){return board[i][0];}}for (i = 0; i < col; i++){if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' '){return board[0][i];}}if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' '){return board[1][1];}if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' '){return board[1][1];}if (is_full(board, row, col) == 1){return 'Q';}return 'C';
}

以上就是完整的井字棋游戏设计思路,相信大家看完之后稍加思考也能独立写出属于自己的“井字棋”。

最后祝各位小伙伴在今后的学习中能够不断进步,如果觉得文章有用的话别忘了点赞支持哦~

【C语言从入门到入土】——“井字棋”相关推荐

  1. python入门游戏之井字棋实例代码

    井字棋简介 井字棋又称三子棋,英文名为Tic Tac Toe.具体玩法为在一个3x3的棋盘上,一个玩家用X做棋子,另一个玩家用O做棋子,谁先在棋盘上的一行.一列或对角线上画满三个棋子,即可获胜,如果棋 ...

  2. C语言实现小游戏之井字棋

    目录 前言 一.井字棋游戏的主流程 二.游戏部分 1.游戏函数 2.初始化棋盘 3.打印棋盘 4.玩家下棋 5.电脑下棋(两个难度等级) 6.判断游戏是否结束 三. 源码展示 总结 前言 这是我在学习 ...

  3. C语言 VS2019编译器实现简易井字棋小游戏~

    文章目录 井字棋小游戏 游戏实现 一.创建新项目及游戏文件 二.引头文件,定义符号 三.主函数 打印菜单 四.开始游戏 1.创建二维数组 2.初始化棋盘 3.打印棋盘 4.玩家下棋 5.电脑下棋 6. ...

  4. python如何在前面加井_python入门之井字棋小游戏

    引言: 刚学python好几天了,从java到python,基础学起来确实比较容易,语法掌握,基本概念上都比较容易入脑. 唯一比较郁闷的是老想着用java的语法去学python代码,这点还需要后面慢慢 ...

  5. 井字棋小游戏c语言简单编码,C语言实现井字棋小游戏

    C语言实现简单的"井字棋游戏",供大家参考,具体内容如下 总体构造: 1.游戏菜单的逻辑实现 2.游戏本体的代码实现 part 1:游戏菜单的整体逻辑 ①简单的通过一个输入0和1的 ...

  6. 【C语言实现井字棋及电脑落子优化】

    朋友们,我们还记得以前上课经常和同桌玩起井字棋,那么我们就当我们回忆童年,现在也用C语言来实现井字棋,本次代码相对于初阶的井字棋,在电脑下棋代码部分做了优化,使得电脑更加具有威胁,但是由于博主水平有限 ...

  7. c语言井字棋程序设计报告,井字棋游戏(课程设计)总结报告.doc

    井字棋游戏(课程设计)总结报告 C语言贪吃蛇游戏设计总结报告 PAGE PAGE 5 丽水学院 计算机信息学院 <C语言课程设计(短一)> 指 导 书 二 ○ 一一 年 三 附件二 封面格 ...

  8. 用c语言编写的打字母游戏,用C语言编写小游戏——“井字棋”

    原标题:用C语言编写小游戏--"井字棋" 作者:Milo Yip 来源:知乎 原文链接:https://zhuanlan.zhihu.com/p/39581573 在 Milo Y ...

  9. C语言小游戏->井字棋

    井字棋想必大家都玩过,今天教大家一个用C语言写一个井字棋小游戏 这个游戏大致可以分为两个部分:游戏菜单和游戏过程. 首先就是创建一个menu()函数来写菜单页面 这里出现了不同指令对应的结果,即输入1 ...

最新文章

  1. step by step YAML 复用
  2. 什么是EEG以及如何解释EEG?
  3. 深入浅出之-route命令实战使用指南
  4. jsp 获取项目路径,java获取项目路径
  5. 自定义依赖注解无效_SpringValidation用注解代替代码参数校验解析
  6. 【计算机就业-后端开发工程师】校招想去互联网公司担任后端开发工程师该怎么准备
  7. idea安装配置tomcat
  8. 查询数据去除后面无用的0_OTM数据库清理超时无效连接--SQLNET.EXPIRE_TIME=10
  9. SHELL脚本也要函数化
  10. socket文件传输功能的实现
  11. 机动车车牌分类及命名规则总结
  12. 计算日期在当月是第几周-【自然周(每月第一个周一为该月第一周)做法以及1号为第一周做法】
  13. java验证用户名和密码_java验证用户名和密码详解
  14. 踩坑指南!anaconda新建环境出错解决!又是猛男落泪的一天!
  15. web前端开发教学视频,web前端开发职业
  16. 酒香也怕巷子深,教你一招,轻松让百度收录你的个人站点
  17. 猴子定律--如何跳出你深陷的棋局看趋势
  18. keil5软件安装开发环境搭建教程(mdk,c51通用)
  19. Windows Sockets 规范及应用
  20. IDEA怎么查看还有多久到期

热门文章

  1. 澳门风云剧情介绍 主演:周润发 谢霆锋 杜汶泽
  2. 常州一院有全消化道的机器人的_“奇奇”再立新功,常州一院胸外科团队跻身全国TOP榜单...
  3. 闪客工具:镜像服务的使用
  4. 解决访问swaggerUI接口文档显示basic-error-controler问题
  5. 分布式文件系统里的EC和RS编解码的效率问题
  6. Python-OpenCV 图像基本操作
  7. 关于NAT——网络地址转换
  8. ALU——调用加法乘法模块
  9. 图的m着色问题(子集树回溯法)
  10. python使用什么关键字来定义,使用( )关键字来创建python自定义函数。