首页 / C语言 / C语言之三字棋的实现及扩展
C语言之三字棋的实现及扩展
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了C语言之三字棋的实现及扩展,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含18609字,纯文字阅读大概需要27分钟。
内容图文
C语言之三字棋的实现及扩展
在我们学习完数组之后,我们完全可以利用数组相关知识来写一个微小型的游戏,比如说今天所说的——三子棋。
大纲:
文件组成
实现
完整代码展示
扩展
即:
一.文件组成:
在我们学习的过程中,我们要逐渐习惯多文件的书写方式,也就是模块化书写。
在本文中,笔者分为了三个文件来写,分别是:
1.game.h——实现游戏函数的声明
2.game.c——游戏函数的实现
3.test.c —— 测试及游戏函数的调用
二.实现
0.文件的初始化
在这里我们分别在我们所创建的 test.c 和 game.c 包含我们的头文件——game.h
1.菜单的实现
在菜单中,我们设置玩家可以选择的模式,play and quit
以及,菜单怎么样多次循环选择,菜单的容错处理。这里,我们利用 do-while 来实现。
#define _CRT_SECURE_NO_WARNINGS 1//加这一句话是因为笔者采用的是 VS 编译器,为了防止一些不必要的错误出现#include "game.h"void menu()//列出可供玩家选择的模式{ printf("**************************************************************\n"); printf("***************** 1.play ****************\n"); printf("***************** 0.exit ****************\n"); printf("**************************************************************\n"); }void play() { }int main() {int input;//在这里,我们利用玩家选择的模式来控制循环的终止do{ menu(); printf("请输入你的选择:"); scanf("%d", &input);switch (input) {case 1://play play();break;case 0://退出printf("欢迎下次再来!\n");break;default://当玩家输入了非法字符,让其重新选择printf("输入错误,请重新输入!\n"); } } while (input);//当input为0时,停止循环return 0; }
运行效果:
现在,我们的菜单已经做好了,接下来要做的就是来打印我们的棋盘。
2.棋盘的打印
这里我们把打印函数的声明放在 game.h 文件里,把实现放在game.c 文件中。
在写代码之前,我们先来想一想在棋盘打印中,我们能不能直接打印空格——这肯定是不能的,因为这样,我们在屏幕上什么都看不见 (≧?≦)?
game.c:
#define _CRT_SECURE_NO_WARNINGS 1#include"game.h"void InitBoard(char board[3][3], int row, int col)//棋盘初始化{int i = 0, j = 0;for (i = 0; i < row; i++) {for (j = 0; j < col; j++) { board[i][j] = ' '; } } }void DisplayBoard(char board[3][3], int row, int col)//棋盘打印函数{int i = 0, j = 0;for (i = 0; i < row; i++) {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 < 3; j++) { printf("---");//分割行if (j < col - 1) { printf("|"); } } } printf("\n"); } }
注:
为了避免文章赘余,test.c 以及 game.h不再表示
运行结果:
但是,我们这么写,会不会有问题?
值得注意的是,在这有人会把棋盘打印写成这个样子
void DisplayBoard(char board[3][3], int row, int col)//棋盘打印函数{for (int i = 0; i < 3; i++) { printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);if (i < 2) { printf("---|---|---\n");//分割行 } } }
这样,无非还是上面那个问题,代码写死,无法扩展
所以,我们在这利用宏来实现,棋盘的大小随我们的宏来改变
因此在这我们给出头文件的部分
#pragma once#include<stdio.h>#define ROW 3//利用宏来实现棋盘的大小#define COL 3void InitBoard(char board[ROW][COL], int row, int col);//棋盘初始化void DisplayBoard(char board[ROW][COL],int row, int col);//棋盘打印函数
3.棋盘下子
1.玩家下子
在这里我们一共要注意几点:
1.在下子之前,我们要判断玩家所要下的位置是否在棋盘内
2.检测玩家要下的位置是否已有了棋子
3.下子之后,检查棋盘的输赢状况 (这个我们后面再说)
void PlayerMove(char board[ROW][COL], int row, int col)//玩家下棋{int x, y; printf("玩家走:\n"); printf("请输入你所要落子的坐标:"); scanf("%d%d", &x, &y);if (board[x - 1][y - 1]!=' ')//坐标被占用 { printf("该坐标已被占用,请重新下子!\n"); }else if (!((x > 0 && x <= row) && (y > 0 && y <= col))) { printf("该坐标为非法坐标,请重新输入!\n");//坐标非法 }else{ board[x - 1][y - 1] = '*';//玩家落子,暂时用 * 来表示 } }
2.电脑下子
再这里我们暂不深究,使用随机函数来生成一个坐标来下子
void ComputerMove(char board[ROW][COL], int row, int col)//电脑下棋{int x, y; printf("电脑走:");while (1) { x = rand() % row; y = rand() % col; if (board[x][y] == ' ') { board[x][y] = '#';//这里我们用 # 来表示电脑下棋 break; } } }
4.胜负的判定
在这里,我们用一个函数的返回值来表示输赢的各个情况。
#-----电脑赢
*-----玩家赢
C-----继续下子
F-----和局
ISFULL( board[ROW][COL], row, i = , j = (i = ; i < row; i++ (j = ; j < col; j++ (board[i][j] == ISWIN( board[ROW][COL], row, i = , j = (i = ; i < row; i++ (j = ; j < col - ; j++ (board[i][j] == board[i][j + ] && board[i][j] == board[i][j + ] && board[i][j] != (board[i][j] == board[i + ][j + ] && board[i + ][j + ] == board[i][j] && board[i][j] != (board[col - - i][j] == board[col - - i][j + ] && board[col - - i][j + ] == board[col - - i][j] && board[col - - i][j] != board[col - - (i = ; i < row - ; i++ (j = ; j < col; j++ (board[i][j] == board[i + ][j] && board[i][j] == board[i + ][j] && board[i][j] !=
//判断是否满盘---放在最后是因为最后一步的判断
if (1 == ISFULL(board, row, col))
{
return 'F';
}
return 'C'; }
到这,我们的三子棋似乎已经编完了,先看一下运行结果:
在这个过程中,我们会发现电脑下的特别快(当然,这跟我们的懒惰有关……)所以我们在电脑下的步骤中加一个Sleep()函数来延长电脑所用时间
已即,我们可以下一次子就清一下屏,这样看起来比较舒服
所以
最后的代码部分:
#pragma once#include<stdio.h>#include<stdlib.h>#include<time.h>#include<Windows.h>#define ROW 3//利用宏来实现棋盘的大小#define COL 3void InitBoard(char board[ROW][COL], int row, int col);//棋盘初始化void DisplayBoard(char board[ROW][COL], int row, int col);//棋盘打印函数void PlayerMove(char board[ROW][COL], int row, int col);//玩家下棋void ComputerMove(char board[ROW][COL], int row, int col);//电脑下棋char ISWIN(char board[ROW][COL], int row, int col);//判断输赢int ISFULL(char board[ROW][COL], int row, int col);//判断棋盘是否已满
game.h
#define _CRT_SECURE_NO_WARNINGS 1#include"game.h"void InitBoard(char board[ROW][COL], int row, int col)//棋盘初始化{int i = 0, j = 0;for (i = 0; i < row; i++) {for (j = 0; j < col; j++) { board[i][j] = ' '; } } }//void DisplayBoard(char board[3][3], int row, int col)//棋盘打印函数//{// for (int i = 0; i < 3; i++)// {// printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);// if (i < 2)// {// printf("---|---|---\n");// } // }//}void DisplayBoard(char board[ROW][COL], int row, int col)//棋盘打印函数{int i = 0, j = 0;for (i = 0; i < row; i++) {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 < 3; j++) { printf("---");//分割行if (j < col - 1) { printf("|"); } } } printf("\n"); } }void PlayerMove(char board[ROW][COL], int row, int col)//玩家下棋{int x, y; printf("玩家走:\n");while (1) { printf("请输入你所要落子的坐标:"); scanf("%d%d", &x, &y);if (!((x > 0 && x <= row) && (y > 0 && y <= col))) { printf("该坐标为非法坐标,请重新输入!\n");//坐标非法 }else if (board[x - 1][y - 1] != ' ')//坐标被占用 { printf("该坐标已被占用,请重新下子!\n"); }else{ board[x - 1][y - 1] = '*';//玩家落子,暂时用 * 来表示break; } } system("cls"); }void ComputerMove(char board[ROW][COL], int row, int col)//电脑下棋{int x, y; printf("电脑走:\n"); Sleep(1000);while (1) { x = rand() % row; y = rand() % col; if (board[x][y] == ' ') { board[x][y] = '#';//这里我们用 # 来表示电脑下棋 break; } } system("cls"); }int ISFULL(char board[ROW][COL], int row, int col) {int i = 0, j = 0;for (i = 0; i < row; i++) {for (j = 0; j < col; j++) {if (board[i][j] == ' ')return 0; } }return 1; }char ISWIN(char board[ROW][COL], int row, int col) {int i = 0, j = 0;for (i = 0; i < row; i++) {for (j = 0; j < col - 2; j++) {//判断横行if (board[i][j] == board[i][j + 1] && board[i][j] == board[i][j + 2] && board[i][j] != ' ')return board[i][j];//判断主对角线else if (board[i][j] == board[i + 1][j + 1] && board[i + 2][j + 2] == board[i][j] && board[i][j] != ' ')return board[i][j];//判断副对角线else if (board[col - 1 - i][j] == board[col - 2 - i][j + 1] && board[col - 3 - i][j + 2] == board[col - 1 - i][j] && board[col - 1 - i][j] != ' ')return board[col - 1 - i][j]; } }for (i = 0; i < row - 2; i++) {for (j = 0; j < col; j++) {//判断竖行if (board[i][j] == board[i + 1][j] && board[i][j] == board[i + 2][j] && board[i][j] != ' ')return board[i][j]; } }//判断是否满盘---放在最后是因为最后一步的判断if (1 == ISFULL(board, row, col)) {return 'F'; }return 'C'; }
game.c
#define _CRT_SECURE_NO_WARNINGS 1//加这一句话是因为笔者采用的是 VS 编译器,为了防止一些不必要的错误出现#include "game.h"void menu()//列出可供玩家选择的模式{ printf("**************************************************************\n"); printf("***************** 1.play ****************\n"); printf("***************** 0.exit ****************\n"); printf("**************************************************************\n"); }void play() {int ret;char board[ROW][COL] = { 0 }; InitBoard(board, ROW, COL); DisplayBoard(board, ROW, COL);while (1) { PlayerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = ISWIN(board, ROW, COL); {if (ret != 'C')break; } ComputerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = ISWIN(board, ROW, COL); {if (ret != 'C')break; } }switch (ret) {case 'F': printf("和局!\n"); system("pause"); system("cls");break;case '#': printf("电脑赢!\n"); system("pause"); system("cls");break;case '*': printf("玩家赢!\n"); system("pause"); system("cls");break;default:break; } }int main() { srand((unsigned)time(NULL));//随机种子的初始化int input;//在这里,我们利用玩家选择的模式来控制循环的终止do{ menu(); printf("请输入你的选择:"); scanf("%d", &input);switch (input) {case 1://playsystem("cls"); play();break;case 0://退出printf("欢迎下次再来!\n");break;default://当玩家输入了非法字符,让其重新选择system("cls"); printf("输入错误,请重新输入!\n"); } } while (input);//当input为0时,停止循环return 0; }
test.c
三.扩展
1.五子棋的实现
五子棋的实现仅仅只改变了判断规则,其它方式都没变。
判断代码:
char ISWIN(char board[ROW][COL], int row, int col) {int i = 0, j = 0; for (i = 0; i < col; i++) {for (j = 0; j < col - 4; j++) {//判断横行if (board[i][j] == board[i][j + 1] && board[i][j] == board[i][j + 2] && board[i][j] == board[i][j + 3] && board[i][j] == board[i][j + 4] && board[i][j] != ' ')return board[i][j];//判断对角线else if (board[i][j] == board[i + 1][j + 1] && board[i + 2][j + 2] == board[i][j] && board[i][j] == board[i + 3][j + 3] && board[i][j] == board[i + 4][j + 4] && board[i][j] != ' ')return board[i][j];else if (board[col - 1 - i][j] == board[col - 2 - i][j + 1] && board[col - 3 - i][j + 2] == board[col - 1 - i][j] && board[col - 4 - i][j + 3] == board[col - 2 - i][j + 1] && board[col - 5 - i][j + 4] == board[col - 2 - i][j + 1] && board[col - 1 - i][j] != ' ')return board[col - 1 - i][j]; } }for (i = 0; i < col - 4; i++) {for (j = 0; j < col ; j++) {//判断竖行if (board[i][j] == board[i + 1][j] && board[i][j] == board[i + 2][j] && board[i][j] == board[i + 3][j] && board[i][j] == board[i + 4][j] && board[i][j] != ' ')return board[i][j]; } }//判断是否满盘if (1 == ISFULL(board, row, col)) {return 'f'; } return 'c'; }
2.玩家对战玩家
只需将电脑下子的部分,替换成玩家下子即可
完整五子棋-人人对战代码:
#pragma once#include <stdio.h>#include<stdlib.h>#include<time.h>#include<Windows.h>#define ROW 10#define COL 10//初始化棋盘 void InitBoard(char board[ROW][COL], int row, int col);//打印棋盘void DisplayBoard(char board[ROW][COL], int row, int col);//玩家走void Player1Move(char board[ROW][COL],int row, int col);//玩家2走void Player2Move(char board[ROW][COL], int row, int col);//电脑走void ComputerMove(char board[ROW][COL], int row, int col);//判断输赢char ISWIN(char board[ROW][COL], int row, int col); //判断棋盘是否已满int ISFULL(char board[ROW][COL], int row, int col);
game.h
#define _CRT_SECURE_NO_WARNINGS 1#include "game.h"void InitBoard(char board[ROW][COL], int row, int col) {int i = 0, j = 0;for (i = 0; i < row; i++) {for (j = 0; j < col; j++) { board[i][j] = ' '; } } }void DisplayBoard(char board[ROW][COL], int row, int col) {int i = 0, j = 0;for (i = 0; i < col; i++) printf(" %d", i + 1); printf("\n");for (i = 0; i < row; i++) { printf("%2d", i + 1);for (j = 0; j < col; j++) { printf(" %c ",board[i][j]);if (j < col - 1) printf("|"); } printf("\n");//打印分割行if (i < row - 1) { printf(" ");for (j = 0; j < col; j++) { printf("---");if (j < col - 1) printf("|"); } printf("\n"); } } }void Player1Move(char board[ROW][COL], int row, int col) {int i = 0, j = 0;while (1) { printf("请输入玩家1要下的棋的坐标:"); scanf("%d%d", &i, &j);//检查是否越界if (1 <= i && i <= row && j >= 1 && j <= col) {if (board[i-1][j-1] != ' ') printf("此坐标已被占用!\n");else{ board[i-1][j-1] = '*';break; } }elseprintf("坐标非法访问!\n"); } system("cls"); }void Player2Move(char board[ROW][COL], int row, int col) {int i = 0, j = 0;while (1) { printf("请输入玩家2要下的棋的坐标:"); scanf("%d%d", &i, &j);//检查是否越界if (1 <= i && i <= row && j >= 1 && j <= col) {if (board[i - 1][j - 1] != ' ') printf("此坐标已被占用!\n");else{ board[i - 1][j - 1] = '#';break; } }elseprintf("坐标非法访问!\n"); } system("cls"); }//void ComputerMove(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;// }// }// Sleep(1000);// system("cls");//}int ISFULL(char board[ROW][COL], int row, int col) {int i = 0, j = 0;for (i = 0; i < row; i++) {for (j = 0; j < col; j++) {if (board[i][j] == ' ')return 0; } }return 1; }char ISWIN(char board[ROW][COL], int row, int col) {int i = 0, j = 0; for (i = 0; i < col; i++) {for (j = 0; j < col - 4; j++) {//判断横行if (board[i][j] == board[i][j + 1] && board[i][j] == board[i][j + 2] && board[i][j] == board[i][j + 3] && board[i][j] == board[i][j + 4] && board[i][j] != ' ')return board[i][j];//判断对角线else if (board[i][j] == board[i + 1][j + 1] && board[i + 2][j + 2] == board[i][j] && board[i][j] == board[i + 3][j + 3] && board[i][j] == board[i + 4][j + 4] && board[i][j] != ' ')return board[i][j];else if (board[col - 1 - i][j] == board[col - 2 - i][j + 1] && board[col - 3 - i][j + 2] == board[col - 1 - i][j] && board[col - 4 - i][j + 3] == board[col - 2 - i][j + 1] && board[col - 5 - i][j + 4] == board[col - 2 - i][j + 1] && board[col - 1 - i][j] != ' ')return board[col - 1 - i][j]; } }for (i = 0; i < col - 4; i++) {for (j = 0; j < col ; j++) {//判断竖行if (board[i][j] == board[i + 1][j] && board[i][j] == board[i + 2][j] && board[i][j] == board[i + 3][j] && board[i][j] == board[i + 4][j] && board[i][j] != ' ')return board[i][j]; } }//判断是否满盘if (1 == ISFULL(board, row, col)) {return 'f'; } return 'c'; }
game.c
#define _CRT_SECURE_NO_WARNINGS 1#include"game.h"void menu() { printf("*********************************************\n"); printf("******* 1.play *********\n"); printf("******* 0.quit *********\n"); printf("*********************************************\n"); }int choice() {int input = 0; printf("请输入你的选择:"); scanf("%d", &input);return input; }void game() {char ret;char board[ROW][COL] = { 0 }; InitBoard(board, ROW, COL); DisplayBoard(board, ROW, COL);while (1) { Player1Move(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = ISWIN(board, ROW, COL); {if (ret != 'c')break; } Player2Move(board, ROW, COL); DisplayBoard(board, ROW, COL); ret = ISWIN(board, ROW, COL); {if (ret != 'c')break; } }switch (ret) {case 'f': printf("和局!\n");break;case '#'://printf("电脑赢!\n");printf("玩家2赢!\n");break;case '*': printf("玩家1赢!\n");break;default:break; } }void play() {int input;do { menu(); input = choice(); system("cls");switch (input) {case 1: game();break;case 0: printf("谢谢使用,欢迎下次再来!\n");break;default: system("cls"); printf("输入错误,请重新输入!\n");break; } } while (input); }int main() { play();return 0; }
test.c
3.电脑下棋的探究
对此我们的算法肯定是需要极大的改进的
建议:
1.不在用随机函数代替机器大脑
2.电脑根据情况堵截(但是这样的话,最终的情况多是平局)
所以:
在这,我们还仍需更多的努力!
4.将game.c转为lib文件
然后出现:
此时我们会看到在我们的项目文件夹下的Debug文件夹下产生了:
接着,我们就可删除我们项目中的game.c了
然后再test.c中加入这样的一句话:
此时我们再点击运行,发现与之前并无不同!
5.打包为可安装文件
因为在VS2019中,微软似乎删除了这个组件,所以我们先需要去官网下载安装一下 : 点这
直接安装就行,尽管它是英文版,但是我们任可使用(学好英语的重要性!!!)
安装好之后,
下面是具体步骤:
之后我们就可以把我们所编写的游戏分享给我们的小伙伴,让其安装畅玩
关于三子棋的讲解便到此为止。
因笔者水平有限,若有错误之处,还望多多指正。
发表于 2021-03-09 14:21 guguguhuha 阅读(206) 评论(0) 编辑 收藏
内容总结
以上是互联网集市为您收集整理的C语言之三字棋的实现及扩展全部内容,希望文章能够帮你解决C语言之三字棋的实现及扩展所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。