三子棋(N子棋)小游戏超详解
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、三子棋的游戏规则?
- 二、三子棋的游戏设计的大概思路?
- 三、设计详细思路加代码
- 1.首先定义一个菜单menu函数
- 2.在test函数中调用menu函数
- 3.在main函数中在调用test函数
- 4.以上均在text.c中进行,然后我们需要在text.c文件中调用game函数,然后在game.c的源文件实现其功能,实现game函数的具体思路和代码如下
- 1.创造一个二维数组,用来打印棋盘
- 2.实现棋盘的初始化
- 3.将棋盘初始化后就是打印棋盘了
- 4.接下来就是玩家和电脑分别进行下棋了
- 5.最后是判断输赢了
- 四.总结
- 此外
前言
提示:这里可以添加本文要记录的大概内容:
三子棋写成的效果如下
写成N子棋 效果如下(其中拿五子棋做示范)
提示:以下是本篇文章正文内容,下面案例可供参考
一、三子棋的游戏规则?
游戏规则要求:电脑(随机)和玩家一次下一子,双方轮流交替下子,直到电脑和玩家任意一方获胜,或者棋盘满了,结束游戏。
获胜判定:只要电脑或者玩家任意一方的棋子有三子连在一起,可以为横连、纵连、斜连,则该方获胜,游戏结束。若棋盘满了,则判定为平局。
二、三子棋的游戏设计的大概思路?
实现程序的思路:首先我们需要定义游戏菜单和游戏规则。
游戏菜单:选择是否开始玩儿游戏,1:玩儿,0:退出游戏;
游戏规则:电脑先走,玩家后走,一方棋子有三子连在一起即为赢,否则棋盘满还未有一方赢判定为平局。
接下来就是开始玩儿游戏了(游戏过程):打印棋盘 → 电脑走一步 → 玩家走一步 → 判定输赢 or 平局 。(为了最后的显示效果,任意一方走一步就打印一次棋盘)。
棋盘初始化 → 打印棋盘 → 设定棋盘的行列数 → 打印盘的样式;
电脑走 → 设定电脑走的随机坐标(棋盘上有空位才能走);
玩家走 → 输入家走的坐标 → 有空位就打印出棋子(还需要考虑坐标被占用和输入坐标不合法两种情况);
判断输赢 → 棋盘上的横连、纵连、斜连有三子一样的即为该方赢 → 棋盘满了即为平局。
三、设计详细思路加代码
为了确保程序的独立性
我们创造两个源文件game.c和text.c,一个头文件game.h实现程序的模块化进行
其中game.c用来实现整个游戏的具体操作
text.c用来最终调用game.c来实现运行
这就需要创造一个头文件game.h来实现上述的调用
1.首先定义一个菜单menu函数
代码如下(示例):
//游戏菜单:选择是否开始玩儿游戏,1:玩儿,0:退出游戏;
void menu()
{printf("*************************\n");printf("******** 1.play ********\n");printf("******** 0.exit ********\n");printf("*************************\n");
}
2.在test函数中调用menu函数
使用函数调用的方式实现
void test()
{//srand((unsigned int)time(NULL));int input = 0;do{menu();printf("请选择:>");scanf("%d", &input);switch (input)//采用switch函数实现选择,选择1就进行game,选择0就退出,其他就重新选择{case 1:game();break;case 0:printf("退出游戏\n");break;default:printf("选择错误\n");break;}} while (input);
}
3.在main函数中在调用test函数
int main()
{test();return 0;
}
4.以上均在text.c中进行,然后我们需要在text.c文件中调用game函数,然后在game.c的源文件实现其功能,实现game函数的具体思路和代码如下
1.创造一个二维数组,用来打印棋盘
void game()
{char board[3][3];
}
为避免创造棋盘的维数受到限制,我们在头文件game.h中定义两个define定义的常变量ROW(行)和COL(列)(column)来表示打印棋盘的行和列
这样我们仅需要该其后面的数字就可以玩我们想玩的维数棋盘了
#define ROW 3
#define COL 3
然后将数组后的行列改为ROW,COL就可以在只改变头文件中ROW,COL后定义的数字控制需要打印的棋盘维数了
void game()
{char board[ROW][COL];
}
2.实现棋盘的初始化
将棋盘全部初始化为空格
在text.c中game函数中调用init_board(board, ROW, COL)函数,并传入行和列
并将其放在头文件game.h中定义
void game()
{char board[ROW][COL];//初始化一下棋盘为全空格init_board(board, ROW, COL);
}
在game.h中声明
//初始化棋盘
void init_board(char board[ROW][COL], int row, int col);
并在game.c中文件中实现
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] = ' ';}}
}
3.将棋盘初始化后就是打印棋盘了
因此在text.c中game函数中调用print_board(board, ROW, COL);函数并传入行和列
同样的头文件game.h中进行声明
在到game.c文件中进行实现
void game()
{char board[ROW][COL];//初始化一下棋盘为全空格init_board(board, ROW, COL);//打印棋盘print_board(board, ROW, COL);
}
在game.h中定义
//打印棋盘
void print_board(char board[ROW][COL], int row, int col)
并在game.c中文件中实现
//打印棋盘(只能打印三子棋)
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");}
}
这中打印方式是固定打印三子棋3x3的棋盘了,相当于把代码写死了,接下来的另一种代码只要在以上代码的基础上进行修改即可
N子棋棋盘打印
//打印棋盘(优化:可以打印任意维数棋盘)
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]);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){//printf("---|---|---\n");for (j = 0; j < col; j++){printf("---");if (j < col - 1)printf("|");}printf("\n");}}
4.接下来就是玩家和电脑分别进行下棋了
同样也是以上思路
在text.c文件中game函数中先调用且传入行和列
并在头文件game.h中声明
在game.c中实现
代码如下
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);//电脑下棋computer_move(board, ROW, COL);print_board(board, ROW, COL);}
}
在game.h中声明
//玩家下棋
void player_move(char board[ROW][COL], int row, int col);//电脑下棋
void computer_move(char board[ROW][COL], int row, int col);
并在game.c文件中实现
//玩家下棋
void player_move(char board[ROW][COL], int row, int col)
{printf("玩家下棋");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] == ' ')//由于玩家不会考虑到数组下标是从0开始,故要按玩家输入的坐标减一放入{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;}}
}
而电脑是用rand函数实现随机数需要test.c文件中的主函数main中使用srand((unsigned int)time(NULL));来实现随机数自由
int main()
{srand((unsigned int)time(NULL));test();return 0;
}
当然在使用库函数srand,rand,time时是也要在头文件game.h进行声明
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
5.最后是判断输赢了
我们规定:
判断输赢的代码要告诉我:电脑赢了?玩家赢了?玩家赢?游戏继续?
//电脑赢:#
//玩家赢:*
//平局:Q
//游戏继续:C
思路同样如上
我们先在text.c文件中game函数调用is_win(board, ROW, COL);来判断胜负,并传入行和列,其中is-win函数返回值用ret接收
同时在头文件game.h中声明
最后在game.c文件中实现
代码如下
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");
}
在头文件game.h中声明
//判断输赢
char is_win(char board[ROW][COL], int row, int col);
在到game.c文件中实现
//只能判断三子棋输赢
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';
同样的和上面打印棋盘时相似,该种判断方式只能判断三子棋的输赢,相当于把代码写死了
对其进行优化,使其能不受限制,在任意N子棋都能判断输赢
N子棋棋盘判断输赢
//判断输赢(优化版:可判断任意维数棋局的输赢)
char is_win(char board[ROW][COL], int row, int col)
{//行判断int i = 0;for (i = 0; i < row; i++){int j = 0;int count = 0;for (j = 0; j < col - 1; j++){if (board[i][j] == board[i][j + 1] && board[i][j] != ' '){count++;}if (count == col - 1)return board[i][j];}}//列判断for (i = 0; i < col; i++){int j = 0;int count = 0;for (j = 0; j < row - 1; j++){if (board[j][i] == board[j + 1][i] && board[j][i] != ' '){count++;}if (count == row - 1)return board[j][i];}}// '/'判断for (i = 0; i < row - 1; i++){if (board[i][row - 1 - i] == board[i + 1][row - 2 - i] && board[i][row - 1 - i] != ' '){if (row - 2 - i == 0)return board[i][row - 1 - i];}}// '\' 判断for (i = 0; i < row - 1; i++){if (board[i][i] == board[i + 1][i + 1] && board[i][i] != ' '){if (i == row - 2)return board[i][i];}}if (is_full(board, row, col) == 1){return 'Q';}return 'C';
}
当棋盘下满了,出现平局,此时就需要在is_win函数中调用is_ful函数来判断
假如全部满了返回1,没满返回0
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;
}
至此三子棋(N子棋)基本完成了
所以总的代码如下
text.c
#include "game.h"//打印菜单
void menu()
{printf("*************************\n");printf("******** 1.play ********\n");printf("******** 0.exit ********\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 test()
{int input = 0;do{menu();printf("请选择:>");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏\n");break;default:printf("选择错误\n");break;}} while (input);
}int main()
{srand((unsigned int)time(NULL));test();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++){printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);if(i<row-1)printf("---|---|---\n");}
}//代码优化
//打印棋盘(优化:可以打印任意维数棋盘)
//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]);
// 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)
// {// //printf("---|---|---\n");
// 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("玩家下棋");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';
}//代码优化
//判断输赢(优化版:可判断任意维数棋局的输赢)
//char is_win(char board[ROW][COL], int row, int col)
//{// //行判断
// int i = 0;
// for (i = 0; i < row; i++)
// {// int j = 0;
// int count = 0;
// for (j = 0; j < col - 1; j++)
// {// if (board[i][j] == board[i][j + 1] && board[i][j] != ' ')
// {// count++;
// }
// if (count == col - 1)
// return board[i][j];
// }
//
// }
// //列判断
// for (i = 0; i < col; i++)
// {// int j = 0;
// int count = 0;
// for (j = 0; j < row - 1; j++)
// {// if (board[j][i] == board[j + 1][i] && board[j][i] != ' ')
// {// count++;
// }
// if (count == row - 1)
// return board[j][i];
// }
// }
// // '/'判断
// for (i = 0; i < row - 1; i++)
// {// if (board[i][row - 1 - i] == board[i + 1][row - 2 - i] && board[i][row - 1 - i] != ' ')
// {// if (row - 2 - i == 0)
// return board[i][row - 1 - i];
// }
//
// }
// // '\' 判断
// for (i = 0; i < row - 1; i++)
// {// if (board[i][i] == board[i + 1][i + 1] && board[i][i] != ' ')
// {// if (i == row - 2)
// return board[i][i];
// }
// }
// if (is_full(board, row, col) == 1)
// {// return 'Q';
// }
// return 'C';
//}
四.总结
我的第一篇博客大功告成,花费的时间和精力总会获得回报
还是小有成就感呢!
继续努力!加油,奥里给!
有不对的请及时指正我!谢谢读者
此外
对于三子棋还可以继续完善
比如:让电脑智能下棋,学会堵棋
或者是电脑有套路化的下棋等等
时间精力充裕的话可以试着去想想此类代码
我们不急慢慢来
三子棋(N子棋)小游戏超详解相关推荐
- 【牛客刷题】上手用C语言写一个三子棋小游戏超详解哦(电脑优化)
作者:[南航科院小张 南航科院小张的博客 专栏:从c语言的入门到进阶 学习知识不只是要懂,还要会用:想要找到好的工作,这里给大家介绍一件可以斩获诸多大厂offer的利器–牛客网 点击免费注册和我一起开 ...
- python小游戏代码大全-20行python代码的入门级小游戏的详解
背景: 作为一个python小白,今天从菜鸟教程上看了一些python的教程,看到了python的一些语法,对比起来(有其他语言功底),感觉还是非常有趣,就随手添了一点内容,改了一个小例程,当着练练手 ...
- python小项目——2048小游戏(详解)
2048游戏 原版游戏地址 第一部分 导入所需要的库 第二部分 确认游戏键位设置,并和对应的操作关联 第三部分 获取用户输入的值,并直到有效键位 第四部分 对矩阵的应用,减少代码量 第五部分 创建棋盘 ...
- Python实现飞机大战小游戏,详解每一行代码【不收藏都对不起我】
一.模块 1. 利用 pip 安装 pygame 模块 Windows系统下的安装参考如下文章: https://blog.csdn.net/qq_38721302/article/details/8 ...
- python必备入门代码-20行python代码的入门级小游戏的详解
背景: 作为一个python小白,今天从菜鸟教程上看了一些python的教程,看到了python的一些语法,对比起来(有其他语言功底),感觉还是非常有趣,就随手添了一点内容,改了一个小例程,当着练练手 ...
- 10款Java小游戏(详解+源码)
开源Java小游戏 前言 下面就给大家介绍十几个开源的Java小游戏,供大家学习交流.资源都下载好共享到我的交流群了,需要的在群内自取853665602不收取任何资源费,毕竟开源才是我们的宗旨. [群 ...
- Unity 之 发布WebGL转微信小游戏过程详解
Unity 之 发布WebGL转微信小游戏 前言 一,准备工作 1.1 下载插件 1.2 下载Unity 1.3 安装微信开发者工具 1.4 创建小程序 二,开始转换 2.1 创建项目 2.2 Mac ...
- Python实现飞机大战小游戏,详解每一行代码!
一.模块 1. 利用 pip 安装 pygame 模块 Windows系统下的安装参考如下文章: https://blog.csdn.net/qq_38721302/article/details/8 ...
- C语言实现贪吃蛇小游戏(详解)
目录 一.程序实现的原理: 二.预备知识 1.控制台窗口 2.通过代码将光标移动到控制台指定位置 三. 程序框架 四.具体操作 1.定义相关头文件 2.定义函数结构以及相关属性 五.完成各代码块 1. ...
最新文章
- 【Java例题】4.3 3. 使用Gauss消元法求解n元一次方程组的根,
- Spring boot 启动后执行特定的操作
- php 删除 r n,PHP去除换行符'/r/n'回车换行与PHP_EOL变量的使用
- matlab教程点语言,编程语言 / Matlab教程_电脑教程学习网( 5 )
- 敏捷方法开发总结的点评记录
- 信号量内核对象 semaphore
- python中比较重要的几个函数_python几个重要的内置函数
- EXCEL保存“加载宏”
- 笔记本电脑如何查看wifi密码
- 11.2 注解的使用示例1 select insert update和delete操作
- 3dmax给模型添加渐变背景有哪些方法
- 适合开发人员看的鸿蒙OS介绍~
- 南卡和Snowkids电容笔哪款更值得入手?口碑最佳的国产电容笔
- 同步六进制加法计数电路(D触发器)
- 新仙剑奇侠传H5上线测试了
- lol登入服务器显示证书,登录LOL提示安全证书不可用怎么办
- python 福利_python 处理json
- MPCS-314 3A 光电耦合器 用于IGBT/MOSFET隔离栅极驱动 完美代替TLP5701
- jdbc不能识别别名_生命离开氧气就不能活了吗? 氢气告诉你,No~
- 结合opencv学习DIP
热门文章
- qq2007登陆协议分析
- 2022仿拼多多拼团PHP系统源码+可封装APP/多商家入驻
- wordnet java_Java中使用Wordnet
- Cocos Creator TypeScript 套牛游戏(可微信小游戏)
- Linux使用mutt发送邮件
- 利用PYHTON爬虫爬取恋家网房价
- java pipeline模式_NIO系列-4: 彻底搞明白Pipeline和Handler
- python爬取网上租房信息_用python爬取租房网站信息的代码
- 教你如何构建 Linux 内核
- java中写入文件_java中创建、写入文件的5种方式