人与人之间的单机五子棋 —— C语言实现
人与人之间的单机五子棋
每博一文案
作家苏曾说,到了现在这个年纪,谁都不想再取悦了,跟谁在一起舒服就和
谁在一起,包括朋友也是,累了,就躲远一点。人活着总是离不开圈子二字。
为了扩大自己的社交圈,参见各种活动,每天觥筹交错,忙得不亦乐乎?
可是,当我们心情低落的时候,把通讯录翻了个遍,也没找到一个能倾诉的人。
当我们遇到麻烦,想要求助,那些所谓的朋友,愿意帮忙的寥寥无几,以前
总觉得圈子越大越好,朋友越多越好。后来,慢慢发现,真正的朋友,再好,不再多。
越简单的人,越难交心,越简单的关系,越难长久。_________ 一禅心灵庙语
文章目录
- 人与人之间的单机五子棋
- 每博一文案
- 五子棋
- 创建项目的注意事项
- 五子棋实现原理解剖
- 功能上简单细节构思
- 定义相关的变量
- 进入游戏的选择
- 打印菜单的功能的实现
- 游戏函数 Game( ) 的构建
- 打印棋盘showBoard() 函数
- 下棋playerMove( )函数
- 判断胜负isOver( )函数
- 计算坐标周围连续的个数chessCount( )函数
- 五子棋完整代码实现
- game.h
- game.c
- test.c
- 最后:
五子棋
五子棋起源于中国,是全国智力运动会竞技项目之一,是一种两人对弈的纯策略型棋类游戏。双方分别使用黑白两色的棋子,下在棋盘直线与横线的交叉点上,先形成五子连珠者获胜。
五子棋容易上手,老少皆宜,而且趣味横生,引人入胜。它不仅能增强思维能力,提高智力,而且富含哲理,有助于修身养性。
而我们做成后的样子是如下: 显示
创建项目的注意事项
- 首先我们要明白一点就是不存在没有完完全全BUG的项目,就像人无完人一样 我们只能不断地对项目进行优化,减少BUG 的出现,但是我们好像并不能完全的消除所有的BUG
- 而消除bug 的最好的方式就是运行测试+调试
- 而我们在运行测试+调试 的时候,需要我们控制一定的量 ,我们需要把握住这个量 ,这一点是十分重要的,这样有助于我们快速的发现问题,也就是bug 的所在,从而提高我们的效率,减少我们的bug 的出现
- 具体的方法,我个人有以下建议:
- 首先我们需要对项目进行合理的分类,那个类,那个文件实现什么样的功能: 比如:一个类是用于定义什么类型,方法的 ,另一个类是用于什么头main 的,再另外一个类是用于对于什么功能上的实现的 ,合理的分类,可以提高我们项目的可读性,让我们自身不会因为自己随着代码量的增加,对应功能上的增加而导致我们越敲越乱,越写越蒙
- 对于量上我们可以,每实现了两三个 功能就运行测试看看,是否存在错误,如果存在出现了错误,我们可以在一定的量(范围内),快速的找出哪里出现了问题,从而对它进行调试 ,解决问题,而不是,把项目整体写完了或者是已经实现了好几十个功能,才开始运行测试项目,结果一运行,bug,警告 冒出一大坨,我们先不说,让不让人,抓头发,就是找出问题,恐怕都需要不时间上的浪费吧
- 对于代码上的注释,没事多写明白一点,或许有一天,你会感想曾经,那个写了注释的自己或同事
- 对于bug 不要害怕,一点一点的调试看看,找出问题的所在,慢慢来,要有耐心,要明白一点现在bug 写的多,以后bug 跟你说拜拜,现在bug ,不解决,bug 天天对你说 明天见
五子棋实现原理解剖
我们使用分布式文件系统,编写该项目
我们这款五子棋游戏是,单机,人与人之间的对战的。角色分为用户1,用户2两位
- 游戏菜单显示,两种情况,是开始游戏,还是退出游戏
- 我们定义二维数组 用于五子棋的显示和存放五子棋的信息。显示情况如下:
- 没有被下过的位置,符号 . 表示
- 被用户1下过的位置,符号 ● 表示
- 被用户2下过的位置,符号 ○ 表示
- 下棋方式是,通过输入坐标的形式,下棋
- 棋盘结果有四种情况分别是:
- 棋盘未满,未分胜负,继续下棋
- 棋盘未满,分胜负,用户1 赢了
- 棋盘未满,分胜负,用户2 赢了
- 棋盘已满,未分胜负,平局
功能上简单细节构思
显示打印数组中以 1 开始,显示行号,以及列号
下棋中,所下坐标位置,不可超出棋盘大小,不可下在已经被下过的位置,去重,每下一步,都需要打印棋盘
每下一步棋,都需要判断,下的这一步是否,分出胜负,而不是下了好几步,才判断结果,
定义相关的变量
这里我们的棋盘的行列,用户1, 用户2,以及棋盘的结果的标识 使用宏 定义,方便修改,以及后期的维护
#define ROW 15 // 棋盘行数
#define COL 15 // 棋盘列数#define PLAYER1 1 // 定义标识用户 1,
#define PLAYER2 2 // 定义标识用户 2// 棋局中的中情况的定义
#define NEXT 0 // 表示没有结果,继续下棋
#define DRAE 3 // 表示棋盘下满了,平局结束
进入游戏的选择
我们把游戏的功能封装写在一个方法中Game() 用于 main 函数调用使用, 使用循环,根据实际情况,我们玩完了一把游戏,可能还会再来一把,所以我们使用循环——> 在循环里头——>再使用分支条件 switch 选择对应的功能, 在循环中定义一个数值,作为循环条件,方便我们更新循环条件,从而达到跳出循环,退出游戏的操作
int main()
{int quit = 0; // 定义一个标识,用于循环条件的退出int select = 0; // 对应功能上的选择while (!quit){menc();printf("请输入你的选择: > ");scanf("%d", &select); // 选择游戏模式switch (select){case 1:Game(); // 进去游戏break;case 0:quit = 1; // 通过改变循环条件,跳出循环,结束游戏printf("ByeBye!ln\n");break;default: // 选择错误重新选择printf("Enter Error , Try Again!!! \n");break;}}return 0;
}
打印菜单的功能的实现
void menc() // 游戏菜单
{printf("#########################\n");printf("### 1.paly 0.Exot ###\n");printf("##### Please Select #####\n");printf("#########################\n");}
游戏函数 Game( ) 的构建
- 首先我们需要创建一个二维数组作为棋盘使用,并使用函数 memset 初始化二维数组(棋盘),同时定义一个变量,用于保存棋盘是否继续,如int result = NEXT ,其中的NEXT就是我们定义的标记:未分胜负,棋盘继续的标识
- 游戏是只有在分出胜负,才会结束,所以需要让游戏不要中途停止,所以写成循环的方式,进行游戏。
- 定义一个函数用于打印棋盘,如:showBoard(board, ROW, COL) 用于打印棋盘,每下一步都需要打印棋盘,传的参数为(数组,数组的行,数组的列)
- 接着定义一个下棋的函数用于下棋,如:playerMove(board, ROW, COL, PLAYER1) ,传的参数是(数组,数组的列,数组的行,谁下的(用户标识符号))
- 定义一个判断每下一棋,判断是否出胜负的函数如:result = isOver(board, ROW, COL),并返回结果(用户1赢,用户2赢,平局,继续),根据返回结果,如果返回值,不是继续,说明分出结果了,跳出循环,结束游戏,
- 退出循环后,再根据返回判断胜负的返回值,判断是谁赢了,还是平局,使用switch(result) 分支语句
逻辑思路
打印棋盘(showBoard( ))——> 用户1下棋(playerMove( ))——>判断胜负结果( isOver( )),(结果上未分胜负)——>打印棋盘(showBoard( ))——>用户2下棋(playerMove( ))——> 判断胜负结果( isOver( )),(结果上未分胜负)——>打印棋盘(showBoard( ))——> 再用户1下棋(playerMove( )),一直这样循环直到分出胜负( isOver( ))
void Game()
{int board[ROW][COL]; // 使用二维数组,定义棋盘memset(board, 0, sizeof(board)); // 初始化二维数组int result = NEXT; // 游戏继续do {showBoard(board, ROW, COL); // 打印棋盘playerMove(board, ROW, COL, PLAYER1); // 用户1 下棋result = isOver(board, ROW, COL); // 判断下了这一手,是否有结果,结果返回if (NEXT != result) // 根据判断后的返回值,判断是否出了结果,是否还需要继续,NEXT 表示继续{break;}showBoard(board, ROW, COL); // 打印棋盘playerMove(board, ROW, COL, PLAYER2); // 用户2 下棋result = isOver(board, ROW, COL); // 判断下了这一手,是否有结果,结果返回if (NEXT != result) // 根据判断后的返回值,判断是否出了结果,是否还需要继续, NEXT 表示继续{break;}} while (1);// 跳出循环,根据返回值,判断该局的,结果是,谁赢,谁输,还是平局switch (result){case PLAYER1:showBoard(board, ROW, COL); // 打印棋盘printf("恭喜用户1,你赢了\n");break;case PLAYER2:showBoard(board, ROW, COL); // 打印棋盘printf("恭喜用户2,你赢了\n");break;case DRAE:showBoard(board, ROW, COL); // 打印棋盘printf("平分秋色,平局\n");break;default: // 不可能会执行到的,这里设置是为了以防万一break;}}
打印棋盘showBoard() 函数
- 首先我们需要清屏,每打印一个新的棋盘,清屏一下,这样体验效果更好,注意我们显示的无论是行号还是列好都是从 1 开始的,所以在打印的过程中需要 +1
- 首先打印两个空格,为打印棋行号,空出位置,更加美观,再打印列号
- 再使用两层循环打印二维数组,显示棋盘,第一层循环打印行号
- 两层循环遍历打印二维数组(显示棋盘),同时判断没有下过的位置以符号==.== 显示,用户1:下过的使用● 显示,用户2:下过的使用○ 显示:
// 打印二维数组
void showBoard(const int board[ROW][COL], const int row, const int col)
{// printf("\e[1;1H\e[2J"); // 清屏system("cls");int i = 0;printf(" "); // 两个空格for (; i < row; i++) // 打印行号{printf("%3d", i+1); // 预留三个位置}printf("\n");for (i = 0; i < row; i++){int j = 0;printf("%2d ",i + 1); // 预留两个位置for (j; j < col; j++){if (0 == board[i][j]) // 没有下过的位置打印 为 .{printf(" . ");} else if (PLAYER1 == board[i][j]) { // 用户1 的显示符号●printf("● ");}else // 不等于,则是用户2 的显示符号 ○{printf("○ "); }}printf("\n");}}
下棋playerMove( )函数
- 使用 static 修饰该函数,封装该函数,让函数只能在该文件内使用,提高代码的可维护性
- 定义两个全局变量,用于保存,赋值输入的坐标位置,
- 判断输入的坐标是否合理:
- 是否超出棋盘的大小,下的位置是否被人下过。
- 注意我们输入的坐标是从 1 下标开始的,而数组是从 0 下标开始的,所以在赋值的过程中需要 -1
- 写成循环,因为有可能输入的坐标不合理,需要重新输入,合理时,赋值坐标到数组中,并退出循环,注意赋值到数组中的值,是该用户所下的,标识数值。在宏中就定义好的
- #define PLAYER1 1 // 定义标识用户 1
#define PLAYER2 2 // 定义标识用户 2
// 下棋
static void playerMove(int board[ROW][COL], const int row, const int col, const int who)
{while (1){printf("player[%d] pleach Enter Your Pos#> ", who); // 提示打印用户谁的输入scanf("%d %d", &x, &y); // 输入坐标// 输入的坐标超出了棋盘,不合法,重新输入if (x < 1 || x > row || y < 1 || y > col){printf("超过棋盘了,请重新输入\n");continue; // 跳过本次循环,重新输入}// 输入的坐标位置,已经被占用了,不合法,重新输入if (0 != board[x-1][y-1]) {printf("pos IsOccupied!\n");continue; // 跳过本次循环,重新输入}// 运行到这,说明该坐标没有问题,可以下入到棋盘中去了board[x - 1][y - 1] = who;break; // 跳出循环}}
判断胜负isOver( )函数
使用 static 修饰该函数,封装该函数,让函数只能在该文件内使用,提高代码的可维护性
定义一个枚举结构用于表示各个方位的数值的标识,如typedef enum Dir
定义一个函数chessCount(board, row, col, LEFT) ,用于计算二维数组中各个方位的上相同的连续出现的数值,返回计算得到的数值,因为在该函数中并没有计算到包含到,本身所下的个数,所以需要额外加上 +1
判断返回的连续出现的数值,是否存在 >=5 的个数,有则存在,五子连珠的情况说明有人赢了,再根据所走这步的,用户是谁,判断是谁,赢了
如果没有五子连珠,则再循环遍历二位数组,是否全部下完了,但凡存在没下的,下完了,则表示棋盘未满,未分出胜负,返回继续下棋,返回值为return NEXT
以上4,5这两种情况都没有出现的话,棋盘满了,未分出胜负,平局,返回值为 return DRAE
枚举类型:表示方位
typedef enum Dir // 枚举 坐标上的方向,注意,枚举以逗号分割开来
{LEFT, // 左边RIGHT, // 右边UP, // 上边DOWN, // 下边LEFT_UP, // 左上边LEFT_DOWN, // 左下边RIGHT_UP, // 右上边RIGHT_DOWN // 右下边// 注意 枚举中的最后一个属性,不要加逗号分隔开,不然会报错的
}Dir;
// 走一步,判断结果
static int isOver(const int board[ROW][COL], const int row, const int col)
{// 从四个位置上判断,可能五子连珠的,可能性,当连续的相同的字符,数量个数为 5 时,表示有一方赢了// 在此基础上都需要加上 1 ,因为本身的位置上的,没有包含计算上,是需要计算上的// 左右横方向上的个数int count1 = chessCount(board, row, col, LEFT) + chessCount(board, row, col, RIGHT) + 1;// 上下纵方向上的个数int count2 = chessCount(board, row, col, UP) + chessCount(board, row, col, DOWN) + 1;// 左斜上方向上的个数int count3 = chessCount(board, row, col, LEFT_DOWN) + chessCount(board, row, col, RIGHT_UP) + 1;// 右斜下方向上的个数int count4 = chessCount(board, row, col, LEFT_UP) + chessCount(board, row, col, RIGHT_DOWN) + 1;// 只要在任意位置上,个数上 >= 5 就,实现了五子连珠,就有获胜了if (count1 >= 5 || count2 >= 5 || count3 >= 5 || count4 >= 5){if (board[x - 1][y - 1] == PLAYER1){return PLAYER1; // 表示用户1 赢了}else{return PLAYER2; //否则就是 表示用户2 赢了}}// 循环遍历二维数组(棋盘),判断棋盘是否存在满了,如果有一个棋位置,还可以下,就表示还可以继续下棋,for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){if (board[i][j] == 0){return NEXT; // 继续,棋盘没有满}}}return DRAE; // 走到这表示棋盘满了,平局}
计算坐标周围连续的个数chessCount( )函数
根据所下的位置判断,是否存在五子连珠 的情况:一共存在四种情况分别是
- 横方向上的 五子连珠
- 纵方向上的五子连珠
- 左斜向下的五子连珠
- 右斜上的五子连珠
注意 :编程中的图形界面上的坐标是与,数学上的坐标是相反的,数学上的,横为 X轴,纵为 Y轴 ,而编程中的是横为 Y轴,纵为 X 轴 ,如下图所示:
根据所传参数中的方位,定义多条分支选择switch() ,作出相应的坐标上的移动,我们需要保留原来的坐标位置用于判断,所以我们需要拷贝复制一份,坐标用于移动,防止丢失原来的坐标位置,因为我们需要计算的是连续的,所以需要写在循环中,
方位上的移动坐标
左边 :y–;
右边:y++;
上边:x++;
下边:x–;
左下边:y–;x–;
左上边:x++;y–;
右上边:y++;x++;
右下边:y++;x–;
- 每移动一个坐标位置,都需要判断该坐标是否,越界了,是否超出了棋盘的范围,超出了,不用计算了,跳出循环
- 在确定移动坐标合理时,再判断该移动的坐标位置上的数值,是否与你所下的位置上的坐标上的数值相等,相等说明连续,计数,不相等,说明不连续,不计数,退出循环
- 退出循环后,返回所计数的结果
- 最后,因为该函数计数时,是没有计算到,包含到,所下位置的本身个数,所以需要额外 + 1
// 计算下的点位置上的,4个方向上的连续字符的 个数,
// 注意编程上的图形界面的坐标是,与数学上的坐标 x,y 是相反的,横坐标为 y, 纵坐标为 x 的
int chessCount(const int board[ROW][COL], const int row, const int col, Dir d)
{int count = 0;int _x = x-1;int _y = y-1; // 拷贝一份坐标,用于移动,防止改变原来的,坐标,// 注意是在数组上的实际坐标,不是你输入的,数组从零开始while (1){switch (d){case LEFT: // 左边_y--;break;case UP: // 上边_x++;break;case DOWN: // 下边_x--;break;case LEFT_DOWN: // 左下_x--;_y--;break;case LEFT_UP: // 左上_x++;_y--;break;case RIGHT: // 右边_y++;break;case RIGHT_DOWN: // 右下_x--;_y++;break;case RIGHT_UP: // 右上_x++;_y++;break;default:break;}// 坐标越界了,跳出循环if (_x < 0 || _x > row - 1 || _y < 0 || -y > col - 1){break;}//if (board[_x][_y] != board[x - 1][y - 1])//{// break; // 表示数组上的数值也就是棋盘上的点,不连续了,不用加加了,跳出循环//}if (board[_x][_y] == board[x - 1][y - 1]){count++; // 说明数组上的数值也就是棋盘上的点,连续,加加计数} else // 否则表示不相等,不连续,跳出循环{break; // 表示数组上的数值也就是棋盘上的点,不连续了,不用加加了,跳出循环}}return count; // 跳出循环,返回在连续的个数
}
所有功能都实现了,可以运行该项目程序了,判断是否存在错误
五子棋完整代码实现
这里采用了分布式文件系统,其中的代码大家只需要,根据对应的文件,复制粘贴内容,就可以了,使用 VS 运行了,注意:不要缺失了,不然,可能无法运行的
game.h
用于存放 :头文件的引入,宏定义,变量,函数的声明,结构体,枚举
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>
#include<string.h>
#include<stdlib.h>#define ROW 15 // 棋盘行数
#define COL 15 // 棋盘列数#define PLAYER1 1 // 定义标识用户 1,
#define PLAYER2 2 // 定义标识用户 2// 棋局中的中情况的定义
#define NEXT 0 // 表示没有结果,继续下棋
#define DRAE 3 // 表示棋盘下满了,平局结束typedef enum Dir // 枚举 坐标上的方向,注意,枚举以逗号分割开来
{LEFT, // 左边RIGHT, // 右边UP, // 上边DOWN, // 下边LEFT_UP, // 左上边LEFT_DOWN, // 左下边RIGHT_UP, // 右上边RIGHT_DOWN // 右下边// 注意 枚举中的最后一个属性,不要加逗号分隔开,不然会报错的
}Dir;extern void menc(); // 打印游戏菜单
extern void Game(); // 进入游戏
extern void playerMove(int board[ROW][COL], const int row, const int col, const int who); // 下棋
extern int isOver(const int board[ROW][COL], const int row, const int col); // 判断下一步后的,结果
extern int chessCount(const int board[ROW][COL], const int row, const int col, Dir d); // 计算,连续出现相同的个数,从而判断是否有五子连珠
extern void showBoard(const int board[ROW][COL], const int row, const int col); // 打印二维数组,棋盘
game.c
存放五子棋中对应功能实现的函数
#include "game.h"int x = 0; // 定义全局变量,X 坐标
int y = 0; // 定义全局变量,y 坐标void menc() // 游戏菜单
{printf("#########################\n");printf("### 1.paly 0.Exot ###\n");printf("##### Please Select #####\n");printf("#########################\n");}void Game()
{int board[ROW][COL]; // 使用二维数组,定义棋盘memset(board, 0, sizeof(board)); // 初始化二维数组int result = NEXT; // 游戏继续do {showBoard(board, ROW, COL); // 打印棋盘playerMove(board, ROW, COL, PLAYER1); // 用户1 下棋result = isOver(board, ROW, COL); // 判断下了这一手,是否有结果,结果返回if (NEXT != result) // 根据判断后的返回值,判断是否出了结果,是否还需要继续,NEXT 表示继续{break;}showBoard(board, ROW, COL); // 打印棋盘playerMove(board, ROW, COL, PLAYER2); // 用户2 下棋result = isOver(board, ROW, COL); // 判断下了这一手,是否有结果,结果返回if (NEXT != result) // 根据判断后的返回值,判断是否出了结果,是否还需要继续, NEXT 表示继续{break;}} while (1);// 跳出循环,根据返回值,判断该局的,结果是,谁赢,谁输,还是平局switch (result){case PLAYER1:showBoard(board, ROW, COL); // 打印棋盘printf("恭喜用户1,你赢了\n");break;case PLAYER2:showBoard(board, ROW, COL); // 打印棋盘printf("恭喜用户2,你赢了\n");break;case DRAE:showBoard(board, ROW, COL); // 打印棋盘printf("平分秋色,平局\n");break;default: // 不可能会执行到的,这里设置是为了以防万一break;}}// 下棋
static void playerMove(int board[ROW][COL], const int row, const int col, const int who)
{while (1){printf("player[%d] pleach Enter Your Pos#> ", who); // 提示打印用户谁的输入scanf("%d %d", &x, &y); // 输入坐标// 输入的坐标超出了棋盘,不合法,重新输入if (x < 1 || x > row || y < 1 || y > col){printf("超过棋盘了,请重新输入\n");continue; // 跳过本次循环,重新输入}// 输入的坐标位置,已经被占用了,不合法,重新输入if (0 != board[x-1][y-1]) {printf("pos IsOccupied!\n");continue; // 跳过本次循环,重新输入}// 运行到这,说明该坐标没有问题,可以下入到棋盘中去了board[x - 1][y - 1] = who;break; // 跳出循环}}// 走一步,判断结果
static int isOver(const int board[ROW][COL], const int row, const int col)
{// 从四个位置上判断,可能五子连珠的,可能性,当连续的相同的字符,数量个数为 5 时,表示有一方赢了// 在此基础上都需要加上 1 ,因为本身的位置上的,没有包含计算上,是需要计算上的// 左右横方向上的个数int count1 = chessCount(board, row, col, LEFT) + chessCount(board, row, col, RIGHT) + 1;// 上下纵方向上的个数int count2 = chessCount(board, row, col, UP) + chessCount(board, row, col, DOWN) + 1;// 左斜上方向上的个数int count3 = chessCount(board, row, col, LEFT_DOWN) + chessCount(board, row, col, RIGHT_UP) + 1;// 右斜下方向上的个数int count4 = chessCount(board, row, col, LEFT_UP) + chessCount(board, row, col, RIGHT_DOWN) + 1;// 只要在任意位置上,个数上 >= 5 就,实现了五子连珠,就有获胜了if (count1 >= 5 || count2 >= 5 || count3 >= 5 || count4 >= 5){if (board[x - 1][y - 1] == PLAYER1){return PLAYER1; // 表示用户1 赢了}else{return PLAYER2; //否则就是 表示用户2 赢了}}// 循环遍历二维数组(棋盘),判断棋盘是否存在满了,如果有一个棋位置,还可以下,就表示还可以继续下棋,for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){if (board[i][j] == 0){return NEXT; // 继续,棋盘没有满}}}return DRAE; // 走到这表示棋盘满了,平局}// 计算下的点位置上的,4个方向上的连续字符的 个数,
// 注意编程上的图形界面的坐标是,与数学上的坐标 x,y 是相反的,横坐标为 y, 纵坐标为 x 的
int chessCount(const int board[ROW][COL], const int row, const int col, Dir d)
{int count = 0;int _x = x-1;int _y = y-1; // 拷贝一份坐标,用于移动,防止改变原来的,坐标,// 注意是在数组上的实际坐标,不是你输入的,数组从零开始while (1){switch (d){case LEFT: // 左边_y--;break;case UP: // 上边_x++;break;case DOWN: // 下边_x--;break;case LEFT_DOWN: // 左下_x--;_y--;break;case LEFT_UP: // 左上_x++;_y--;break;case RIGHT: // 右边_y++;break;case RIGHT_DOWN: // 右下_x--;_y++;break;case RIGHT_UP: // 右上_x++;_y++;break;default:break;}// 坐标越界了,跳出循环if (_x < 0 || _x > row - 1 || _y < 0 || -y > col - 1){break;}//if (board[_x][_y] != board[x - 1][y - 1])//{// break; // 表示数组上的数值也就是棋盘上的点,不连续了,不用加加了,跳出循环//}if (board[_x][_y] == board[x - 1][y - 1]){count++; // 说明数组上的数值也就是棋盘上的点,连续,加加计数} else // 否则表示不相等,不连续,跳出循环{break; // 表示数组上的数值也就是棋盘上的点,不连续了,不用加加了,跳出循环}}return count; // 跳出循环,返回在连续的个数
}// 打印二维数组
void showBoard(const int board[ROW][COL], const int row, const int col)
{// printf("\e[1;1H\e[2J"); // 清屏system("cls");int i = 0;printf(" "); // 两个空格for (; i < row; i++) // 打印行号{printf("%3d", i+1); // 预留三个位置}printf("\n");for (i = 0; i < row; i++){int j = 0;printf("%2d ",i + 1); // 预留两个位置for (j; j < col; j++){if (0 == board[i][j]) // 没有下过的位置打印 为 .{printf(" . ");} else if (PLAYER1 == board[i][j]) { // 用户1 的显示符号●printf("● ");}else // 不等于,则是用户2 的显示符号 ○{printf("○ "); }}printf("\n");}}
test.c
main 函数的所在文件,用于测试五子棋,是否存在错误,因为有关代码封装的比较好,所以在该main 函数中代码量并不多。
// #define _CRT_SECURE_NO_WARNINGS 1#include"game.h"int main()
{int quit = 0; // 定义一个标识,用于循环条件的退出int select = 0; // 对应功能上的选择while (!quit){menc();printf("请输入你的选择: > ");scanf("%d", &select); // 选择游戏模式switch (select){case 1:Game(); // 进去游戏break;case 0:quit = 1; // 通过改变循环条件,跳出循环,结束游戏printf("ByeBye!ln\n");break;default: // 选择错误重新选择printf("Enter Error , Try Again!!! \n");break;}}return 0;
}
这便是五子棋实现的所有代码,运行看看
最后:
限于自身水平,其中存在的错误,希望大家给予指教,韩信点兵——多多益善,谢谢大家,后会有期,江湖再见!
人与人之间的单机五子棋 —— C语言实现相关推荐
- 人与动物之间有没有一条不可逾越的鸿沟?——从基础存在论到生命哲学
来源:<哲学动态> 2018年第12期作者:舒红跃(湖北大学哲学学院)张哲(湖北省道德与文明研究中心) 海德格尔<存在与时间>中对"此在"的生存论刻画是哲学 ...
- 人与人之间关系的随想
注意:本文包含若干软件开发术语. 写之前,刚好有个朋友提醒我,老外不这样.所以,我这里所写的,仅限我对中国大陆地区(特别是北方)人与人之间关系的一些不成熟的想法. 人和人之间相处,经常会产生各种问题. ...
- 人之间的尊重是相互的_人与人之间的感情,最基本的是相互尊重
有很多人就是靠一些冒犯别人的办法来刷自己的存在感,但很多时候,这样的人刷着刷着就把自己刷没了.有的感情,自己很看重,别人却不当回事:人与人之间的感情,最基本的是相互尊重. 有的感情,自己很看重,别人却 ...
- 人与人之间交往最重要的是什么?
真诚,就是待人真心实意. 真诚,就是对人说真话,吐真情,对人满腔热情,真心实意,毫无矫揉造作,毫无虚情假意. 真诚,就是与人交往中相信人,信任人,对人满怀信心,坦坦荡荡,不疑神疑鬼,不遮遮掩掩. 真诚 ...
- 人之间的尊重是相互的_人与人之间,尊重很重要
问题:怎样才能每天免费收到这种文章呢? 答案:只需要点击上方蓝字<鸡汤心语>关注即可! 人与人之间,尊重是相互的 心与心相交,尊重是必须的 尊重,是一个人教养 体现在做人做事 尊重,是一 ...
- 人之间的尊重是相互的_人与人之间要学会相互尊重
偶然间想说说人与人之间相互尊重的话题,因为,在当今社会中,真有那么一大部分人不懂得如何去尊重别人或不懂得相互尊重,在人与人之间相处的范围中产生了一定的影响.所以,仅就人与人之间是否需要尊重说说个人的态 ...
- 思维方式-《终身成长》书中的精髓:决定人与人之间巨大差距的,是你的思维模式。
<终身成长>书中的精髓:决定人与人之间巨大差距的,是你的思维模式. 有些朋友可能觉得智商.情商和财富才是人与人之间差距所在,不过别急,请听我讲一个故事. 大家都知道迈克尔·乔丹,他是有史以 ...
- 神州优车粗暴裁员:人与人之间最起码的尊重呢?
年底了,又有一些企业开始想着怎么"优化"人员结构还不用"安抚"员工了. 这是一段神州优车 HR 小姐姐与试用期即将满 6 个月的员工.在工位上展开的一段对话视频 ...
- 人之间的尊重是相互的_人与人之间彼此尊重是相互的,你若敬我一尺,我必敬你一丈...
01 静坐常思己过,闲谈莫论人非,当你不开心的时候,想想自己还剩下多少天可以折腾,还有多少时间够你作践.你开心,这一天过了:不开心,一天也过了.想明白了,你就再也不会生气了. 02 当你烦恼的时候,想 ...
最新文章
- 《VMware Virtual SAN权威指南》一2.2 VSAN的要求
- java hashmapconcurrentHashmap源理
- boost::edge_coloring用法的测试程序
- sql 2008 使用output避免数据修改后的二次查询
- django模型查询_如何在Django中编写有效的视图,模型和查询
- 数据结构与算法之七归并排序
- javaWeb:相关监听方法汇总
- mybatis 实现查询商品列表的分页
- 视频教程-SQL语句视频课程(进阶版)-Oracle
- 使用OpenGL绘制shp文件
- PhotoShop简单案例(4)——利用ps制作正在加载中动画(loading.gif)
- 微软和美国航空航天局(NASA)强强联手,推出Python免费课程
- 国内及国际公共DNS收录
- 立创开源 | 基于555定时器的电子琴设计
- Windows上搭建PHP开发环境
- 敏捷迭代管理 --需求变更规范
- 一只小白,在学习delphi.感觉很吃力。。
- 图像数据增强及其对应的标签扩充
- 安卓 网络工具_小米公布MIUI适配计划,支持10台机型升级安卓Q,9款今年内测
- IP地址分类及子网掩码划分网段详解!!!
热门文章
- android fun os,vivo也要吃上奥利奥!FuntouchOS宣布Android Oreo机型适配列表
- 王者荣耀s20赛季服务器维护,王者荣耀s20赛季开启时间 王者荣耀s20赛季段位继承规则及赛季皮肤...
- 谈谈浏览器的缓存过期时间
- 什么是electron?
- 四川数字经济发展分析:四川21市州数字经济发展活跃度解密
- Unity中左手坐标系的四元数转右手坐标系中的四元数
- duo是什么意思_吃鸡上面duo是什么意思 | 手游网游页游攻略大全
- HashMap 分析
- java swarm有什么用,Docker Swarm的使用总结
- 阴阳师哪些服务器可以跨系统转移,《阴阳师》跨系统角色转移攻略